1. let

let相较于var的最大好处是创建了块级作用域,此外也不存在变量提升

  1. {
  2. let a = 10;
  3. var b = 1;
  4. }
  5. console.log(a) // ReferenceError: a is not defined.
  6. console.log(b) // 1

没有块级作用域所引起的问题:用来计数的循环变量被泄露为全局变量。

  1. var s = 'hello';
  2. for (var i = 0; i < s.length; i++) {
  3. console.log(s[i]);
  4. }
  5. console.log(i); // 5

2. const

  1. const声明一个只读的常量。一旦声明,常量的值就不能改变。
  2. const一旦声明就必须立即初始化,不能留到以后赋值。
  3. const也有块级作用域,也不存在变量提升。

const本质上并不是保证变量的值不得改动,而是变量指向的那个内存地址不得改动。

  • 对于数值、字符串、布尔值等,值就保存在变量指向的那个内存地址,因此等同于常量。
  • 对于对象、数组,变量所保存的只是一个指针,const只能保证这个指针指向的对象不能改变,而指针所指向的对象的内部属性是可以改变的。> 盒子不能变,而盒子里面的东西可以变。

3. 字符串

几个新增的函数:at()startsWith()endsWith()includes()repeat()padStart()padEnd()matchAll()

  1. //at
  2. '𠮷'.charAt(0) // "\uD842"
  3. '𠮷'.at(0) // "𠮷"
  4. // startsWith、endsWith、includes
  5. let s = 'Hello world!';
  6. s.startsWith('world', 6) // true
  7. s.endsWith('Hello', 5) // true ,这里表示针对前n个字符
  8. s.includes('Hello', 6) // false
  9. // repeat
  10. 'x'.repeat(3) // "xxx"
  11. // padStart、padEnd
  12. // 第一个参数指定字符串的最小长度,第二个参数是用来补全的字符串。
  13. 'x'.padStart(4, 'ab') // 'abax'
  14. 'x'.padEnd(4, 'ab') // 'xaba'

