let 关键字允许你声明一个作用域被限制在块级中的变量、语句或表达式。

let 与 var 关键字的区别

(1)var 声明的变量只能是全局或者整个函数块的,let将变量的作用域限制在块内({…}内)。

(2)var 声明的变量会提升,let 不存在变量提升。变量提升即变量可以在声明之前使用,值为undefined。


console.log(x);
var x = 1024;

Result: unfefined

Reason:

var x;
console.log(x);
x = 1024.

(3)var 声明的变量可以重复声明,let 声明的变量不可以。

(4)使用 let 声明的变量不可以再用 var 声明。

const 定义的对象,可以修改其 value 值


const object = {key: "value"};

object.key = "newValue";

console.log(object);

模版字符串


const str = "World";

const result = `Hello ${str}`;

函数默认参数

函数默认参数允许在没有值或undefined被传入时使用默认形参。


function multiply(a, b = 1) {
  return a * b;
}

console.log(multiply(5, 2));  // 10

console.log(multiply(5));   // 5

console.log(multiply(5, null));   // 0

箭头函数

更简短的函数且不绑定 this。

在箭头函数出现之前,每一个新函数根据它是如何被调用的来定义这个函数的 this 值:

(1)如果该函数是一个构造函数,this 指针指向一个新对象;

(2)在严格模式下的函数调用,this 指向 undefined;

(3)如果该函数是一个对象的方法,则它的 this 指针指向这个对象。


const arr = [1, 2, 3, 4, 5];

arr.map(function(item){
  return item * 2;
})

// 使用箭头函数

arr.map((item) => {
  return item * 2;
})

// 当箭头函数只有一个参数时,可以省略参数的圆括号

arr.map(item => {
  return item * 2;
})

// 当箭头函数的函数体只有一个 `return` 语句时,可以省略 return 关键字和方法体的花括号

arr.map(item => item * 2);

展开语法

Spread Operator 即3个点 …,有几种不同的使用方法。

等价于 apply 的方式


function myFunction(x,y,z) { }

var args = [0,1,2];

myFunction(...args);

数组拷贝(仅拷贝了一层)


var arr = [1,2,3,[5,6]];

var arr2 = [...arr];

arr.push(4);  // [1,2,3,[5,6,4]]

连接多个数组、对象


const todo = ['Learn ES6'];

const todo2 = [...todo, 'Learn React'];

var arr = [0,1];

var arr2 = [2,3];

var arr3 = [...arr, ...arr2];

var obj = { study: 'es6', time: 13 };

var obj2 = { study: 'react', time: 14};

var obj3 = { ...obj, ...obj2 };  // { study: 'react', time: 13, time: 14 };

剩余语法

剩余语法(Rest syntax)看起来和展开语法完全相同,不同点在于,剩余参数用于解构数组和对象。

从某种意义上讲,剩余语法与展开语法是相反的:展开语法将数组展开为其中的单个元素,而剩余语法则是将多个元素收集起来并“凝聚”为单个元素。


function sum(...rest) {
  return rest.reduce((pre, cur) => {
    return pre + cur;
  });
}

console.log(sum(1,2,3))  // 6

面试题:new 关键字背后的原理


// 构造函数
function Person(name, age) {
  this.name = name;
  this.age = age;
  this.say = function() {
    return this.name;
  }
}

// let person = new Person('HelloWorld', 7);

// 实现一个 new 关键字
function newFunc(Constructor, ...args) {  // args 表示除 Person 外的剩余入参

  // 创建对象
  let obj = new Object();

  // 将 obj 的 __proto__ 属性绑定到构造函数的 prototype 属性上
  // 对于每一个对象都有 __proto__ 属性,而只有函数才有 prototype 属性 
  obj.__proto__ = Constructor.prototype;

  // Constructor 的 this 指向 obj
  let result = Constructor.apply(obj, args);

  // 如果构造函数有返回值,则返回构造函数的返回值;若没有,则返回 obj
  return result || obj;
}

let person = newFunc(Person, 'HelloWorld', 7);

person.say();