箭头函数

先来看一段代码:

var func = new function() { 
      this.a = "func"; 
    } 
 
    // var func2 = function(x) { 
    //     var a = "func2"; 
    //     alert(this.a);     // func           
    //     alert(x);          // func2
    // }
 
    // 箭头函数this指向对象本身
    let func2 = x => {
      let a = 'func2';
      alert(this.a)   // undefined
      alert(x)        // func2
    }
 
    // call改变this指向,将func2的this指向func
    func2.call(func, "func2");

 

一、什么是箭头函数,为什么使用箭头函数?

 

箭头函数就是函数的一种简写形式,使用括号包裹参数,跟随一个=>,紧接着是函数体。

 

ES6中,箭头函数的引入有两个方面的作用:一是更简短的函数书写,二是对this的词法解析。

 

二、箭头函数的this

 

箭头函数没有它自己的this值,箭头函数内的this值继承自外围作用域。
 
this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。正是因为它没有this,所以也就不能用作构造函数。
 
var col = 3
var obj = {
    col: 5,
    show: function () {
          console.log(this.col)
    }
}
obj.show()    // 5
 
分析:
     调用者是obj,所以this指向obj
 
var col = 3
var obj = {
    col: 5,
    show: () => console.log(this.col)
}
obj.show()    // 3
 
分析:
     因为是箭头函数,var定义的obj,作用域在全局,所以此时的this指向window
 
let col = 3
let obj = {
    col: 5,
    show: () => console.log(this.col)
}
obj.show()    // undefined
 
分析:
     因为是let声明,let、const、class命令声明的全局变量是不属于顶层对象的属性的,所以,this就既不指向window,也不指向obj

 

function Person() {
    // 构造函数 Person() 定义的 `this` 就是新实例对象自己
    this.age = 0;
    setInterval(function growUp() {
        // 在非严格模式下,growUp() 函数定义了其内部的 `this`为全局对象,
        // 不同于构造函数Person()的定义的 `this`
        this.age++;
    }, 3000);}

var p = new Person();

 

上面定时器的this并不是指向构造函数的this,这并不是我们想要的。所以想要定时器里面的this指向构造函数,我们可以通过把this的值赋值给变量,然后将该变量放到闭包中来解决。

 

function Person() {
    var self = this;
    // 也有人选择使用 `that` 而非 `self`, 只要保证一致就好.
    self.age = 0;
    setInterval(function growUp() {
        // 回调里面的 `self` 变量就指向了期望的那个对象了
        self.age++;
    }, 3000);}

var p = new Person();

 

我们还可以使用bind函数,把期望的this值传递给growUp函数。当然,我们可以使用箭头函数轻松实现,箭头函数会捕获他所在的上下文的this值,作为自己的this值。

 

function Person() { 
    this.age = 0; 
    setInterval(() => {
        // 回调里面的 `this` 变量就指向了期望的那个对象了
        this.age++;
    }, 3000);}

var p = new Person();

 

call和apply调用对箭头函数this的影响:

 

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 ——译者注)

 

分析如下:

 

1、adder.add(1)执行add函数,add返回f(a)也就是f(1)的调用,执行f()函数,f是箭头函数写法,this.base中的this指向对象本身,所以输出2

 

2、adder.addThruCall(1)执行addThruCall,返回f.call(b, a),call本质是将f的this指向b,所以此时的this.base理应是2,但是因为是箭头函数的写法,this已经在词法层面完成了绑定,通过call或者apply方法调用的时候,只是出入了参数,并没有改变this的指向,所以此时的值还是2.

 

三、arguments

箭头函数不会在其内部暴露出参数,也就是说没有自己的arguments:

 

var arguments = 42;var arr = () => arguments;

arr(); // 42

function foo() {
  var f = (i) => arguments[0]+i; 
  // foo函数的间接参数绑定
  return f(2);}

foo(1); // 3

 

不过在大多数情形下,rest参数可以给出一个解决方案:

 

function foo() { 
  var f = (...args) => args[0]; 
  return f(2); 
}

foo(1); 
// 2

 

四、注意事项

 

1、箭头函数不能用作构造器,和new一起用就会报错

 

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

 

2、箭头函数没有原型属性

 

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

 

3、箭头函数既支持简写也支持常规编写

 

var func = x => x * x;                 
// 简写函数 省略return

var func = (x, y) => { return x + y; };
//常规编写 明确的返回值
原文地址:https://www.cnblogs.com/sup9278/p/7448461.html