箭头函数

92 阅读4分钟

先说结论

  1. 箭头函数没有自己的this,内部的this值继承自定义时外部作用域的this,是静态的
  2. 箭头函数不能通过call、apply、bind来改变this指向
  3. 箭头函数不能当作构造函数
  4. 箭头函数没有prototype
  5. 箭头函数不能被当作生成器函数
  6. 箭头函数没有arguments,使用rest参数代替

具体分析

1. 没有自己的this值

箭头函数没有自己的this值,内部的this是定义函数时上层作用域的this值(继承定义时外部作用域的this)

普通函数

let obj={
  x:1,
  f:function(){
  console.log(this)
  console.log(this.x)
  }
}
obj.f()

image.png

当普通函数作为对象的属性值时,函数里面的this就指向当前对象

箭头函数

let obj={
  x:1,
  f:()=>{
  console.log(this)
  console.log(this.x)
  }
}
obj.f()

image.png 当箭头函数作为对象的属性值时,因为箭头函数没有自己的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

image.png

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

image.png

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)

image.png

经过验证,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

image.png

最终结果就是给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)

image.png

箭头函数

let add = ()=>{
  console.log(arguments)
}
add(12,2)

image.png

在箭头函数里使用arguments直接报未定义的错误

但是,当箭头函数外部存在普通函数时,此时的arguments变量就是外部的普通函数的,根据作用域链往上查找得到的

function sum(){
  return ()=>{
    console.log(arguments)
  }
}
sum(1,2)()

image.png 箭头函数没有arguments,那怎么获取到所有的参数呢? 可以通过rest参数(形式为...变量名

let add = (...args)=>{
  console.log(args)
}
add(12,2)

image.png

借助扩展运算符,将所有的参数都汇集到args中,就可以获取到参数了,这里的args是一个数组,可以直接使用数组的所有方法,arguments是类数组,想要使用数组的某些方法时需要转为数组才可使用