说一说ES6中的箭头函数?

箭头函数定义:ES6中允许使用(=>)来定义函数。箭头函数相当于箭头函数,并且简化了函数定义。

箭头函数有两种格式:当函数体是单条语句的时候可以省略{}和return;另一种是包含多条语句,不可以省略{}和return。

    let foo = (name) => console.log(name);
    foo('lalala')

    let foo1 = (name) => {
      if (name) return `我是${name}`
      return 'liyou';
    }
    console.log(foo1());//liyou
    console.log(foo1('猪猪侠'));//猪猪侠

这里需要注意的是如果箭头函数返回的是一个字面量对象,则需要用括号包裹该字面量对象返回

    let foo2 = (name) => ({
      a:1,
      b:2,
      name
    })
    console.log(foo2('zhuzhuxia'));

箭头函数与普通函数的区别:

声明方式不同,匿名函数:声明一个普通函数需要奥使用关键字function来完成,并且function既可以声明一个具名函数也可以声明一个匿名函数;声明一个箭头函数则只需要使用箭头就可以,无需使用关键词function,比普通函数声明更简洁;箭头函数只能声明匿名函数,但可以通过表达式的方式让箭头函数具名;

this指向不同:对与普通函数来说,内部的this指向函数运行时所在的对象,但是这一点在箭头函数上不成立。它没有自己的this对象,内部的this就是定义时上层作用域中的this。也就是说,箭头函数内部的this指向是固定的,相比之下,普通函数的this指向是可变的。

    var age = 18;
    var person = {
      age:20,
      sayAge:function() {
        console.log('age',this.age);
      },
      sayAge1:() => {
        console.log('age',this.age);
      }
    }
    person.sayAge();//20
    person.sayAge1();//18

箭头函数的this永远不会改变,call、apply、bind也无法改变:我们可以通过call、apply、bind来改变普通函数的this指向,但是由于箭头函数的this指向在它定义时就已经确定了,永远指向它定义时的上层作用域中的this,所以使用这些方法永远也改变不了箭头函数的this指向;

    var age = 18;
    var person = {
      age:20,
      sayAge:function() {
        console.log('age',this.age);
      },
      sayAge1:() => {
        console.log('age',this.age);
      }
    }
    person.sayAge.call({age:30});//'age' 30
    person.sayAge1.call({age:30});//'age' 18

箭头函数没有原型prototype:

    var age = 18;
    var person = {
      age:20,
      sayAge:function() {
        console.log('age',this.age);
      },
      sayAge1:() => {
        console.log('age',this.age);
      }
    }

    console.log(person.sayAge.prototype);//{constructor: ƒ}
    console.log(person.sayAge1.prototype);//undefined

箭头函数不能当做一个构造函数:因为箭头函数没有自己的this,它的this其实是继承了外层执行环境中的this,且this指向永远不会改变,并且箭头函数没有原型prototype,没法让他的实例的__proto__属性指向构造函数的prototype,所以箭头函数就无法作为构造函数,用new调用时会报错。

    var fn = (name) => {
      console.log('name',name);
    }
    const f = new fn('lalala')

new内部实现的过程:1、新建一个空对象;2、链接到原型;3、绑定this,执行构造函数;4、返回新对象;

    function myNew() {
      // 1、新建一个空对象
      let obj = {}
      // 2、获得构造函数
      let con = arguments.__proto__.constructor
      // 3、链接原型
      obj.__proto__ = con.prototype
      // 4、绑定this,执行构造函数
      let res = con.apply(obj,arguments)
      // 5、返回新对象
      return typeof res === 'object' ? res : obj
    }

 没有new.target:new是从构造函数生成实例对象的命令。ES6为new命令引入了一个new.target属性,这个属性一般用在构造函数中,返回new调用的那个构造函数。如果构造函数不是通过new命令或者Reflect。construct()调用的,new.target会返回undefined,所以这个属性可以用来确定搜早函数是怎么调用的。

 function fn(name) {
      console.log('fn:', new.target)
    }

    fn('liyou') // undefined
    new fn('liyou');/*fn: ƒ fn(name) {
                                console.log('fn:', new.target)
                              }*/

注意:new.target属性一般用在构造函数中,返回new调用的那个构造函数;箭头函数的this指向全局对象,在箭头函数中使用new.target会报错;箭头函数的this指向普通函数,他的new.target 就是指向该普通函数的引用;

箭头函数没有自己的arguments:箭头函数处于全局作用域中,没有arguments;

