-
Javascript介绍
浏览器(网页)
手机号
email
固定电话
地址
身份证 xxx
…
|
提交
|
后台(校验)跳转(jsp)IE
chrome
safari
firefoxJava
语法 sun
解释器 jdk sunJavascript
网景 firefox script
解释器
语法
IE script
解释器
语法
…网易严选 脚本 校验登录页面 ECAMA
-
Javascript组成
ECMAScript5(javascript语法标准)
js标准语法
注释
变量
操作符
操作数
表达式
语句
数组
函数
对象
…
var a = 10;
【lodash.js】DOM (document object model)
js操作html
文档浏览器
var dom = document.getElementById("");
dom.onclick = function(){}
dom.addEventListener(function(){})【jQuery】 ie低版本 ie+
BOM (browser object model)
js操作浏览器
alert();
setInterval()
setTimeout()
getClientX
window.history
… -
js解释器
-
在所有的主流浏览器中都具备js解释器
js -> 浏览器(客户端) -
google chrome
google v8引擎(js解释器)-> nodeJS
nodejs -> linux,unix,windows,macos
js不仅仅可以运行在浏览器端,还可以运行在服务器端js运行在浏览器端:动画,表单验证,ajax数据交互…
js运行在服务器端:js转换,代码编译,操作数据库,流,网络,iot
-
-
js学习方式
ECMAScript
所有浏览器,所有的js解释器(nodejs)
linux(ubuntu16.04) + nodejsjs语言特性
解释性语言
js -> nodejs编写代码 vim 执行行吗 nodejs 编译型语言 java - .class -> jdk -> linux c - .out -> linux
-
hello world
- 创建一个文件
hello.js - 编写文件
function sayHello(){
console.log(“hello world”);
}
sayHello(); - 执行代码
$ node hello.js
console.log(a,b,c);
将a,b,c变量的内容打印到控制台中 - 创建一个文件
-
变量
强类型
变量的数据类型取决于变量的声明
int a = 3;
a是个整数类型,由于int a ;
a = true;
以上表达式不允许,因为a是一个整数类型,不能赋值为布尔类型弱类型
变量的数据类型取决于值的类
var a ; // 变量的声明
a = 3 ; // 变量的初始化
=>
var a = 3; //变量的声明与初始化一起a是个数字类型,由于a = 3; a = true; a变成类布尔类型
变量声明
var a;
var str;变量初始化
a = true;
str = 1;
str = “1”;变量的使用
a + 1 ;变量类型
基本数据类型
数字类型 number
var a = 3;
var a = 3.0;
var a = 011;
var a = 0x11;
…
字符串类型 string
var str = “hello world”;
var str = ‘hello’;
var str = ‘{“name”:“terry”}’
布尔类型 boolean
var b = true;
var b = false;
null object
一般表示空对象
var a = null;
undefined
var a; // undefined
var a = undefined; //undefined检测数据类型 var a = 3; typeof a isNaN(result) 3/"a" 如果result是NaN,那么这个函数返回true isFinite(result) 如果result是一个有穷数,返回true 3/0 => inFinite 无穷数 引用数据类型 数组 var arr = [1,2,3,4,5,6]; var names = ["terry","larry","tom"] 函数 function sayHello(){ console.log(); } 对象 var p = { name:"terry", age:21, gf:null } 正则表达式 基本数据类型与引用数据类型在内存中的表示 基本 var a = "terry"; 引用 var b = { name:"terry", age:12, gender:"male" } 基本数据类型的值保存在栈区;引用数据类型的引用地址保存在栈区,内容保存在堆区
-
操作符
-
算术操作符
-
+=
-
-=
-
*=
/ /=
% %= -
-
赋值操作符
var result = 1 + 2;result += 3;
等价于>
result = result + 3;将1+2这个表达式的运算结果赋值给result
-
一元运算符
++ 自增
– 自减
前置:先自增、减再参与其他运算
后置:先参与其他运算,再自增、自减
var a = 3;
var b = 1;
var result = ++a+b++;++a; // a = 4; a+b // result 5; b++ // b = 2;
- var a =3 ;
+a;
将其他数据类型转换为数字类型
+true //1
+‘11’ //11
- -a;
将其他数据类型转换为数字类型
-(-true) //1
-(-‘11’) //11
- var a =3 ;
-
逻辑运算符
短路运算符【返回结果不一定是boolean】
&&
当第一个表达式为假的时候,不再计算第二个表达式,整个表达式的结果由第一个表达式来决定,因此会返回第一个表达式的运算结果var age = 12; gender = "male" age>18 && gender == 'male' // false "hello" && 1 //1
||
当第一个表达式为真的时候,整个表达式的结果就为真,不再计算第二个表达式。返回第一个表达式
null || “hello” //“hello”!
!false // true
!true // false
!3 // false将其他数据类型转换为boolean !!3 // true
-
比较运算符(比较栈区的值)【返回类型为Boolean】
!=
比较值
‘11’ == 11 // true
比较对象的时候比较的是对象的引用!==
先比较数据类型,如果数据类型不一致,会直接返回false,如果数据类型一致,再比较值
‘11’ === 11 // false=
<
<= -
三目运算符
exp1 ? exp2 : exp3
当exp1为真,返回exp2,否则返回exp3var result = age > 18 ? “成年人” : “未成年人”
==>
var result;
if(age > 18){
result = “成年人”;
} else {
result = “未成年人”
}
#7) 位运算符(number,先将number转换二进制再运算)
异或 ^
位与 &
3 & 4
位或 |
&& 与 & 的区别? -
拼接运算符
当使用 “+” ,操作数中出现了字符串,那么就肯定是拼接运算
-
-
类型转换
null undefined "" 0 NaN
boolean false false false false false
string ‘null’ ‘undefined’ ‘’ ‘0’
number转换方式:
其他数据类型转换为boolean
!!v
Boolean(v)
其他数据类型转换为string
v+""
String(v);
v.toString(); //null与undefined除外
其他数据类型转换为number
+v
-(-v)
Number();parseInt(); parseFloat(); 解析字符串为整数int、是浮点数float
自动装箱
int a = 13; -
流程控制语句
-
分支语句
if(w == ‘下雨’){
console.log(“带伞出门”);
}if(age > 18){
console.log(“成年人”);
} else {
console.log(“未成年人”);
}var day = 1;
if(day == 1){
console.log(“周一”);
} else if (day == 2){
console.log(“周二”);
} else if (day == 3){
console.log(“周三”);
} else if(day == 4){
console.log(“周四”);
} else {
console.log(“周末”);
}switch(day){
case 1:
console.log(“周一”);
break;
case 2:
console.log(“周二”);
break;
…
default:
console.log(“周末”);}
作业:(使用if-else / 使用switch-case)
根据变量day的值,打印对应内容
1 今天是周一
2 今天是周二
…
6,7 今天是周末if( exp1 ){
exp2
}
当exp1为真的时候,执行exp2
if(exp1){
exp2
} else if(exp3){
exp4
} else {
exp5
}
当exp1为真,执行exp2,否则如果exp3为真执行exp4,否则z执行exp5var day = 1;
switch(day){
case 常量1:
// 代码1
break;
case 常量2:
// 代码2
break;
…
default:
// 代码d
}
day === 常量1 ,如果为真,执行代码1,当遇到break,跳出switch代码块,结束运行;如果为假,继续判断 day===常量2, -
循环语句
三要素:初始化条件,结束判定条件,迭代-
for循环语句
for(初始化条件; 结束判定条件; 迭代){
循环体
}
计算出1到100累加的和
1+2+3+4+…+100
初始化 i = 1;
结束判定 i<=100
迭代 i++var result = 0;
for(var i=1; i<=100; i++){
result += i;
}var i = 1;
i <= 100; true
result = 0 + 1; result = 1;
i++ i = 2;i<=100 true
result = 1 + 2 result = 3;
i++ i = 3;i<=100 true
result = 3 + 3 result 6
i++ i = 4…
i++ i = 100i<=100 true
result = x + 100 result
i++ i = 101i<=100 false 结束循环
-
前置判断循环 while循环
初始化条件
while(结束判定条件){
循环体
迭代
}var result = 0;
var i = 1;
while(i<=100){
result += i++;
} -
后置判断循环 do-while循环
初始化条件
do {
//循环体
迭代
} while(结束判定条件);
使用for循环打印出99乘法表中的第8行
形式一:
11 = 1
…
18 = 8 28 = 16 38 = 24 … 8*8 = 64形式二:
18 = 8 28 = 16 38 = 24 … 88 = 64
…
1*1 = 1形式三:
1*1 = 1 ...
18 = 8 28 = 16 38 = 24 … 88 = 64
形式四:
18 = 8 28 = 16 38 = 24 … 88 = 64
…
1*1 = 1 -
-
-
对象
-
介绍
复杂的数据类型,引用数据类型,一般情况下,对象中包含了多个属性和方法。 -
对象创建方式
-
对象字面量
对象使用"{}“作为边界,对象是由多个属性(方法是一种特殊的属性)来组成,每个属性之间通过”,“分割,属性名与属性值之间通过”:"分割。属性名可以不使用双引号,当属性名中包含特殊字符一定使用双引号,属性值一般为常量或者具体的值,也可以变量var obj = {
name:“terry”,
age:12,
sayName:function(){}
};
-
使用构造函数构建对象
var obj = new Object();
obj.name = “terry”;
obj.age = 12;
=>
var obj = {};
obj.name = “terry”;
obj.age = 12;
…
var obj = {};
Object是所有对象的根对象,一个普通对象都会直接间接的继承Object
-
-
属性的访问:
点访问符
对象名.属性名
obj.name
中括号访问符
var name = “name”;
obj[name]
=>
obj[“name”] -
所有的对象直接或者间接的继承Object,也就是说所有的对象都可以调用Object原型中的方法和属性。
Object.prototype.xxxconstructor 构造函数,谁创建了当前对象
hasOwnProperty(prop) 判断某个属性是否属于当前对象的自有属性
propertyIsEnumerable(prop) 检测某个属性是否可以被枚举
isPrototypeOf(prop) 检测某个属性是否是原型链中的属性
toString(); 返回该对象的字符串描述信息
valueOf(); 返回该对象的数字描述信息 -
删除属性
delete obj1.name -
对象序列化和返序列化
var obj = {name:“terry”};将js对象转换为json字符串
var json = JSON.stringify(obj)将json字符串转换js对象
var obj = JSON.parse(json); -
对象的遍历
var obj = {
name:“terry”,
age:12
}
var arr = [“terry”,“larry”];for(var key in obj){
//如何获取属性值
var value = obj[key]
}obj可以为对象或者数组;key表示对象的属性名或者是数组的索引;在运行的时候,每次从obj中获取一个属性名或者索引赋值给key,然后执行循环体,循环…
-
in关键字
prop in obj
检测prop是否可以被obj调用
-
-
函数(方法)
-
函数的用处
- 使用函数封装某些功能代码,执行特定功能
arr.sort() 排序
arr.reverse() 数组反转
jQuery() 调用jquery函数完成特定功能
… - 使用函数封装创建对象的模板【构造函数】面向对象
- 使用函数封装某些功能代码,执行特定功能
-
函数的使用(功能)
2.1 函数的定义
1) 函数声明
function 函数名(形参) {
函数体
}
2) 函数表达式
var 函数名 = function(形参){} sayHello(); var sayHello = function(){ } console.log(a); var a = 3;
2.2 函数的调用
函数名(实参)
函数名.call(this,实参列表);
函数名.apply(this,实参数组); -
函数声明会提升
如果一个函数使用函数声明的方式来定义,那么在函数定义之前就可以调用该函数
s -
函数的作用域
如果一个变量声明在函数中,那么这个变量只能在函数中访问,当函数执行完毕后,这个变量就会被释放掉。nodejs ECMAScript(var)
var不存在局部作用域
function foo(){
if(true){
// 局部作用域,a只能在当前代码块生效
var a = 3;
}
console.log(a);
}如果该代码运行在nodejs中,a访问不到,但是如果运行在浏览器中,a的值为3。
5)函数内部属性
只能在函数运行的时候才能确定的属性,只能在函数内部访问。
function add(a,b){
var result = a + b;
return result;
}
add(32,22,19);1. 形参 a,b 接受实参的快捷方式 a:32 b:22 2. arguments 接受实参的真正所在,类数组对象 arguments:{ 0:32, 1:22, 2:10, length:3 } 课堂作业:计算任意个人的数值相加 3. this 当前对象(环境对象) 如何判断this的值为谁: this的取值与该函数的调用方式有关 1) 如果函数使用"()"来调用,那看一下括号前面是不是函数名,如果是,看函数名前面有没有对象,如果有,this指向该对象,否则指向全局对象(window/global) 2) 如果通过call,apply来调用,this为用户手动指向的那么对象 foo() p1.sayName() p2.sayName() 课堂作用: var p1 = { name:"terry", age:12, sayName:foo } var p2 = { name:"larry", age :12, sayName:foo } // 当执行p1.sayName()打印“hello my name is terry”,执行p2.sayName()打印“hello my name is larry”,foo函数如何定义 function foo(){ console.log("hello my name is "+this.name); }
-
值传递和引用传递
var a = 3;
var b = a; //b 为3 值拷贝b++
console.log(a);var a = {name:“terry”,age:12};
var b = a; // a为指针,b为指针 引用拷贝b.age++;
console.log(a.age);
-
-
数组
-
作用
存放多个数据的集合;数组的边界"[]",数组的组成称为元素,元素与元素之间通过逗号隔开,元素的数据类型没有限制,
-
定义方式
-
数组字面量
var name = “terry”
var arr = [name,1,true,“hello”,null,{name:“s”},function(){}]; -
构造函数 Array
Array 继承 Object
通过Array构造函数构建出来的对象可以调用Array原型中的方法,还可以调用Object原型中的方法var arr = new Array();
var arr = new Array(length);
var arr = new Array(item1,item2,…);arr ->Array.prototype-> Object.prototype
-
-
数组访问方式
中括号访问符,索引从0开始,如果指定索引的位置没有值,返回undefined数组名[索引]
var arr = [3,12,5,3];
arr[1]+=1;var obj = {
name:“terry”,
age:12,
sayHello:function(){}
}
obj.sayHello();
var arr = [
“terry”,
12,
function(){}
]
arr2
=>
var arr = {
“0”:“terry”,
“1”:12
}
arr[“0”]
-
数组内存
var arr = [“terry”,12,[1,2,3]];arr是变量,保存在栈区
arr是引用数据类型的变量,栈区保存的引用地址,数组的值保存在堆区var arr = [“terry”,12,{name:“terry”,age:12}];
var a = arr[1];
a++;
console.log(arr[1]); //12var b = arr[2]
b.age++;
console.log(arr[2].age); //13 -
数组的属性
数组也是一种对象,length是表示数组长度的属性,length表示数组中元素的个数 -
数组的遍历(循环遍历索引)
var arr = [1,2,3,4,5];- 使用for循环
for(var i = 0 ; i<arr.length; i++){
var val =arr[i]
console.log(val);
} - 使用while
- 使用do-while
- 使用增强for循环
for(var key in arr){
var val = arr[key]
}
- 使用for循环
-
数组相关的API
var obj = new Object();
var arr = new Array();Array() 构造函数(类)
arr 实例(对象)
实例可以调用构造函数原型中的方法Array === Array.prototype.constructor
你 === 你男朋友的女朋友api
含义; 参数; 返回值;1) 添加元素移除元素相关【改变原值】
push(p1,p2,…); 入栈,在数组的最后添加一个元素
参数:要入栈的元素
返回值:数组长度
pop(); 出栈,从数组的最后取出一个元素
参数:none
返回值: 出栈的元素1. 对原值进行改变 arr = [1,2,3]; arr.push(4); shift(); 出队,将数组中第一个元素取出来 参数:none 返回值:出队的元素 unshift(p1,p2,...); 插队,将元素插入在数组的最前面 参数:要插队的元素 返回值:插队后队列的长度
-
排序方法【改变原值】
sort()
按照字符在字符编码表中出现的位置进行排序
3,12,29,8,32,4
=》
12, 29, 3, 32, 4, 8
sort(comparator)
comparator为一个比较器函数,函数可以接受两个值a,b;当a位于b之前的时候返回 -
序列化方法
toString()
将数组转换为字符串,数组中的元素通过逗号连接
join(v)
将数组转换为字符串,数组中的元素通过v连接
JSON.stringify();
将数组转换为JSON字符串
arr -> Array.prototype -> Object.prototype
var arr = [“terry”,“larry”]
arr.toString();
Array.prototype
Object.prototype让Object.prototype中的toString转换arr
=>
[“terry”,“larry”].toString(); -
截取方法
concat() 【不改变原值】
将参数中的数组和当前数组合并为一个数组
参数:多个数组
返回值:合并后的数组
slice(begin,end)【不改变原值】
从当前数组中截取一个子数组并且范围
参数:begin 起始位置;end 结束位置
返回值:截取到的子数组
splice(begin,delete[,p1,p2,…])【改变原值】
从数组中删除、插入、更新元素
参数:
begin
起始位置(删除,插入)
delete
删除的个数
p1,p2,…
插入的值
返回值:
删除的元素组成的数组
var arr = [1,2,3,4,5];
arr.splice(1,3,9,9,9) -
迭代方法
forEach(function(item,index,arr){})
遍历当前数组
参数:function(item,index,arr){}
每次遍历一次,这个匿名函数就会被调用一次,forEach将当前遍历的元素,索引,当前数组当做实参传递个这个匿名函数
every(function(item,index,arr){})
判断数组中所有的元素是否满足回调函数中给定的条件
参数:function(item,index,arr){}
当每次回调函数返回值为true,every方法的结果为true,
当回调函数返回值为false,every方法的结果就为false
some(function(item,index,arr){})
判断数组中是否有满足条件的元素
参数:function(item,index,arr){}
当回调函数返回true,some方法的结果就为true
当每次回调函数返回false,some方法的结果才为falses
filter(function(item,index,arr){})
参数:function(item,index,arr){}
当回调函数返回true,当前元素就会被添加到返回值数组中
返回值:数组
map(function(item,index,arr){})
参数:function(item,index,arr){}
回调函数可以返回任意类型的值,这些值都会被添加到map方法的返回值数组中
返回值:数组
- 查找方法
indexOf()
lastIndexOf()
-
-
-
回调函数
函数调用
a 调用 b环境a
获取b在执行过程中、执行完毕的结果实时反馈 回调函数 最终反馈 return
-
包装器类型
Number
BooleanString
String.prototype.xxx
length
获取字符串中字数的数量
charAt(index)
获取指定索引处的字符
charCodeAt(index)
获取指定索引处的字符编码
indexOf()
获取指定字符在字符串中索引
lastIndexOf();
获取指定字符在字符串中的索引,【从后往前】
concat()
连接两个字符串
slice(begin,end)
截取子字符串,begin开始位置,end结束位置,不包含结束位置
substring(begin,end)
截取子字符串,begin开始位置,end结束位置,不包含结束位置
substr(begin,length)
截取子字符串,begin开始位置,length截取的字符的个数
trim()
删除字符串左右两边的空格
" 112233 "
toUpperCase()
转换为大小
toLowerCase()
转换为小写对正则表达式支持的方法 search(regexp) 测试,类似于test(),不支持global 返回值匹配内容的索引 match(regexp) 查找匹配的内容 返回值数组,保存了匹配的内容 replace(regexp,xx) split(regexp)
-
Math对象
Math.min(1,2,3,4,5) //1
Math.max(1,2,3,4,5); //5
Math.random();
获取0~1之间的随机小数
Math.round();
四舍五入
Math.ceil()
向上舍入
Math.floor()
向下舍入
Math.tan() -
函数维护在哪里
对象
var Math = {
foo:function(){},
bar:function(){}
}Math.foo();
构造函数的原型
Object/Array/RegExpArray.prototype.foo = function(){} Array.prototype.bar = function(){} var arr = new Array(); arr.foo(); arr.bar();
-
正则表达式
RegExp 构造函数-
实例化正则表达式对象
-
构造函数模式
var pattern = new RegExp(“正则表达式”,“模式”);
var pattern = new RegExp("[0-9]{4}-[0-9]{7}",“g”) -
正则表达式字面量
var pattern = /正则表达式/模式
var pattern = /[0-9]{4}-[0-9]{7}/gim
-
-
正则表达式
[0-9]{4}-[0-9]{7}
0351-5510110-
字符类
. 匹配任何单个字符
\d 匹配任意数字,等价于[0-9]
[0-9] 匹配中扩展任意一个字
[0123456789]
\D 匹配任意非数字
[^0-9] 等价于\D,上箭头在中括号中表示非
1 表示任意一个数字作为一行的开始
\w 字符,等价于[a-zA-Z0-9_]
[a-zA-Z0-9_]
\W 非字符,等价于[^a-zA-Z0-9_]
\s 空白字符,tab,return,space…
\S 非空白字符 -
分组
/[a-z][0-9]/ig
匹配一个字符后拼接一个数字
a1
o2
d3/([a-z])([0-9])/ig
匹配一个字符后拼接一个数字,分组匹配字符,分组匹配数字
a1 a 1
o2 o 2
d3 d 3a1hello2world3
-
数量词
exp{3} 将前面的表达式匹配3次
exp{3,5} 将前面的表达式匹配3~5次
exp{3,} 将前面的表达式匹配3+次
exp* 将前面的表达式匹配0次或多次
exp+ 将前面的表达式匹配1次或多次
exp? 将前面的表达式匹配0次或1次贪婪匹配(默认情况下)
/\d{2,}/
尽可能多的匹配
var str = “abc123456789”
=>123456789非贪婪匹配
/\d{2,}?/
尽可能多的匹配
var str = “abc123456789”
=>12\d{3}
[0-9]{3}
-
-
模式
i ignoreCase
g global
m multiline -
引用
属性
lastIndex
如果模式中包含g,每次执行test或者exec的时候,都会维护这个属性,下一次搜索开始的位置;如果模式中不包含g,lastIndex为0
ignoreCase
如果模式中包含i,返回true
global
如果模式中包含g,返回true
multiline
如果模式中包含m,返回true
source
正则表达式的字符串表示
flags
正则表达式模式的字符串表示方法
test(str)
使用正则表达式对象测试str,如果str满足正则表达式返回true,否则返回false
exec(str)
从str中查找出满足正则表达式的字符串
返回值:类数组对象
[
匹配的内容
index,匹配的内容所在的索引位置
input,输入信息]
var str = “briup telephone is 0512-5511000, baidu telephone is 0100-5518888.”
-
js中内置函数有哪些?
内置构造函数
Object
Array
内置函数
Math.random()
…
静态网页的部署地址为:http://134.175.154.93:80/lianjia,svn服务器的地址为:svn://134.175.154.93/web1902/group0,ftp服务的地址为 ftp://134.175.154.93:22/
url统一资源定位符
协议://ip:port/path
1) 获取所有的url
2) 分别获取每个url的 协议,ip,port,path
跑腿小张
function buyWater(money) {
var result ;
switch(money){
case 2.5:
result = “农夫山泉”;
break;
case 3:
result = “百事可乐”;
break;
case 5.5"
result = “红牛”
break;
default:
result = “水”
}
return result;
}
var obj = {
name:“跑腿小张”,
age:22,
gender:“男”,
buyWater:buyWater
}
obj.buyWater();
表达式 = 操作符 + 操作数
以下那个是css的注释
<!---->
//
/**/
/** */
设计出来一个开发语言,类似javascript
语法
解释器
系统库
1. 循环语句
for() - 99乘法表 -》document.write (dom)
while(){}
do{ }while();
2. 对象
定义
创建方式
对象字面量
{k:v,k:v}
构造函数
new Object()
访问方式
.
["k"]
[k]
删除
delete obj.k
Object
原型 constructor,hasOwnproperty,...
json序列化
日期序列化
课堂作业:
定义一个函数,sayHello,打印出,hello world
function sayHello(){
console.log(“hello world”);
}
将该函数赋值给一个变量,通过该变量调用这个函数
var foo = sayHello();
foo();
将该函数赋值给一个对象中的属性,通过该对象调用该函数
var obj = {
foo:foo
}
obj.foo();
编写代码
模拟push,重构myPush代码
var arr = [];
arr.push()
arr.myPush()
function myPush(){
}
模拟pop,重构myPop代码
模拟shift,重构myShift代码
模拟unShift,重构myShift代码
模拟sort,重构myShift代码【选做】
排序算法???
......
排序
var students = [{
id:1,
name:"terry",
age:12,
grade:89
},{
id:3,
name:"larry",
age:9,
grade:92
},{
id:2,
name:"tom",
age:13,
grade:99
},{
id:4,
name:"jacky",
age:11,
grade:85
}]
最少代码,完成可以自由选择按照id/name/age/grade来升序或者降序排列
students.sort(handler())
问:
handler()这个方法如何设计???
function handler(key){
//返回比较器函数
return function(a,b){
if(a[key] > b[key]){
return 1;
} else {
return -1;
}
}
}
var prop = "age";
students.sort(handler(prop));
console.log(students);
0-9 ↩︎