首先:我们先考虑一下这个箭头函数没有自己的thisargumentssuper>首先:我们先考虑一下这个箭头函数没有自己的thisargumentssuper new.target`是什么意思?带着问题去看下面的内容会更事半功倍。

一、语法

1.基础语法
(参数1, 参数2, …, 参数N) => { 函数声明 }

//相当于:(参数1, 参数2, …, 参数N) =>{ return 表达式; }
(参数1, 参数2, …, 参数N) => 表达式(单一)

// 当只有一个参数时,圆括号是可选的:
(单一参数) => {函数声明}
单一参数 => {函数声明}

// 没有参数的函数应该写成一对圆括号。
() => {函数声明}
2.高级语法
//加括号的函数体返回对象字面表达式:
参数=> ({foo: bar})

//支持剩余参数和默认参数
(参数1, 参数2, ...rest) => {函数声明}
(参数1 = 默认值1,参数2, …, 参数N = 默认值N) => {函数声明}

//同样支持参数列表解构
let f = ([a, b] = [1, 2], {x: c} = {x: a + b}) => a + b + c;
f();  // 6

二、没有自己的this,不绑定this

我们先看一下下面的代码,

const Person = {
    'name': 'little bear',
    'age': 18,
    'sayHello': function() {
        setTimeout(function() {
            console.log('我叫' + this.name + '我今年' + this.age + '岁!')
        }, 1000)
    }
}
console.log(Person.sayHello()) //我叫我今年undefined岁!

打印的结果是undefined,知道是什么原因吗?当然,setTimeout方法里面的this指向的是window,所以是undefined,sayhello方法中的this才是指向Person的,如果按照下面的方式将sayHello中的this赋值给封闭变量self,就可以正确打印结果了

const Person1 = {
    'name': 'little bear',
    'age': 18,
    'sayHello': function() {
        var self = this;
        setTimeout(function() {
            console.log('我叫' + self.name + '我今年' + self.age + '岁!')
        }, 1000)
    }
}
console.log(Person1.sayHello());//我叫little bear我今年18岁!

我们再看一下下面的代码,想想打印的结果是什么呢?

const Person3 = {
    'name': 'little bear',
    'age': 18,
    sayHello() {
        setTimeout(() => {
            console.log('我叫' + this.name + '我今年' + this.age + '岁!')
        }, 1000)
    }
}
console.log(Person3.sayHello());//我叫little bear我今年18岁!

这个结果是否如你所料呢?

我们再看看下面的代码就应该好理解了

const Person5 = {
    'name': 'little bear',
    'age': 18,
    sayHello: () => {
        setTimeout(() => {
            console.log('我叫' + this.name + '我今年' + this.age + '岁!')
        }, 1000)
    }
}
Person5.sayHello();//我叫我今年undefined岁!

封闭函数的this指向的是外部对象windowsetTimeout继承上一层this,所以也是指向的window

通过 call 或 apply 调用

首先我们回顾一下 callapply

  1. 他们各自的定义:

    • apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。
    • call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。
  2. 它们的共同之处:

    都“可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象”。

  3. 它们的不同之处:

    • apply:最多只能有两个参数——新this对象和一个数组argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里。如果argArray不是一个有效的数组或arguments对象,那么将导致一个TypeError。如果没有提供argArray和thisObj任何一个参数,那么Global对象将被用作thisObj,并且无法被传递任何参数。
    • call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表。这个方法主要用在js对象各方法相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针。如果没有提供thisObj参数,那么 Global 对象被用作thisObj。

我们先来看一下下面的代码,思考一下打印的结果,

var adder = {
  base : 1,

  add : function(a) {
    var f = v => v + this.base;
    return f(a);
  },

  addThruCall: function(a) {
    var f = v => v + this.base;
    var b = {
      base : 2
    };

    return f.call(b, a);
  }
};

console.log(adder.add(1));         // 输出 2
console.log(adder.addThruCall(1)); // 仍然输出 2(而不是3 ——译者注)

结果:

三、不绑定arguments

我们都知道函数内部,argument是一个作为函数输入的值-原始数据或对象

var arguments = [5, 6, 7];

function person1(a, b, c) {
    console.log(arguments);
}
person1(1, 2);//arguments[1,2]

var arr1 = () => { return arguments; }
console.log(arr1());//[5,6,7]

var arr2 = (a) => { return arguments; }
console.log(arr2(1));//[5,6,7]

从上就可以看出,一般的函数是绑定了Arguments 对象,而箭头函数没有绑定

看下面的代码箭头函数中的arguments只是引用了封闭作用域内的arguments

var arguments = [1, 2, 3];
var arr = () => arguments[0];

arr(); // 1

function foo(n) {
  var f = () => arguments[0] + n; // 隐式绑定 foo 函数的 arguments 对象. arguments[0] 是 n
  return f();
}

foo(1); // 2

四、使用 new 操作符

箭头函数不能用作构造器,和 new一起用会抛出错误。

var Foo = () => {};
var foo = new Foo(); // TypeError: Foo is not a constructor

五、使用prototype属性

箭头函数没有prototype属性。

var Foo = () => {};
console.log(Foo.prototype); // undefined

六、使用 yield 关键字

yield关键字通常不能在箭头函数中使用(除非是嵌套在允许使用的函数内)。因此,箭头函数不能用作生成器。

点击可以查看更多详情

01-23 13:01