1. let
let相较于var的最大好处是创建了块级作用域,此外也不存在变量提升。
{let a = 10;var b = 1;}console.log(a) // ReferenceError: a is not defined.console.log(b) // 1
没有块级作用域所引起的问题:用来计数的循环变量被泄露为全局变量。
var s = 'hello';for (var i = 0; i < s.length; i++) {console.log(s[i]);}console.log(i); // 5
2. const
const声明一个只读的常量。一旦声明,常量的值就不能改变。const一旦声明就必须立即初始化,不能留到以后赋值。const也有块级作用域,也不存在变量提升。
const本质上并不是保证变量的值不得改动,而是变量指向的那个内存地址不得改动。
- 对于数值、字符串、布尔值等,值就保存在变量指向的那个内存地址,因此等同于常量。
- 对于对象、数组,变量所保存的只是一个指针,
const只能保证这个指针指向的对象不能改变,而指针所指向的对象的内部属性是可以改变的。> 盒子不能变,而盒子里面的东西可以变。
3. 字符串
几个新增的函数:at()、startsWith()、endsWith()、includes()、repeat()、padStart()、padEnd()、matchAll()
//at'𠮷'.charAt(0) // "\uD842"'𠮷'.at(0) // "𠮷"// startsWith、endsWith、includeslet s = 'Hello world!';s.startsWith('world', 6) // trues.endsWith('Hello', 5) // true ,这里表示针对前n个字符s.includes('Hello', 6) // false// repeat'x'.repeat(3) // "xxx"// padStart、padEnd// 第一个参数指定字符串的最小长度,第二个参数是用来补全的字符串。'x'.padStart(4, 'ab') // 'abax''x'.padEnd(4, 'ab') // 'xaba'
引入了使用反引号(`)的模板字符串。
4. 函数
参数的默认值
允许为参数设定默认值,并可直接写在参数定义的后面。
function log(x, y = 'World') {console.log(x, y);}log('Hello') // Hello Worldlog('Hello', 'China') // Hello Chinalog('Hello', '') // Hello
rest / spread操作符(…)
rest被用于函数传参,是为了获取函数的多余参数,在传参时可把参数转为数组。
// rest参数的写法1const sortNumbers = (...numbers) => numbers.sort();sortNumbers(5,6,8,1,4) // [1, 4, 5, 6, 8]// rest参数的写法2function add(...values) {let sum = 0;for (var val of values) {sum += val;}return sum;}let add = sum(...values) =>(values.sum());add(2, 5, 3) // 10
spread则用于函数调用,其参数是数组,效果是将其展开为独立元素。
function foo(x,y,z) {console.log(x,y,z);}let arr = [1,2,3];foo(...arr); // 1 2 3
name属性
.name方法返回函数的函数名。
function foo() {}foo.name // "foo"
箭头函数
使用“箭头”(=>)定义函数,圆括号代表参数部分。
let sum = (num1, num2) => num1 + num2;const isEven = n => n % 2 == 0;const square = n => n * n;// 简化回调函数[1,2,3].map(function (x) {return x * x;});[1,2,3].map(x => x * x);
如果箭头函数直接返回一个对象,必须在对象外面加上括号。
// 报错let getTempItem = id => { id: id, name: "Temp" };// 不报错let getTempItem = id => ({ id: id, name: "Temp" });
使用的注意点:
(1)函数体内的this对象,是定义时所在的对象,而不是使用时所在的对象;
(2)不可以当作构造函数(不可以使用new命令);
(3)不可以使用arguments对象,如果要用,可以用rest代替;
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
对apply、call和bind的回顾
三种写法用于显式绑定this对象。
apply方法的第一个参数是要绑定给this的值,第二个参数是一个参数数组。call方法第一个参数是要绑定给this的值,从第二个参数开始传入参数列表。bind方法第一个参数是this的指向,从第二个参数开始传入的参数列表,返回值是函数。【注意:bind方法所创建的新函数的this值是传递给bind()的第一个参数,而其余参数则作为新函数的参数】
// bindfunction fn(a, b, c) {return a + b + c;}var _fn = fn.bind(null, 10);var ans = _fn(20, 30); // 60
双冒号运算符
双冒号运算符(::)又称函数绑定运算符,其左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。
foo::bar;// 等同于bar.bind(foo);foo::bar(...arguments);// 等同于bar.apply(foo, arguments);
5. 数组
一些常用的方法
数组求最大值:
var arr = [1, 2, 3, 89, 46]// applyvar maxApply = Math.max.apply(null,arr) // 89// callvar maxCall = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4]) // 89// spread...let maxSpread = Math.max(...arr) // 89
数组追加:
// apply// 注:push()方法的返回值是新的长度var arr1 = [1,2,3];var arr2 = [4,5,6];var total = [].push.apply(arr1, arr2); // 6// 也可以用Array.prototype.push.apply(arr1, arr2);console.log(arr1) // [1, 2, 3, 4, 5, 6]console.log(arr2) // [4, 5, 6]// spreadarr1.push(...arr2);
数组复制:
const a1 = [1, 2];const a2 = a1;a2[0] = 2;a1 // [2, 2]// 直接复制仅复制了指向底层数据结构的指针,而非克隆一个全新的数组。const a3 = [...a1];a3 // [1, 2]
数组合并(浅拷贝):
const arr1 = ['a', 'b'];const arr2 = ['c'];const arr3 = ['d', 'e'];// ES5arr1.concat(arr2, arr3);// [ 'a', 'b', 'c', 'd', 'e' ]// ES6[...arr1, ...arr2, ...arr3]// [ 'a', 'b', 'c', 'd', 'e' ]
字符串转数组
[...'hello']// [ "h", "e", "l", "l", "o" ]
Array.of()
Array.of方法用于将一组值转换为数组。
Array.of(3, 11, 8) // [3,11,8]Array.of(3) // [3]
Array.from()
Array.from方法用于将类似数组的对象(Array-Like Objects,例如NodeList,arguments,字符串等具有length属性的对象)和可遍历的对象(Iterable Objects,例如Map和Set等)转为真正的数组。
// NodeList对象let ps = document.querySelectorAll('p');Array.from(ps).filter(p => {return p.textContent.length > 100;});// arguments对象function func1(a, b) {console.log(arguments[0]);console.log(arguments[1]);let args = Array.from(arguments);console.log(args)}func1(1, 2); /*> 1> 2> [1, 2] */
6. Promise对象
7. Iterator
8. Generator函数
Generator 函数是 ES6 提供的一种异步编程解决方案。
执行 Generator 函数会返回一个遍历器对象,它可以依次遍历 Generator 函数内部的每一个状态。
Generator 函数比普通函数多了两个特征。一是function关键字与函数名之间有一个星号;二是函数体内部使用yield表达式,定义不同的内部状态。
调用 Generator 函数后并不执行函数,也不返回函数运行结果,而返回一个指向内部状态的指针对象(遍历器对象),下一步必须调用遍历器对象的next方法,使得指针移向下一个状态。
每次调用遍历器对象的next方法,就会返回一个有着value和done两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。
