普通函数和箭头函数的区别
不同点
- 写法
- 箭头函数使用箭头定义
- 普通函数没有使用箭头定义
- 匿名函数
- 箭头函数都是匿名函数
- 普通函数可以是匿名函数,也可以是具名函数
- this指向
- 普通函数中
- 在普通函数中,this 的指向(执行上下文)是动态的,其值取决于函数是如何被调用的:
- 直接调用时,其指向为全局对象(严格模式下为 undefined)
- 方法调用时,其指向为调用该方法的对象
- new 调用时,其指向为新创建的实例对象
- call、apply、bind 调用时,其指向为三种方法的第一个参数
- 在普通函数中,this 的指向(执行上下文)是动态的,其值取决于函数是如何被调用的:
- 无论如何执行或在何处执行,箭头函数内部的 this 值始终等于外部函数的值,即箭头函数不会改变 this 的指向,
- 注意:由于箭头函数没有自己的 this 指针,通过 call() 、 apply() 和 bind() 方法调用时,只能传递参数,而不能绑定 this,他们的第一个参数会被忽略。
- 普通函数中
- 构造函数
- 在 JavaScript 中,函数和类的继承是通过 prototype 属性实现的,且 prototype 拥有属性 constructor 指向构造函数
- 而采用箭头函数定义函数时,其是没有 prototype 属性的,也就无法指向构造函数。
- 没有自己的 this,也就意味着无法调用 apply、call 等
- 没有 prototype 属性,而 new 命令在执行时需要将构造函数的 prototype 赋值给新的对象的 proto。
function newOperator(Con, ...args) { let obj = {}; Object.setPrototypeOf(obj, Con.prototype); // 相当于 obj.__proto__ = Con.prototype let result = Con.apply(obj, args); return result instanceof Object ? result : obj; }更具体的原因是,JavaScript函数两个内部方法: [[Call]] 和 [[Construct]],当函数被直接调用时执行的是 [[Call]] 方法,即直接执行函数体,而 new 调用时是执行的 [[Construct]]方法。箭头函数没有 [[Construct]]方法,因此不能被用作构造函数进行实例化。
为什么箭头函数不能构造实例对象
function newFunc(father, ...rest) {
var result = {}; // 1. 创建空对象result
result.__proto__ = father.prototype; // 2. 将空对象result的原型链指向构造器father的原型
var result2 = father.apply(result, rest); // 3. 将fathe函数中的this指向result【若此处father为箭头函数而没有自己的this,call()函数无法改变箭头函数的指向,也就无法指向result。】
if (
(typeof result2 === 'object' || typeof result2 === 'function') &&
result2 !== null
) {
return result2;
}
return result;
}
普通函数
this的优先级如下
- new
- call bind apply 等硬绑定
- 上下文对象中调用(隐式绑定)
- 默认绑定,即指枪全局对象