javascript的参考文档:
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
新增类型
Set
和其他语言的一样,Set是唯一结构的,无序的集合.没有索引,可以用来给数组去重.Set默认不做类型转换.虽然NaN在js中不想等,但Set内部认为他们是相同的.这个应该很好理解.而且同样没有索引的概念,这个因该也没什么异议吧?
方法
add(value):添加一个值,返回Set结构本身
delete(value):删除某个值,返回布尔值
has(value):返回布尔值,表示是否是成员
clear():清除所有成员,无返回值
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
keys,values,entries三个方法其实返回的值是一样的.
Map
Map应该是一种接近python中的dict的数据结构,和以前不同,这次是一个直接的键值对的构造了.而且key的选择和python一样宽容.(我估计动态语言都是这么宽松,只要可以hash的估计都能做key)注意map对象的定义方法,不能直接加参数,而是map = new Map(); 然后map.set(key,val)的方法来设定,注意,这个对象的实例看起来和js原来的字典很像,但并不是一种东西.有一些明显的差别:
- 使用JSON.stringify()返回的是{}
- 有一个size属性可以知道对象的长度.js的字典对象没这个方法也没类似的方法.
目前看来,这个类型还很简单,倒是map方法很成熟.
Proxy
代理对象.
这个新的类型用处很多,建议之间看参考文档.https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
新特性
箭头函数
就是匿名函数,类似python中的lambda表达式,和lambda表达式不同的是,使用{}的情况下,箭头函数支持多行代码.需要注意的是,箭头函数的this一般指向的是window是不是当前运行函数的对象.
f= x=>x*2+1
f(2)
5
f=(x,y)=>console.log(`${x}+${y}=${x+y}`)
f(2,3)
2+3=5
f=(x,y)=>{console.log(`${x}+${y}=${x+y}`);console.log(`${x}x${y}=${x*y}`);}
f(3,4)
3+4=7
3x4=12
class关键字
对类的支持.
class Person {
constructor(name, age) {
// 构造器
this.name = name;
this.age = age;
}
say_hello() {
console.log(`my name is ${this.name},I am ${this.age} years old.`);
}
}
let tom = new Person("Tom", 12);
tom.say_hello();
输出:my name is Tom,I am 12 years old.
用字面量定义一个对象
human = {
name: "jack",
age: 12,
say_hello() {
console.log(`my name is ${this.name},I am ${this.age} years old.`);
}
};
human.say_hello();
输出:my name is jack,I am 12 years old.
原型构造方法.
student = {
__proto__: human, // 以human为原型,类似类构造器的继承某个父类
name: "Smith"
}
student.say_hello();
输出:my name is Smith,I am 12 years old.
字符串模板
student.say_hello();
let a = "jack",
b = "tom";
console.log(`${a} and ${b}`); // 注意是反引号
输出:jack and tom
解构
对数组或者字典对象中的元素进行解析赋值.
/*对数组解构赋值*/
let [a, b, c] = [1, 2, 3];
console.log(a, b, c);
/*
注意不能对集合解构赋值,像下面这样会报错的
let (m, n, j) = (11, 22, 33);
*/
/*对字典解构赋值*/
let {
"name": name
} = {
"name": "jack"
};
console.log(name);
函数的参数新方法
指定默认值,不定参数和展开序列的魔法函数
/*参数默认值*/
function f1(name = "jack") {
console.log(name);
}
f1();
/*混合带默认值和不带默认值的参数*/
function f11(name = "jack", age = 10, sex) {
console.log(name, age, sex);
}
f11(undefined, undefined, "男");
输出:jack 10 男
/*不定参数,类似python的*args,使用三个点表示*/
function f2(...args) {
console.log(args); // 输出 ["name", "age", "sex"]
console.log(...args); // 输出 name age sex
}
f2("name", "age", "sex");
/*类似python的赋值参数的情况*/
let arg_list = [1, 2, 3, 4];
f2(..arg_list);
扩展运算符之...
类似python的*展开数组.请看实际代码
/**传递参数,解包数组***/
let l1 = ["jack", 12, "male"];
f = (...args) => console.log(...args); // 不定参数格式
f(...l1); // 相当与f("jack", 12, "male")
let l2 = [2, 4, 9, 31, 12, 3, 81, 33];
console.log(Math.max(...l2)); // 求最大值
console.log(Math.min(...l2)); // 求最小值
l2.push(...[1, 1, 5, 1.7]); // 连接数组
console.log(l2);
let l3 = [...l1, ...l2]; // 合并数组
console.log(l3);
console.log(..."world"); // 展开字符串
新函数和新方法
call和apply
这个不是新的,但是要注意一下.
call(obj/func, arg1, arg2,.....) 改变函数执行时的上下文(this对象)
第一个参数是一个函数(或者对象的函数)
第二个到...n个是func的函数.
class Person {
constructor(name, age) {
// 构造器
this.name = name;
this.age = age;
}
say_hello() {
console.log(`my name is ${this.name},I am ${this.age} years old.`);
}
explain_array(arg1, arg2, arg3) {
console.log(arguments); // 内置参数
console.log(`arg1=${arg1}; arg2=${arg2}; arg3=${arg3}`);
}
}
/*call的演示*/
let p1 = new Person("张三", 12);
let p2 = new Object();
p2.name = "李四";
p2.age = 22;
p1.say_hello.call(p2);
输出:my name is 李四,I am 22 years old.
/*
实际上是用p2替换了p1(改变了函数执行时的this对象);
p2对象并没有say_hello这个方法.
*/
/*
*apply的演示,还有apply和call的对比,两则只是传递参数的方法的差别:
* call是顺序传递.apply需要一个数组.
*/
let p3 = new Object();
p3.name = "王五";
p3.age = 33;
p1.explain_array("a", "b", "c");
p1.explain_array.call(p3, "a", "b", "c");
p1.explain_array.apply(p3, ["a", "b", "c"]);
lastIndexOf
查找索引
lastIndexOf(key, from)
key需要查找的对象.
form从那个索引开始向前查找.
return 返回第一次查找到key的值对应的索引
和indexOf相反的方法,反序查找一个对象.返回从索引或者-1,注意.无论lastIndexOf还是indexOf,索引都是从数组的头部开始计算的.下面距离说明:
[1,2,3,4,4.5,5,1,7].lastIndexOf(1,3);
返回的是0, 因为数组第三元素3之前之有0这个索引的值等于1,
[1,2,1,3,4,4.5,5,1,7].lastIndexOf(1,3)
返回的是2, 因为数组第三元素3之前之有2这个索引的值等于1,
forEach方法
循环数组
forEach(func, new_this)
func 回调函数,不一定有返回值.
new_this可以用这个参数重新定义this指向.
其中.回调函数func有三个参数.
function(value, index, array){}
value是当前循环的值,
index是当前索引.
array是数组对象本身.
["a","b","c"].forEach(function(value,index,array){console.log(`No.${index} value=${value} in ${array}`);});
No.0 value=a in a,b,c
No.1 value=b in a,b,c
No.2 value=c in a,b,c
for...in和for...of
循环数组,
这两个方法放一起是为了比较,in循环的是索引,of循环的是元素.
另外,for...of可以循环字符串,Set,Map和以前的字典对象(其实是Object对象).
// for...of 解析Map对象.注意,只有Map才可以使用解构(destructuring)来将键值对拆解为两个独立的变量
for(let [k,v] of map){console.log(`${k}:${v}`);}
name:jack
age:12
// for...of 解析 dict对象.
for(let k of Object.keys(d)){console.log(`${k}=${d[k]}`);}
name=tom
age=14
// for...of解析数组.
for(let i of l){console.log(i);}
jack
tom
John
//for...in解析数组
for(let i in l){console.log(i);}
0
1
2
map
映射,这个方法和python的map基本上是同一个意思.
array.map(func,newthis)
func 回调函数,必须有返回值,
newthis 如果你要固定this对象,请使用这个参数.
其中.回调函数func有三个参数.
function(value, index, array){}
value是当前循环的值,
index是当前索引.
array是数组对象本身.
l = ["jack", "tom", "John"];
l.map(function(a,b,c){console.log(`${a}||${b}||${c}`);})
jack||0||jack,tom,John
tom||1||jack,tom,John
John||2||jack,tom,John
filter
过滤器,同上,这个方法和python的filter基本上是同一个意思.(话说javascript和python越来越像了,不,好像动态语言都越来越像了,大家都在进步嘛,呵呵)
array.filter(func,newthis)
func 过滤函数,必须返回布尔值,
newthis 如果你要固定this对象,请使用这个参数.
其中.回调函数func有三个参数.
function(value, index, array){}
value是当前循环的值,
index是当前索引.
array是数组对象本身.
// 返回数组中的偶数
l = [1,2,3];
l.filter(function(item){if(item%2===0){return 1;}else{return 0;}});
[2]
every
判断函数,序列中每一个都满足判断条件就返回真值.
array.every(func)
func 判断函数,必须返回布尔值,
其中.回调函数func有三个参数.
function(value, index, array){}
value是当前循环的值,
index是当前索引.
array是数组对象本身.
// 判断数组元素是否都是数字?
l = [1,2,3,4];
l.every(function(item){return !isNaN(item);})
true
some
判断函数,序列中只要一个都满足判断条件就返回真值.
array.some(func)
func 判断函数,必须返回布尔值,
其中.回调函数func有三个参数.
function(value, index, array){}
value是当前循环的值,
index是当前索引.
array是数组对象本身.
// 判断数组元素是否都是数字?
l = [1,"a",3,4];
l.some(function(item){return !isNaN(item);})
false
reduce
化简函数, 从左到右依次处理序列中的元素,并返回结果
array.reduce(func),从0索引开始,依次把元素相加,结果再作为下一个迭代的第一个参数.为了便于理解,我们这样定义一下加法:
加数1+加数2=结果.
func有三个参数.
function(value1, value2, index){}
value1是当前迭代中的加数1,也是上一次迭代的返回值.
value2是当前迭代中的加数2,
index是当前迭代中加数2的索引.
return 函数处理的结果.
很显然,这个函数是用来做累加计算的.
// 累加计算
l = [11, 22, 33, 44, 55, 66]
l.reduce(function(a,b,c){console.log(`加数1=${a}, 加数1=${b}, 索引=${c}`); return (a+b) + 1000;});
加数1=11, 加数1=22, 索引=1
加数1=1033, 加数1=33, 索引=2
加数1=2066, 加数1=44, 索引=3
加数1=3110, 加数1=55, 索引=4
加数1=4165, 加数1=66, 索引=5
5231 // 最终的处理结果.
reduceRight
化简函数, 从右到左依次处理序列中的元素,并返回结果,这基本就是reduce的反函数.
array.reduceRight(func),从0索引开始,依次把元素相加,结果再作为下一个迭代的第一个参数.为了便于理解,我们这样定义一下加法:
加数1+加数2=结果.
func有三个参数.
function(value1, value2, index){}
value1是当前迭代中的加数1,也是上一次迭代的返回值.
value2是当前迭代中的加数2,
index是当前迭代中加数2的索引.
return 函数处理的结果.
同reduce,这个函数是用来做累加计算的.
// 累加
l = [11, 22, 33, 44, 55, 66]
l.reduceRight(function(a,b,c){console.log(`加数1=${a}, 加数1=${b}, 索引=${c}`); return (a+b) + 1000;});
加数1=66, 加数1=55, 索引=4
加数1=1121, 加数1=44, 索引=3
加数1=2165, 加数1=33, 索引=2
加数1=3198, 加数1=22, 索引=1
加数1=4220, 加数1=11, 索引=0
5231 // 最终的处理结果.
箭头函数
是一种简化的匿名函数的书写方式,并且在一开始就会锁定内部的this对象,下面会做一些箭头函数的演示来说明问题: