1. 语法

按常规语法定义函数:

function funcName(params) {
    return params + 2;
}
funcName(2);

该函数改成箭头函数:

var funcName = params => params + 2;
funcName(2);

我们来深入了解箭头函数的语法:

parameters => {
    statements;
};

如果没有参数,那么可以进一步简化:

() => {
    statements;
};

如果只有一个参数,可以省略括号:

parameters => {
    statements;
};  

如果函数体只有一句返回值,可以省略大括号和return

parameters => true; 
等价于:
parameters => { return true;};

2. 箭头函数和普通函数的区别

(1) 没有this

箭头函数没有this,需要通过查找作用域链来确定this的值。因此如果箭头函数被非箭头函数包裹,this绑定的就是最近一层非箭头函数的this.

下面的例子是经常遇到的:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function () {
       console.log(this); // this指向的是window或者undefined
            return new Date().getFullYear() - this.birth;
        };
        return fn();
    }
};
obj.getAge(); //NaN

  

上面的输出结果是NaN,因为fn是函数表达式,会有一个this指向它,不能拿到外层函数的this,而fn没有birth属性,所以this.birth是undefined,因此输出结果是NaN。

要修复这个问题,可以把外层的this保存起来,然后再内层函数使用:

var obj = {
    birth: 1990,
    getAge: function () {
        console.log(this.birth);
	var self = this;
        var fn = function () {
            return new Date().getFullYear() - self.birth;
        };
        return fn();
    }
};
obj.getAge(); // 29

  

或者通过call或者apply将this传到内部函数中:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function () {
            return new Date().getFullYear() - this.birth; 
        };
        return fn.apply(this); // 或者:return fn.call(this);
    }
};
obj.getAge(); // 29  

 现在可以通过箭头函数的方法解决了:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => new Date().getFullYear() - this.birth; // this.birth仍是1990,因为this还是外部函数的this
        return fn();
    }
};
obj.getAge(); // 29  

但是如果把外部函数也改成箭头函数,结果又是不一样的了:

var obj = {
    birth: 1990,
    getAge:  (year) => {
        var b = this.birth; // 1990
        var fn = () => {
	  console.log(this); // window
	    return new Date().getFullYear() - this.birth; // this.birth是undefined
      }
        return fn();
    }
};
obj.getAge(); // NaN

 

因为外部函数也是箭头函数,所以不会有this, 就会按照作用域链继续往上寻找,这段代码的往上寻找,找到的this是window;

所以箭头函数this指向的关键是找到最近的非箭头函数的this

 

(2) 没有arguments

箭头函数没有自己的arguamnets对象, 但是箭头函数可以访问外围函数的arguments对象;看下面两个例子:

var Foo = () => {console.log(arguments)};
Foo(); // ReferenceError: arguments is not defined
function myFunc(age) {
	var Foo = () => {console.log(arguments)};
	return Foo();
	
}
myFunc(12); 

代码执行结果:

 

第一段代码:输出箭头函数的argument报错,说明箭头函数是没有arguments对象的

第二段代码:在箭头函数中输出的arguments对象信息name为myFunc, 说明箭头函数中的是外围函数的arguments, 而第一段代码没有外围函数,所以会报错。

 

(3) 不能通过new关键字调用

js的函数有两个内部方法:[[call]]和[[Construct]]

当通过new调用构造函数时,执行[[Construct]]方法,创建一个实例对象,然后再执行函数体,将this绑定到实例上。当直接调用的时候,执行[[call]]方法,直接执行函数体。

箭头函数并没有[[Construct]]方法,不能被用作构造函数,因此通过new的方式调用,会报错。

var Fun = () => {};
var fun = new Fun(); // typeError: Fun is not a constructor

 

(4) 没有原型

由于不能使用new调用箭头函数,所以也没有构建原型的需求,于是箭头函数也不存在prototype这个属性。

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

(5) 没有super

箭头函数没有原型,所以不能通过super来访问原型的属性,所以箭头函数是没有super的,super的值由最近一层非箭头函数决定。

posted on 2019-05-13 17:48  yyy_鸳鸯  阅读(147)  评论(0编辑  收藏  举报