ECMAScript 6 学习总结
1.什么是ES6?
简单的说 ES6 的第一个版本,在2015年6月发布了,正式名称就是《ECMAScript 2015标准》(简称 ES2015)在2016年6月,小幅修订的《ECMAScript 2016标准》(简称 ES2016)如期发布,2017年6月发布的新版本就是ES7。ES6 既是一个历史名词,也是一个泛指,含义是5.1版以后的 JavaScript 的下一代标准,涵盖了ES2015、ES2016、ES2017等等。
2.箭头函数 =>
会解析为 function(){}
eg. input.map(item => item+1); 解析完:
input.map(function(item){
item = item + 1;
});
箭头函数的特征:
- 代码简写
- 箭头函数会捕获上下文的this对象,本身没有this对象
- 箭头函数是匿名函数
function MyFun(){ this.a = 1; setInterval(function growUp(){ //此处的this,growUp函数定义的内部的this, 不同于构造函数MyFun函数中的this this.a ++; },1000); } var fun = new MyFun(); //要修改的话,我们往往会将构造函数的this指定到一个新增的变量中 //如果使用箭头函数,就会很方便: function MyFun(){ this.a = 1; setInterval(() => { //此处的this正确的指向了构造函数MyFun this.a++; },1000); } var fun = new MyFun();
3.let 和const命令
let定义的变量只在let命令所在的代码块内有效.
let不允许在相同作用域内重复声明,允许在块级作用域内声明函数, 声明类似于var,即会提升到全局作用域或函数作用域的头部。同时,函数声明还会提升到所在的块级作用域的头部。
{ let a = 10; var b = 1; } console.log(a); // ReferenceError: a is not defined. console.log(b); // 1 for循环,就很适合使用let命令 for(let i = 0; i < 10; i++){} console.log(i);// ReferenceError: i is not defined //循环的语句定义和循环体可以作为两个不同的作用域 for(let i = 0; i < 10; i++){ let i = “abc”; console.log(i); } //所以会打印3个”abc”
const用来定义不可变的常量,不可变的常量名一般全大写。一旦声明,常量的值就不能改变。
eg. const PI = 3.14;
对于const来说,只声明不赋值,就会报错。const的作用域与let命令相同:只在声明所在的块级作用域内有效。
4.ES6 的解构赋值
(1)数组的解构赋值——右边如果不是数组则报错,并且在严格模式中,变量不能重复定义,否则会报异常。
let [x, y, z] = [1, 2, 3]; let [a, …b] = [1, 2, 3, 4]; ==> a = 1; b = [2, 3, 4]; let [x1, [y1, [z1, r]]] = [1, [2, [3]]]; r = undefined; //对应不上的变量值为undefined //解构赋值可以添加默认值,如果右边赋值不严格(===)等于undefined, 则默认值将不会生效。 let [h=1] = [undefined]; //h = 1; let [h1=1] = [null]; //h1 = null; //如果默认值是一个表达式,会懒赋值,就是在需要的时候才会去执行结果 function myFun(){ console.log(“come in”); } let [f = myFun()] = [1];
(2)对象的解构赋值
对象赋值可数组赋值的区别是:数组是按位置取值,值由位置来决定
而对象不一定顺序一致,只要变量名和属性名相同,便可以取值。
var {bar, liz} = {bar: ‘barValue’, liz1: ‘liz1Value’}; console.log(bar);//barValue console.log(liz);//undefined 属性名不一致 var obj = {first:'hello',last:'world'}; var {first:fi,last:la} = obj; console.log(fi);//hello console.log(la);//world //默认赋值,必须严格等于(===)undefined,默认值才会生效.如果解构失败,变量的值就等于undefined var {lib = 1} = {lib: undefined}; var {lib1 = 2} = {lib1: null}; console.log(lib); //1 console.log(lib1); //null
(3)字符串的解构赋值 —其赋值规则类似于数组
const [a0, b0, c0, d0, e0] = “hello”; console.log(a0);//h console.log(b0);//e console.log(c0);//l console.log(d0);//l console.log(e0);//o //字符串有个属性length const {length: len} = “hello”; console.log(len); //5
(4)数值和布尔类型的解构赋值——等号右边不是对象,而是数值或者布尔值,则先转换为对象。
let {toString: x0} = 123; console.log(x0);//[function:toString] x0 === Number.prototype.toString; let {toString:y0} = true; console.log(y0);//[function:toString] y0 === Boolean.prototype.toString; //因为undefined和null不能转换为对象,所以会报异常 let {toString:z0} = undefined /null; console.log(z0); //var z0 = undefined.toString;TypeError: Cannot read property 'toString' of undefined
(5)函数的参数解构赋值
function add([x, y]){ return x+y; } console.log(add([1,2])); //3 console.log([[1,2],[3,4]].map(([a,b]) => a+b));//[3,7] //函数参数默认值结构赋值,也是===undefined时,默认值有效 function myFun([x=1,y=2]){ return x+y; } console.log(myFun([4,5]));//9 console.log(myFun({}));//error console.log(myFun([5]));//7 console.log(myFun([null,null]));//0
变量解构赋值用处:
(1)交换值
eg. let [myx,myy] = [myy,myx];
(2)函数可以返回多个值(good)
eg. function mytest(){
return [1,2,3];
}
let [m1,m2,m3] = mytest();
(3)函数可以返回多个对象
eg. function mytest2(){
return ({
foo:1,
foo1:2,
})
}
let {foo, foo1} = mytest2();
console.log(foo); //1
console.log(foo1); //2
5.ES6的算术方法
ES6的二进制(0b/0B)和八进制(0o/0O)表示
Number(); //方法将其转换为10进制数值 console.log(Number(0b111)); console.log(Number(0o111)); NUmber.isFinite();//判断是否是非无穷 Number.isNaN();//检查是否是NaN Number.parseInt(); Number.parseFloat(); Number.isInterger(); console.log(Number.isInterger(3)); console.log(Number.isInterger(3.0)); Number.EPSILON;//表示一个极小的变量 2.220446049250313e-16 //起作用来进行浮点数计算的误差判断,误差<Number.EPSILON 则计算结果正确 // js表示整数的范围是 -2^53 ~ 2^53 //ES6引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。 Number.MAX_SAFE_INTEGER; Number.MIN_SAFE_INTEGER; isSafeInterger()//方法就是判断某个整数值是否落在上面的安全范围之间 Number.isSafeInterger(); //获取整数部分,对于空值和无法截取整数的值,返回NaN。 Math.trunc(4.1);//4 Math.trunc(4.9);//4 Math.trunc(-4.1);//-4 Math.trunc('NaN');//NaN //来返回一个函数是正数(1),负数(-1),还是0(0),-0(-0),其他返回NaN Math.sign(5);//1 Math.sign(-5);//-1 Math.sign(0);//0 Math.sign(-0);//-0 Math.sign("NaN");//NaN //用来计算一个数的立方根 Math.cbrt(); //将一个整数用32位二进制来表示 Math.clz32(); //Math.imul方法返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位的带符号整数。 Math.imul(a,b); //返回一个数的单精度浮点数形式 Math.fround(); //Math.hypot方法返回所有参数的平方和的平方根。 Math.hypot(); ES6新增了6个三角函数方法。 Math.sinh(x) //返回x的双曲正弦(hyperbolic sine) Math.cosh(x) //返回x的双曲余弦(hyperbolic cosine) Math.tanh(x) //返回x的双曲正切(hyperbolic tangent) Math.asinh(x) //返回x的反双曲正弦(inverse hyperbolic sine) Math.acosh(x) //返回x的反双曲余弦(inverse hyperbolic cosine) Math.atanh(x) //返回x的反双曲正切(inverse hyperbolic tangent) ES7新增了一个指数运算符(**) b **= 3;//等同于 b = b * b * b;
6.ES6数组方法
Array.from(); ——将类似于数组的对象和可遍历的对象(明显特征就是有length属性)转为数组
let obj = { "0":"dtl", "1":18, "2":1234, length:5 } var arr = Array.from(obj); console.log(arr); //["dtl",18,1234,undefined,undefined]
Array.of(); ——将一组数转为数组,如果没有参数,返回一个空数组
console.log(Array.of(3));//[1]
copyWith(); ——方法用于将目标元素拷贝到指定位置,将代替指定位置target的元素
Array.prototype.copyWithin(target,[start],[end]); //target 必需元素,从start位置开始拷贝 :默认为0
//复制几个就从指定位置替换几个元素 console.log([1,2,3,4,5].copyWithin(0,3));//[4,5,3,4,5] console.log([1,2,3,4,5].copyWithin(0,2));//[3,4,5,4,5] console.log([1,2,3,4,5].copyWithin(0));//[1,2,3,4,5]
find(); ——用于找回第一个符合条件的数组成员,回调函数的三个参数:1表示当前的值,2表示当前的位置,3表示当前的数组
findIndex(); ——返回第一个符合条件的数组成员的位置
let b = [1,2,5,8,9].find(function(value,index,arr){ return value > 7; }); console.log(b);//8 let c = [1,2,5,8,9].findIndex(function(value,index,arr){ return value > 7; }); console.log(c);//3
fill(value,start,end); ——使用给定值来填充一个数组 ,常用于数组的初始化。value表示填充的值,start填充的起始位置,end填充的结束位置(但不包括结束位置)
let myArr = new Array(3).fill(7, 0, 2); console.log(myArr); //[7, 7, ]
entries(),keys(),values(); ——来遍历数组
for (let index of ['a', 'b'].keys()) { console.log(index); } 0 1 for (let elem of ['a', 'b'].values()) { console.log(elem); } 'a' 'b' for (let [index, elem] of ['a', 'b'].entries()) { console.log(index, elem); } 0 "a" 1 "b"
includes(); ——返回数组是否包含某个值,true/false。没有includes之前我们通过indexOf()来判断,它有两个弊端:使用===判断,对NaN判断不准确,还有表达语义不够直观
Es6明确将空位转为undefined。
copyWith()//会连空位一起拷贝
fill()//会将空位当正常数组对待
for...of //循环会遍历空位
entires(),keys(),values(),find(),findIndex()//都会将空处理成undefined
7.ES6 函数
函数参数赋默认值
//原来的方式给函数赋默认值 function add(x,y){ y=y||'world'; console.log(x+' '+y); } add('hello',); add('hello','china'); add('hello','');//hello world 将“”变成了默认值,所以给y赋值时先要判断又是否有值,因此原来的方式很麻烦 //新的方式给函数参数赋默认值 function newAdd(x,y = 'world'){ console.log(x+' '+y); } newAdd('hello',); newAdd('hello','');//hello
后续ES6 学习总结:
1.块级作用域和let ,const
let和const不会提升变量的声明
同名的变量或者常量在同一个作用域不能重复定义
在作用域内,在声明前操作let或const定义的变量或者常量,会抛出异常。 (临时死区 TDZ)
在循环中使用let和const每次迭代会创建新绑定(产生一个副本),所以可以获取到每次迭代的值
块级作用域绑定的最佳实践: 默认使用const 定义,除非需要修改变量值时,使用let, 这样在很大程度上就实现了代码的不可变,防止错误的产生。
2.String.codePointAt() 获取字符占用的编码单元数量
String.fromCodePoint() 根据指定的码位生成一个字符串
normalize() 字符串比较之前,现将其按照同一规则进行转换
includes(), startWith(), endsWith() 返回结果为true/false, 都可以传入两个参数,第一个表示要搜索的字符,第二个参数可选表示开始检索的其实位置
endsWith() 从字符串的末尾开始向前匹配
repeat() 传入number类型的参数,表示字符串重复的次数
正则表达式的flags属性会返回所有应用于但钱正则表达式的修饰字符串,source属性获取正则表达式的文本部分
ES5中一直缺乏许多特性,如多行字符串、字符串格式化、HTML转义等。ES6通过模板字面量的方式进行了填补。模板字面量:用反撇号(``)替代单双引号,如果要在字符串中使用反撇号,用反斜杠(\)将其转义即可。字符串占位符${} 符号组合,中间可以包含任意的JavaScript表达式,可以是变量,运算式,函数等,也可以在模板字 面量里面嵌套另外一个。创建标签模板,标签函数接受模板字面量每个部分组成的参数数组,通过这些数据来组装出一个适合的字符串值。String.raw`Multiline\nstring` 获取原生字串-> Multiline\\nstring
3.ECMAScript 6 的函数
默认参数值arguments,在ECMAScript 5里非严格模式和严格模式不同:
function(first, second){
console.log(first === arguments[0]);
console.log(second === arguments[1]);
first = ‘c’;
second = ‘d’;
console.log(first === arguments[0]);
console.log(second === arguments[1]);
}
返回的结果为:
true
true
true
true
非严格模式下,参数的改变会同步到arguments对象中
下面再看下严格模式:
function(first, second){
“use strict”;
console.log(first === arguments[0]);
console.log(second === arguments[1]);
first = ‘c’;
second = ‘d’;
console.log(first === arguments[0]);
console.log(second === arguments[1]);
}
返回的结果为:
true
true
false
false
严格模式下,无论参数如何变化,arguments 对象不再随之改变
在ECMAScript 6 的函数,如果使用了默认值,则无论是否显式的定义了严格模式,arguments都保持和ECMAScript 5严格模式下保持一致
function(first, second=‘5’){
console.log(arguments.length);
console.log(first === arguments[0]);
console.log(second === arguments[1]);
first = ‘c’;
second = ‘d’;
console.log(first === arguments[0]);
console.log(second === arguments[1]);
}
返回结果为:
1
true
false
false
false
arguments.length的值为1,arguments[1]的值为undefined
函数的不定参数:在函数的命名参数前添加三个点(…)就表明这是一个不定参数,该参数为一个数组,包含自它传入后的所有参数。arguments 是返回了所有的参数,不定参数可以放心直接遍历。如果函数声明了不定参数,arguements对象包含了所有传入函数的参数。
函数的length 属性统计的是函数命名参数的数量,不算不定参数,所以不定参数的引入不会影响函数的length值。还有不定参数必须放在函数参数的末尾,否则会语法错误。
展开运算符: 简化使用数组传参的过程。
let values = [10, 9, 0,5,6,20];
console.log(Math.max.apply(Math, values)); //ES5 通过apply实现
console.log(Math.max(…values)); //ES6中展开运算符很大程度可以代替apply
Es6引入了new.target原属性,如果通过new 函数调用则new.target !== undefined,比如通过call,或者apply调用。
ES6引入了块级函数,来解决在ES6之前版本函数声明在不同浏览器下的不兼容性。
“use strict”;
if(s){
console.log(typeof doSomething); // function
console.log(typeof doSomething1); // undefined
function doSomething(){
} //Es6的严格模式下,块级函数的声明会被提升到块级顶部
let doSomething1 = function(){} // let定义的函数声明不会被提升
}
console.log(typeof doSomething); // undefined 在非严格模式下会提升至全局作用域
增加了name 属性,来返回函数的名称。
箭头函数
1.没有this,super, arguments, new.target的绑定,这些值由外围最近一层的非箭头函数决定。
2.不能通过new关键字调用
3.没有原型
4.不可改变this的绑定
5.不支持arguments对象
6.不支持重复的命名参数
let reflect = value => value;
let sum = (sum1, sum2) => sum1 + sum2;
let sum2 = (num1, num2) => {
return num1 + num2;
}
let getName = () => 'dtl';
let myFun = () => {} ; // 创建一个空函数
let getObj = id => ({id: id, name:'dd'}); //在函数外返回一个对象字面量,用小括号将字面量包裹起来
let person = ((name) => {
return {
getName: function(){
return name;
}
};
})('dtl'); //创建立即执行函数,小括号将箭头函数包裹,不包裹传参部分。
尾调用优化可以帮助函数保持一个更小的调用栈,从而减少内存的使用,避免栈溢出错误。在函数尾部,直接return 函数调用结果。引擎进行的自动优化。
function factorial(n, p = 1){
if(n <= 1){
return 1*p;
}else{
let result = n*p;
return factorial(n -1, result); // 优于 return n*factorial(n -1);
}
}
4.扩展对象的功能性
对象字面量:
function createPerson(id, name){
return { //当属性名与值名字相同,可以不用写冒号
id,
name,
}
}
var person = {
id: '123',
sayName(){ //消除了冒号和function关键字
console.log(this.name);
}
}
let lastName = "last name";
let person = {
"first name" : 'taoli',
[lastName]: 'du', // 在对象字面量中使用[],表示该属性名是可以计算的,它的内容被求值并转换为一个字符串。
}
ES6 在全局Object上引入了新方法:
Object.is() 弥补全等运算符的不准确计算 +0 === -0 //true Object.is(+0, -0)//false NaN === NaN //false Object.is(NaN, NaN) // true 除了这两个特例,剩下的基本和 === 返回结果一致
Object.assign() 接受一个接收对象和任意淑玲的源对象,最终返回接收对象。可以代替ES5中的maxin() 方法
ES6 清晰的定义了枚举类型的枚举顺序,先数字升序,再字母,按照插入的先后顺序排列。
Object.getPrototypeOf()
Object.setPrototypeOf(a, b) //改变a 的原型为 b 对象创建后,用此方法修改它的原型
super 便捷地访问原型对象原型 super 就是 Object.getPrototypeof(this)的值,使用super时,此时的this会被自动设置为当前作用域的this值。
5.解构:使数据访问更便捷
对象解构:根据对象字面量,读取相应的属性名称。注意,使用 var,let或const 解构声明变量时,必须提供初始化值。如果不适用解构赋值,只有const定义必须初始化。
数组解构:按顺序对应赋值,eg, let a =1;b=2; [a, b] = [b, a];实现两个数的交换。嵌套数组解构,不定元素解构,不定元素必须是数组的最后一个条目。
解构的混合应用: 对象解构和数组解构嵌套混合使用赋值。
在对象和解构赋值中,都可以为值为null/undefined的对象数组或数组元素指定默认值。
let node = {
type : 'identifier',
name: 'foo',
loc: {
start: {
line: 1,
column: 1
},
end:{
line: 1,
column: 4
}
},
range: [0, 3]
}
let {
loc: { start },
range: [ startIndex ]
} = node;
console.log(start.line); //1
console.log(start.column); //1
console.log(startIndex);//0
6.Symbol和Symbol属性
ES6 为 JavaScript 引入了一种新的基本类型:Symbol,它由全局 Symbol() 函数创建,每次调用 Symbol()函数,都会返回一个唯一的 Symbol。
所有可以计算属性名的地方都可以用Symbol。
Symbol 是 JavaScript 中的新原始类型。console.log(typeof symbol) //Symbol
let uid = Symbol.for(‘uid’);//Symbol.for() 创建之前会去全局Symbol注册表中搜索,如果有,就是用已建的,没有就创建新的Symbol
Symbol.keyFor(‘uid’) //‘uid’ /undefined Symbol.keyFor() 在Symbol全局注册表中检索与Symbol有关的键
Symbol不能和其他类型进行转换/强制转换,会报错
Object.getOwnProperty-Symbol() 来检索Symbol属性
Object.getOwnPropertySymbol() 返回Symbol自有属性数组
well-known Symbol定义了一些语言内部可用的功能,eg. Symbol.hasInstance 属性,需要再去查阅。
7.Set集合和Map集合
一般来说,Set集合常被用于检查对象中是否存在某个键名,而Map集合常被用于获取已存信息。
ES6中的Set集合: 是一种有序列表,其中含有一些相互独立的非重复值
let set = new Set();
set.add(5);
set.add(‘5’);
console.log(set.size); //2
set.add(5); //重复add的值,实际调用会被忽略
let set = new Set([1,2,3,4,5,5,5,5]); console.log(set.size);// 5 重复add的值,实际调用会被忽略
不会对所存值进行强制类型转换
let set = new Set(),
key1 = {},
key2 = {};
set.add(key1);
set.add(key2);
cosole.log(set.size); //2 ES6 中不会key1,key2强转为字符串,因此在set集合中是两个独立的元素,而在ES5中会被转换,则两者的值“[object object]”,实际是同一个属性值
set.has(5); // true has()方法检测set集合中是否存在某个值
set.delete(5); //delete()方法移除Set集合中的某个元素
set.clear(); //clear()方法清除Set集合中的元素
Set集合和数组之间的转换:
let set = new Set([1,2,3,3,4,4,5]), //去掉了重复了值
array = […set]; //用展开运算符,很容易将set转换为array
console.log(array); //[1,2,3,4,5]
Weak set: 解决清除了对初始对象的引用,但Set集合缺保留着引用,而引起的一些内存泄漏问题。
创建Weak Set 集合:
let set = new WeakSet(),
key = {};
set.add(key);
key = null;
//console.log(set.has(key));// false
WeakSet 和Set的一些区别:
. 在weakSet的实例中,如果向 add(), has()和delete()这三个方法传入非对象参数都会导致程序出错。
.Weak Set 集合不可迭代,所以不能被用于for-of循环
.没有keys(),values()等任何迭代器,所以无法通过程序本身来检测其中的内容。
.不支持forEach()方法
.不支持size()属性
Map集合的初始化方法
let map = new Map([[‘name’, ‘dtl’], [‘age’, 18]]);
同样:map.set(key,value);
map.delete(key);
map.clear(); //清除所有键值对
也可以用对象作为Map的key, 在对象中,是不能用对象作为对象的属性名。
let set = new Set([1, 2]);
forEach 方法都支持传入三个参数:
set.forEach(function(value, key, ownerset){ //set中的 value === key
console.log(key + ' ' + value);
console.log(ownerSet === set);
});
let map = new Map([['name', 'dtl'], ['age', 18]]);
map.forEach(function(value, key, ownerMap){
console.log(key + ' ' + value);
console.log(ownerMap === map);
});
WeakMap集合 支持 has(key), 和delete(key)方法判断和移除key,value.
如果只用对象作为key, WeakMap集合将是最好的选择,当数组再也不可访问后集合中存储的相关引用和数据会被自动回收。但是WeakMap不支持forEach(),size,clear()来管理元素,对用户的能见度较低。
如果使用费对象的kay,那就选择Map集合。
Set 集合的值和Map集合的key 的等价性都是通过Object.is()来判断。如果相同,会高滤掉重复的值。
8. ES6中的迭代器(Iterator)和生成器(Generator)
迭代器(Iterator): 迭代器是一种特殊对象,它具有一些专门为迭代过程设计的专有接口,所有的迭代器对象都有一个next()方法,每次调用都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔类型的值,当没有更多可返回数据时返回true,如果没有相关数据则返回undefined 。迭代器还会保存一个内部指针,用来指向当前集合中值的位置,每调用一次next()方法,都会返回下一个可用的值。
生成器(Generator): 是来返回迭代器的函数。
function关键字后的星号(*)来表示,函数中会用到新的关键字yield。星号可以紧挨着function关键字,也可以在中间添加一个空格。
function *createGenerator(){
yield 1;
yield 2;
yield 3;
}
// 生成器能像正规函数那样被调用,但会返回一个迭代器
let iterator = createIterator();
console.log(iterator.next().value); // 1
console.log(iterator.next().value); // 2
console.log(iterator.next().value); // 3
只会在调用迭代器的next()方法时,返回yield的值。并且yield只能在迭代器的主函数中有效,不能嵌套在语句里,会报错。(yield关键字只可在生成器内部使用,在其他地方使用会导致程序抛出错误)
生成器函数表达式,function与次奥括号之间添加一个* 号。
let createIterator = function *(items) {
for (let i = 0; i < items.length; i++) {
yield items[i];
}
};
生成器对象方法:
var o = {
*createIterator(items) {
for (let i = 0; i < items.length; i++) {
yield items[i];
}
}
};
let iterator = o.createIterator([1, 2, 3]);
可迭代对象具有Symbol.iterator属性,是一种与迭代器密切相关的对象。在ES6中,所有的集合对象(数组、Set集合及Map集合)和字符串都是可迭代对象,这些对象中都有默认的迭代器。
let values = [1, 2, 3];
let iterator = values[Symbol.iterator]();
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
创建可迭代对象:
默认情况下,开发者定义的对象都是不可迭代对象,但如果给Symbol.iterator属性添加一个生成器,则可以将其变为可迭代对象。
let collection = {
items: [],
*[Symbol.iterator]() {
for (let item of this.items) {
yield item;
}
}
};
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);
for (let x of collection) {
//1
//2
//3
console.log(x);
}
在数组字面量对此使用展开运算符,将可迭代对象的多个元素依次插入新数组中,替换原先展开运算符所在的位置。
let smallNumbers = [1, 2, 3],
bigNumbers = [100, 101, 102],
allNumbers = [0, ...smallNumbers, ...bigNumbers];
console.log(allNumbers.length); // 7
console.log(allNumbers); // [0, 1, 2, 3, 100, 101, 102]
内建迭代器:
1.集合对象迭代器: 数组,Map集合,Set集合
内建了三种迭代器:
entries() 返回一个迭代器,其值为对个键值对
values() 返回一个迭代器,其值为集合的值
keys() 返回一个迭代器,其值为集合中的所有键名
let colors = [ "red", "green", "blue" ];
let tracking = new Set([1234, 5678, 9012]);
let data = new Map();
data.set("title", "Understanding ES6");
data.set("format", "ebook");
for (let entry of colors.entries()) {
console.log(entry); //[0, red][1, green],[2,blue]
}
for (let entry of tracking.entries()) {
console.log(entry); //[1234,1234] [5678, 5678] [9012, 9012]
}
for (let entry of data.entries()) {
console.log(entry); //[“title”, “Understanding ES6”] [“format”,”ebook”]
}
for (let entry of colors.values()) {
console.log(entry); //“red” “green” “blue”
}
for (let entry of tracking.values()) {
console.log(entry); //“1234” “5678” “9012”
}
for (let entry of data.values()) {
console.log(entry); //“Understanding ES6” ”ebook”
}
for (let entry of colors.keys()) {
console.log(entry); //0 1 2
}
for (let entry of tracking.keys()) {
console.log(entry); //1234 5678 9012
}
for (let entry of data.keys()) {
console.log(entry); //“title” “format”
}
2.字符串迭代器 for of 循环输出正确的内容
3.NodeList迭代器 for of 循环输出正确的内容
9.类的访问器属性
let propertyName = “html”;
class CustomHtmlElement {
constructor(element) {
this.element = element;
}
get [propertyName] () { //用[] 包裹起来,就是可计算名称
return this.element.innerHTML;
}
set [propertyName] () {
return this.element.innerHTML = value;
}
}
类中的所有方法和访问器属性都可以添加static,除了构造函数之外。
不可在实例中访问静态成员,必须要在类中访问静态成员。
继承和派生类:
class Rectangle
class Square extends Rectangle
使用super()可访问基类的构造函数,需注意以下几点:
1.只可在派生类(extends 声明的类)的构造函数中使用super()
2.在构造函数访问this之前一定要调用super()
3.如果不想调用super(),则唯一的方法就是让类的构造函数返回一个对象
10.改进的数组功能
ES6 增加了Array.of() 和Array.from() 方法
查找数组中匹配的元素:
find() 返回查到的值
findIndex() 返回查到值的索引
查找与某个值匹配的元素:
indexOf()和lastIndexOf()
fill()用指定的值填充数组中一到多个元素
eg. let number = [1,2,3,4];
number.fill(1);
Console.log(numbers.toString()); //1,1,1,1
let number = [1,2,3,4];
number.fill(1,2);
Console.log(number.toString());//1,2,1,1 从索引2开始填充元素,到number.length结束
number.fill(0,1,3);
console.log(numbers.toString()); //1,0,0,1 索引1和2的元素填充0
copyWithin(a, b, [c]) 方法 a:开始填充值的索引位置 b:开始复制值的索引位置 [c]:到该索引停止赋值
eg. Let numbers = [1, 2, 3, 4]; numbers.copyWithin(2, 0); console.log(numbers.toString());// 1,2,1,2
numbers.copyWithin(2, 0, 1); //1,2,1,4
了解定型数组
11.Promise 与异步编程
promise的生命周期: pending(进行中), fulfilled(已完成),rejected(已拒绝)
Promise.resolve()
Promise.reject()
Promise 链操作,并且传递返回值给下一个promise, 看下面的例子:
let p1 = new Promise(function(resolve, reject){
resolve(42);
});
p1.then(function(value){
console.log(value);// 42
return value+1;
}).then(function(value){
console.log(value); //43
});
也可以返回promise对象,在一个promise执行成功后,创建另一个promise,然后调用
let p1 = new Promise(function(resolve,reject){
resolve(42);
});
P1.then(function(value){
console.log(value); //42
let p2 = new Promise(function(resolve, reject){
resolve(43);
})
return p2;
}).then(function(value){
console.log(value);//43
})
直到p2处理完成后,才处理第二个处理程序
响应多个Promise
Promise.all() 方法 只接受一个参数,并且返回一个Promise,该参数是一个含有多个受监视的promise可迭代对象,只有可迭代对象中的promise全部处理完成,最后的promise才会执行
let p1 = new promise(function(resolve,reject){
resolve(42);
});
Let p2 = new Promise(function(resolve,reject){
resolve(43);
});
Let p3 = new Promise(function(resolve.reject){
resolve(44);
});
Let p4 = Promise.all([p1,p2,p3]);
P4.then(function(value){
console.log(Array.isArray(value)); //true
console.log(value[0]);//42
console.log(value[1]);//43
console.log(value[2]);//44
});
Promise迭代对象中只要有一个被拒绝,不等其他执行完成,都全部拒绝。
let p1 = new promise(function(resolve,reject){
resolve(42);
});
Let p2 = new Promise(function(resolve,reject){
reject(43);
});
Let p3 = new Promise(function(resolve.reject){
resolve(44);
});
Let p4 = Promise.all([p1,p2,p3]);
P4.then(function(value){
console.log(Array.isArray(value)); //false
console.log(value);//42
});
Promise.race() 方法和promise.all()的区别就是,只要promise迭代对象中有一个解决,那么无需等待其他promise解决,就返回,会竞选,如果p2先完成,则返回拒绝的promise,如果跑先完成,返回已完成的promise.
let p1 = new promise(function(resolve,reject){
resolve(42);
});
Let p2 = new Promise(function(resolve,reject){
reject(43);
});
Let p3 = new Promise(function(resolve.reject){
resolve(44);
});
Let p4 = Promise.race([p1,p2,p3]);
P4.then(function(value){
console.log(value);//42
});