引入了使用反引号(`)的模板字符串。

4. 函数

参数的默认值

允许为参数设定默认值,并可直接写在参数定义的后面。

  1. function log(x, y = 'World') {
  2. console.log(x, y);
  3. }
  4. log('Hello') // Hello World
  5. log('Hello', 'China') // Hello China
  6. log('Hello', '') // Hello

rest / spread操作符(…)

rest被用于函数传参,是为了获取函数的多余参数,在传参时可把参数转为数组

  1. // rest参数的写法1
  2. const sortNumbers = (...numbers) => numbers.sort();
  3. sortNumbers(5,6,8,1,4) // [1, 4, 5, 6, 8]
  4. // rest参数的写法2
  5. function add(...values) {
  6. let sum = 0;
  7. for (var val of values) {
  8. sum += val;
  9. }
  10. return sum;
  11. }
  12. let add = sum(...values) =>(values.sum());
  13. add(2, 5, 3) // 10

spread则用于函数调用,其参数是数组,效果是将其展开为独立元素。

  1. function foo(x,y,z) {
  2. console.log(x,y,z);
  3. }
  4. let arr = [1,2,3];
  5. foo(...arr); // 1 2 3

name属性

.name方法返回函数的函数名。

  1. function foo() {}
  2. foo.name // "foo"

箭头函数

使用“箭头”(=>)定义函数,圆括号代表参数部分。

  1. let sum = (num1, num2) => num1 + num2;
  2. const isEven = n => n % 2 == 0;
  3. const square = n => n * n;
  4. // 简化回调函数
  5. [1,2,3].map(function (x) {
  6. return x * x;
  7. });
  8. [1,2,3].map(x => x * x);

如果箭头函数直接返回一个对象,必须在对象外面加上括号。

  1. // 报错
  2. let getTempItem = id => { id: id, name: "Temp" };
  3. // 不报错
  4. 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()的第一个参数,而其余参数则作为新函数的参数
  1. // bind
  2. function fn(a, b, c) {
  3. return a + b + c;
  4. }
  5. var _fn = fn.bind(null, 10);
  6. var ans = _fn(20, 30); // 60

双冒号运算符

双冒号运算符(::)又称函数绑定运算符,其左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。

  1. foo::bar;
  2. // 等同于
  3. bar.bind(foo);
  4. foo::bar(...arguments);
  5. // 等同于
  6. bar.apply(foo, arguments);

5. 数组

一些常用的方法

数组求最大值:

  1. var arr = [1, 2, 3, 89, 46]
  2. // apply
  3. var maxApply = Math.max.apply(null,arr) // 89
  4. // call
  5. var maxCall = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4]) // 89
  6. // spread...
  7. let maxSpread = Math.max(...arr) // 89

数组追加:

  1. // apply
  2. // 注:push()方法的返回值是新的长度
  3. var arr1 = [1,2,3];
  4. var arr2 = [4,5,6];
  5. var total = [].push.apply(arr1, arr2); // 6
  6. // 也可以用Array.prototype.push.apply(arr1, arr2);
  7. console.log(arr1) // [1, 2, 3, 4, 5, 6]
  8. console.log(arr2) // [4, 5, 6]
  9. // spread
  10. arr1.push(...arr2);

数组复制:

  1. const a1 = [1, 2];
  2. const a2 = a1;
  3. a2[0] = 2;
  4. a1 // [2, 2]
  5. // 直接复制仅复制了指向底层数据结构的指针,而非克隆一个全新的数组。
  6. const a3 = [...a1];
  7. a3 // [1, 2]

数组合并(浅拷贝):

  1. const arr1 = ['a', 'b'];
  2. const arr2 = ['c'];
  3. const arr3 = ['d', 'e'];
  4. // ES5
  5. arr1.concat(arr2, arr3);
  6. // [ 'a', 'b', 'c', 'd', 'e' ]
  7. // ES6
  8. [...arr1, ...arr2, ...arr3]
  9. // [ 'a', 'b', 'c', 'd', 'e' ]

字符串转数组

  1. [...'hello']
  2. // [ "h", "e", "l", "l", "o" ]

Array.of()

Array.of方法用于将一组值转换为数组

  1. Array.of(3, 11, 8) // [3,11,8]
  2. Array.of(3) // [3]

Array.from()

Array.from方法用于将类似数组的对象(Array-Like Objects,例如NodeList,arguments,字符串等具有length属性的对象)和可遍历的对象(Iterable Objects,例如Map和Set等)转为真正的数组。

  1. // NodeList对象
  2. let ps = document.querySelectorAll('p');
  3. Array.from(ps).filter(p => {
  4. return p.textContent.length > 100;
  5. });
  6. // arguments对象
  7. function func1(a, b) {
  8. console.log(arguments[0]);
  9. console.log(arguments[1]);
  10. let args = Array.from(arguments);
  11. console.log(args)
  12. }
  13. func1(1, 2); /*
  14. > 1
  15. > 2
  16. > [1, 2] */

6. Promise对象

7. Iterator

8. Generator函数

Generator 函数是 ES6 提供的一种异步编程解决方案。

执行 Generator 函数会返回一个遍历器对象,它可以依次遍历 Generator 函数内部的每一个状态。

Generator 函数比普通函数多了两个特征。一是function关键字与函数名之间有一个星号;二是函数体内部使用yield表达式,定义不同的内部状态。

调用 Generator 函数后并不执行函数,也不返回函数运行结果,而返回一个指向内部状态的指针对象(遍历器对象),下一步必须调用遍历器对象的next方法,使得指针移向下一个状态。

每次调用遍历器对象的next方法,就会返回一个有着valuedone两个属性的对象。value属性表示当前的内部状态的值,是yield表达式后面那个表达式的值;done属性是一个布尔值,表示是否遍历结束。