先说结论
- 箭头函数没有自己的this,内部的this值继承自定义时外部作用域的this,是静态的
- 箭头函数不能通过call、apply、bind来改变this指向
- 箭头函数不能当作构造函数
- 箭头函数没有prototype
- 箭头函数不能被当作生成器函数
- 箭头函数没有arguments,使用rest参数代替
具体分析
1. 没有自己的this值
箭头函数没有自己的this值,内部的this是定义函数时上层作用域的this值(继承定义时外部作用域的this)
普通函数
let obj={
x:1,
f:function(){
console.log(this)
console.log(this.x)
}
}
obj.f()
当普通函数作为对象的属性值时,函数里面的this就指向当前对象
箭头函数
let obj={
x:1,
f:()=>{
console.log(this)
console.log(this.x)
}
}
obj.f()
当箭头函数作为对象的属性值时,因为箭头函数没有自己的this,this值取自定义箭头函数时上层作用域的this,这里就指向了全局的window
2. 不能使用call、apply、bind来改变this指向
因为没有自己的this值,所以使用call,apply,bind等改变this指向的方法时是无效的
普通函数
var x = 7
let obj={
x:1,
f:function(){
console.log(this.x)
}
}
let obj1 = {x:2}
obj.f.call(obj1) // 2
call的第一个参数,就是我们指定的this所要指向的对象,所以在执行obj.f的时候,f中的this指向的是obj1,最终打印出2
箭头函数
var x = 7
let obj={
x:1,
f:()=>{
console.log(this.x)
}
}
let obj1 = {x:2}
obj.f.call(obj1) // 7
obj.f中this是window,使用call是想将this指向obj1,想得到结果是输出obj1中的x,但是最后输出的还是window.x,this指向是没有改变的,所以箭头函数是不能通过call、apply、bind来改变this值指向的,它内部的this是一个静态值,确定以后就不会改变了
3. 不能用做构造函数
我们先来自己实现一个new,看看构造函数在new的过程中是如何使用的
function nyNew(constructor,...args){
// 创建一个空对象并链接到构造函数的原型对象
const instance = Object.create(constructor.prototype);
// 将构造函数的上下文绑定到新对象
const result = constructor.apply(instance, args);
// 如果构造函数返回了一个对象,则返回该对象
if (typeof result === 'object' && result !== null) {
return result;
}
// 否则返回新对象实例
return instance;
}
上面的myNew是我们自己实现的new,先验证一下是否有效
function Person(name,age){
this.name=name
this.age= age
}
let newPerson = myNew(Person,'xiaofan','17')
console.log(newPerson)
经过验证,myNew可以实现和new一样的功能,里面使用了apply想要在执行构造函数时将this改为instance的this,但是在第二条中,我们刚证实了箭头函数不能通过从call、apply、bind改变this指向,所以构造函数是箭头函数时, const result = constructor.apply(instance, args);
箭头函数
let Person= (name,age)=>{
this.name=name
this.age= age
}
let newPerson = myNew(Person,'xiaofan','17')
console.log(newPerson)
箭头函数Person中的this是window,在调用myNew函数时,apply没办法改变this指向,所以执行Person时的this还是指向window
最终结果就是给window添加了name属性和age属性
4.没有prototype
每一个函数被当作构造函数使用时,都会被自动添加一个prototype属性,但是箭头函数是不能作为构造函数的,所以它没有prototype属性
5.不能使用yield关键字,不能用做Generator函数
普通函数用做Generator函数
function* generatorFunction() {
yield 1;
yield 2;
}
const generator = generatorFunction();
console.log(generator.next().value); // 输出 1
console.log(generator.next().value); // 输出 2
箭头函数不支持 function* 语法和 yield 关键字
由于箭头函数没有内部的执行上下文和 yield 关键字的支持,它们无法直接实现生成器函数的功能。生成器函数需要特定的语法和语义来处理暂停和恢复执行的行为,而箭头函数不提供这些功能。
6. 没有自己的arguments
普通函数
let add = function (){
console.log(arguments)
}
add(12,2)
箭头函数
let add = ()=>{
console.log(arguments)
}
add(12,2)
在箭头函数里使用arguments直接报未定义的错误
但是,当箭头函数外部存在普通函数时,此时的arguments变量就是外部的普通函数的,根据作用域链往上查找得到的
function sum(){
return ()=>{
console.log(arguments)
}
}
sum(1,2)()
箭头函数没有arguments,那怎么获取到所有的参数呢?
可以通过rest参数(形式为
...变量名)
let add = (...args)=>{
console.log(args)
}
add(12,2)
借助扩展运算符,将所有的参数都汇集到args中,就可以获取到参数了,这里的args是一个数组,可以直接使用数组的所有方法,arguments是类数组,想要使用数组的某些方法时需要转为数组才可使用