es6+的javascript拓展内容
一.let,const
1.因为块级的作用域,这样打印01234,循环外打印i会报错
for (let i = 0; i < 5; i++) { setTimeout(console.log(i), 0); }
用es6以后,可以用块级作用域代替闭包
2.不存在变量提升
var tmp = 123; if (true) { tmp = 'abc'; // ReferenceError let tmp; }
一个大括号就是一个作用域,let tmp使该作用域绑定了tmp,let前赋值就报错。
3.不能重复声明
4.块级作用域内声明的函数类似于let
,对作用域之外没有影响
function f() { console.log('I am outside!'); } (function () { if (false) { // 重复声明一次函数f function f() { console.log('I am inside!'); } } f(); }());
这种方式在es5中if里面的f声明会提前,在es6中,if条件不满足就不执行函数声明,因为这个声明类似let。
5.const 声明后不能修改变量内容
二.变量的解构赋值
var [a, b, c] = [1, 2, 3];
let [ , , third] = ["foo", "bar", "baz"]; third // "baz" let [x, , y] = [1, 2, 3]; x // 1 y // 3 let [head, ...tail] = [1, 2, 3, 4]; head // 1 tail // [2, 3, 4]
下面代码的写法会报错,因为JavaScript引擎会将{x}
理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免JavaScript将其解释为代码块,才能解决这个问题。
var a; { a} = {a:1} console.log(a );//error
解构赋值需要等号右边具有Iterator接口,比如generator函数。
1.解构赋值允许指定默认值。
var [foo = true] = [1]; foo // 1
es6会用全等判断 foo对应的值 ===undefined,相等就会用默认值。不等就用它对应的值。
以上相当于 1?(foo=1):(foo=true);就是说,如果默认值foo=函数,如果后面不是undefined这个函数就不会执行。
2.关于解构赋值中的圆括号
变量声明语句中,不能带有圆括号。
// 全部报错 var [(a)] = [1]; var {x: (c)} = {}; var ({x: c}) = {}; var {(x: c)} = {}; var {(x): c} = {}; var { o: ({ p: p }) } = { o: { p: 2 } };
赋值语句中,不能将整个模式,或嵌套模式中的一层,放在圆括号之中。
// 全部报错 ({ p: a }) = { p: 42 }; ([a]) = [5];
可以使用圆括号的情况只有一种:赋值语句的非模式部分,可以使用圆括号。
[(b)] = [3]; // 正确 ({ p: (d) } = {}); // 正确 [(parseInt.prop)] = [3]; // 正确
三.字符串拓展
这里只写常用的方法
1.ES6为字符串添加了遍历器接口,使得字符串可以被for...of
循环遍历。
2.at
方法,可以识别Unicode编号大于0xFFFF
的字符,返回正确的字符。
'abc'.at(0) // "a" '𠮷'.at(0) // "𠮷"
3.字符串的方法
- includes():返回布尔值,表示是否找到了参数字符串。
- startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
- endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
这三个方法都支持第二个参数,表示开始搜索的位置。
var s = 'Hello world!'; s.startsWith('world', 6) // true s.endsWith('Hello', 5) // true s.includes('Hello', 6) // false
4.repeat方法
'x'.repeat(3) // "xxx" 'hello'.repeat(2) // "hellohello" 'na'.repeat(0) // ""
参数如果是小数,会被取整。如果参数是0到-1之间的小数,则等同于0,这是因为会先进行取整运算。0到-1之间的小数,取整以后等于-0
,repeat
视同为0。如果repeat
的参数是字符串,则会先转换成数字。
5.ES7推出了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart
用于头部补全,padEnd
用于尾部补全。
'x'.padStart(5, 'ab') // 'ababx' 'x'.padStart(4, 'ab') // 'abax' 'x'.padEnd(5, 'ab') // 'xabab' 'x'.padEnd(4, 'ab') // 'xaba'
第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。
四.数值扩展
1.ES6提供了二进制和八进制数值的新的写法,分别用前缀0b
(或0B
)和0o
(或0O
)表示。
2.ES6在Number对象上,新提供了Number.isFinite()
和Number.isNaN()
两个方法。Number.isFinite()
用来检查一个数值是否为有限的(finite)。
3.ES6将全局方法parseInt()
和parseFloat()
,移植到Number对象上面,行为完全保持不变。
4.Number.isInteger()
用来判断一个值是否为整数。
5.ES6在Number对象上面,新增一个极小的常量Number.EPSILON
Number.EPSILON // 2.220446049250313e-16
6.ES6引入了Number.MAX_SAFE_INTEGER
和Number.MIN_SAFE_INTEGER
这两个常量,用来表示这个范围的上下限。Number.isSafeInteger()
则是用来判断一个整数是否落在这个范围之内。
五.Math对象的扩展
1.Math.trunc
方法用于去除一个数的小数部分,返回整数部分。
2.Math.sign
方法用来判断一个数到底是正数、负数、还是零。
它会返回五种值。
- 参数为正数,返回+1;
- 参数为负数,返回-1;
- 参数为0,返回0;
- 参数为-0,返回-0;
- 其他值,返回NaN。
3.Math.cbrt
方法用于计算一个数的立方根。
4.ES7新增了一个指数运算符(**
)
let a = 2; a **= 2; // 等同于 a = a * a;
六.数组的拓展
1.Array.from
方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map)。
let arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3 }; // ES5的写法 var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c'] // ES6的写法 let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
2.Array.of
方法用于将一组值,转换为数组。用来代替New Array()
Array.of() // [] Array.of(undefined) // [undefined] Array.of(1) // [1] Array.of(1, 2) // [1, 2]
3.数组实例的copyWithin
方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。会修改原数组
Array.prototype.copyWithin(target, start = 0, end = this.length)
- target(必需):从该位置开始替换数据。
- start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
- end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
// -2相当于3号位,-1相当于4号位 [1, 2, 3, 4, 5].copyWithin(0, -2, -1) // [4, 2, 3, 4, 5]
4.数组实例的find
方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true
的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined
。
[1, 5, 10, 15].find(function(value, index, arr) { return value > 9; }) // 10
findIndex
方法返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
[1, 5, 10, 15].findIndex(function(value, index, arr) { return value > 9; }) // 2
另外,这两个方法都可以发现NaN
,弥补了数组的IndexOf
方法的不足。
5.fill
方法使用给定值,填充一个数组。
['a', 'b', 'c'].fill(7) // [7, 7, 7] new Array(3).fill(7) // [7, 7, 7]
fill
方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置
['a', 'b', 'c'].fill(7, 1, 2) // ['a', 7, 'c']
6.数组遍历方法keys()
是对键名的遍历、values()
是对键值的遍历,entries()
是对键值对的遍历。
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"
7.ES7,Array.prototype.includes
方法返回一个布尔值,表示某个数组是否包含给定的值
[1, 2, 3].includes(2); // true [1, 2, 3].includes(4); // false [1, 2, NaN].includes(NaN); // true
七.函数扩展
1.解构赋值函数参数默认值
function log(x, y = 'World') { console.log(x, y); }
2.扩展运算符
3.箭头函数
var f = v => v; 等同于 var f = function(v) { return v; };
4.ES7,函数绑定运算符是并排的两个双冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
foo::bar; // 等同于 bar.bind(foo);
八.对象的拓展
1.属性简洁写法:
var foo = 'bar'; var baz = {foo}; baz // {foo: "bar"} // 等同于 var baz = {foo: foo};
2.属性名表达式
// 方法一 obj.foo = true; // 方法二 obj['a' + 'bc'] = 123;
3.Object.is用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。不同之处只有两个:一是+0
不等于-0
,二是NaN
等于自身。
4.Object.assign
方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
var target = { a: 1 }; var source1 = { b: 2 }; var source2 = { c: 3 }; Object.assign(target, source1, source2); target // {a:1, b:2, c:3}