let fn = name => {
    console.log(arguments)
}
let fn2 = function(name) {
    console.log(arguments)
}
fn2() // Arguments [callee: ƒ, Symbol(Symbol.iterator): ƒ]
fn()  // 报错 Uncaught ReferenceError: arguments is not defined

箭头函数处于普通函数的函数作用域中,arguments则是上层普通函数的arguments

let fn2 = function(name) {
    console.log('fn2:',arguments)
    let fn = name => {
        console.log('fn:',arguments)
    }
    fn()
}
fn2('liyou')

箭头函数可以用rest参数代替arguments

let fn3 = (a,...arr) => {
    console.log(a,arr) //1, [2,3,4,5,6]
}

fn3(1,2,3,4,5,6)

箭头函数不能重复函数参数名称

function fn(name,name) {
    console.log('fn2:',name)
}
let fn2 = (name,name) => {
    console.log('fn',name)
}
fn('nan','jiu') // 'jiu'
fn2('nan','jiu') // 报错

不可以使用yield命令,因此箭头函数不能用作Generator函数

箭头函数不适用的场景:

对象方法,且方法中使用了this:

var name = '猪猪侠'
var person = {
    name: 'zhuzhuxia',
    say: function() {
        console.log('say:',this.name)
    },
    say2: () => {
        console.log('say2:',this.name)
    }
}

person.say() // say: zhuzhuxia
person.say2() //say2: 猪猪侠

当函数需要动态this时

var button = document.querySelector('.btn');
button.addEventListener('click', () => {
  this.classList.toggle('on');
});

这里很显然会报错,因为按钮点击的回调是一个箭头函数,而箭头函数内部的this永远都是指向它的上层作用域中的this,在这里就是window,所以会报错。这里只需要将箭头函数改成普通函数就能正常调用了!

巩固知识点:

    var name = '猪猪侠'
    function Person(name) {
      this.name = name
      this.say1 = function () {
        console.log(this.name);
      }
      this.say2 = () => console.log(this.name);
      this.say3 = function () {
        return function () {
        console.log(this.name);
        }
      }
      this.say4 = function () {
        return () => {
        console.log(this.name);
        }
      }
    }

    var person1 = new Person('zhu')
    var person2 = new Person('xia')

    person1.say1();//'zhu'
    person1.say1.call(person2);//'xia'

    person1.say2();//'zhu'
    person1.say2.call(person2);//'zhu'

    person1.say3()();//'猪猪侠'
    person1.say3.call(person2)();//'猪猪侠'
    person1.say3().call(person2);//'xia'

    person1.say4()();//'zhu'
    person1.say4.call(person2)();//'xia'
    person1.say4().call(person2);//'zhu'

解析:

全局代码执行,person1 = new Person('zhu'),person2 = new Person('xia')执行完,person1中的this.namezhuperson2中的this.namexia,OK这一点清楚后,继续往下看:

执行person1.foo1()foo1为普通函数,所以this应该指向person1,打印出zhu

执行person1.foo1.call(person2)foo1为普通函数,并且用call改变了this指向,所以它里面的this应该指向person2,打印出xia

执行person1.foo2()foo2为箭头函数,它的this指向上层作用域,也就是person1,所以打印出zhu

执行person1.foo2.call(person2),箭头函数的this指向无法使用call改变,所以它的this还是指向person1,打印出zhu

执行person1.foo3()(),这里先执行person1.foo3(),它返回了一个普通函数,接着再执行这个函数,此时就相当于在全局作用域中执行了一个普通函数,所以它的this指向window,打印出猪猪侠

执行person1.foo3.call(person2)()这个与上面类似,也是返回了一个普通函数再执行,其实前面的执行都不用关心,它也是相当于在全局作用域中执行了一个普通函数,所以它的this指向window,打印出猪猪侠

执行person1.foo3().call(person2)这里就是把foo3返回的普通函数的this绑定到person2上,所以打印出xia

执行person1.foo4()(),先执行person1.foo4()返回了一个箭头函数,再执行这个箭头函数,由于箭头函数的this始终指向它的上层作用域,所以打印出zhu

执行person1.foo4.call(person2)(),与上面类似只不过使用call把上层作用域的this改成了person2,所以打印出xia

执行person1.foo4().call(person2)这里是先执行了person1.foo4(),返回了箭头函数,再试图通过call改变改变该箭头函数的this指向,上面我们说到箭头函数的this始终指向它的上层作用域,所以打印出zhu

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值