[toc] ## 1. 箭头函数和普通函数的区别 ### 1.1 this指向的不同 普通函数的this不是在定义时决定,取决于调用的对象以及环境。不像其他形式的函数,箭头函数并没有他们自己的执行上下文。实际上,这就意味着代码中的this和arguments都是继承自他们的父函数。 **箭头函数的this在定义时就已决定,指向被定义环境的执行上下文this**。 * 箭头函数的this指向定义时所在的外层第一个普通函数,跟使用位置没有关系 * 被继承的普通函数的this指向改变,箭头函数的this指向会跟着改变 **不能直接修改箭头函数的this指向**,我们可以通过间接的形式来修改箭头函数的指向:去修改被继承的普通函数的this指向,然后箭头函数的this指向也会跟着改变。 **箭头函数外层没有普通函数,严格模式和非严格模式下它的this都会指向window(全局对象)** ### 1.2 不绑定 arguments 参数 普通函数绑定了`arguments`,可以直通过`arguments`获取所有传递参数,箭头函数本身不绑定`arguments`,取而代之使用 `...rest` 参数解决,但如果箭头函数的 `this`如果指向普通函数,它的 `argumens` 继承于该普通函数。 ### 1.3 不可以作为构造函数 普通函数可以作为构造函数,使用`new`关键字,而**箭头函数是匿名函数,不能作为构造函数使用`new`关键字**。 无论箭头函数的 `this` 指向哪里,使用 `new` 调用箭头函数都会报错,因为箭头函数没有 `constructor`。 ```javascript let a = () => {}; let b = new a(); // a is not a constructor ``` **箭头函数不支持 `new.target`**,`new.target`是ES6新引入的属性,普通函数如果通过`new`调用,`new.target`会返回该函数的引用,此属性主要:用于确定构造函数是否为`new`调用的。 ### 1.4 没有原型属性 普通函数有原型`prototype`属性,箭头函数没有原型属性 ``` let a = () =>{}; console.log(a.prototype); // undefined ``` ### 1.5 箭头函数不能变量提升 普通函数可以变量提升,箭头函数不能变量提升,必须在定义之后调用 ### 1.6 箭头函数的注意事项 一条语句返回对象字面量,需要加括号,或者直接写成多条语句的`return`形式,否则像func中演示的一样,花括号会被解析为多条语句的花括号,不能正确解析 ``` var func1 = () => { foo: 1 }; // 想返回一个对象,花括号被当成多条语句来解析,执行后返回undefined var func2 = () => ({foo: 1}); // 用圆括号是正确的写法 var func2 = () => { return { foo: 1 // 更推荐直接当成多条语句的形式来写,可读性高 }; }; ``` 箭头函数在参数和箭头之间不能换行! ``` var func = () => 1; // 报错: Unexpected token => ``` 箭头函数的解析顺序相对靠前,虽然箭头函数中的箭头不是运算符,但箭头函数具有与常规函数不同的特殊运算符优先级解析规则,解析顺序相对 `||` 靠前。 ## 2. 箭头函数不适用场景 这里有许多箭头函数不推荐的场景,这种情况之下不仅没有帮助,而且还会造成不必要的麻烦。 * 在对象上定义函数 * 在原型上定义函数 * 动态上下文中的回调函数 * 箭头函数不能作为构造器。 JavaScript 会通过抛出异常的方式进行隐式地预防 * 太简短的(难以理解)函数