Li Mei

个人技术博客

嗨,我是李梅,一名前端开发者。


主要是记录个人对技术的理解和开发过程中遇到的问题,欢迎了解更多。

JS:箭头函数

先来看下ES6中箭头函数的基本语法:

let func = value => value;

相当于:

let func = function (value) {
    return value
}

如果需要传入多个参数:

let func = (value, num) => value * num;

上面箭头函数例子中都省略了return关键字和代码的花括号,在箭头函数中如果方法体中只有一行代码,可以省略关键字和方法体的花括号,直接简化成value => value

如果函数的代码块需要有多条语句:

let func = (value, num) => {
    return value * num;
}

如果需要返回一个对象,箭头函数的方法体必须放在大括号()中,这样做的原因是:没有大括号,JS引擎没办分区分是正常定义一个对象还是一个箭头函数体:

let func = (value, num) => ({ value: value, num: num }); //正确写法

let func = (value, num) => { value: value, num: num }; //会报错

与普通函数的区别

没有this

箭头函数式的this需要通过查找作用域链来确定,它的this是指包在它外面的作用域的this,我们来看下以下代码中的this分别指的是什么:

const obj = {
    a: function () {
        console.log(this); // obj
    },
    b: () => {
        console.log(this); // windows
    }
}

obj.b是一个箭头函数,它的this是包在它外层的词法作用域的this(离它最近的词法作用域),obj对象不是可执行代码,所以它不是离箭头函数最近的词法作用域,再往外就是全局作用域window了,所以obj.b的this指的是windows。

再来看一段代码:

var pageHandler = {

    id: "123456",

    init: function () {
        document.addEventListener("click", function (event) {
            this.doSomething(event.type);     // error
        }, false);
    },

    doSomething: function (type) {
        console.log("Handling " + type + " for " + this.id);
    }
};

在调用pageHandler.init方法的时候会报错,报错的函数是个回调函数,这个回调函数的this指的全局变量windows,在全局变量里没有doSomething这个方法,所以会报错。那么怎么才能让它不报错呢?

第一种方式是通过bind来指定this:

var pageHandler = {
    id: "123456",
    init: function () {
        document.addEventListener("click", (function (event) {
            this.doSomething(event.type)
        }).bind(this), false)

    },
    doSomething: function () {
        console.log("Handling" + type + " for " + this.id)
    }
}

.bind(this)中的this是指pageHandler这个对象,通过bind生成一个this指向pageHandler的新函数,这样执行init方法的时候不会报错,看起来怪怪的有没有。

第二种方式是通过箭头函数:

var pageHandler = {
    id: "12345",
    init: function () {
        document.addEventListener("click", () => {
            this.doSomething();
        }, false)
    },
    doSomething: function () {
        console.log("Handling" + type + " for " + this.id);
    }
}

把init中的回调函数改成了箭头函数,箭头函数的this是它最近的作用域链上的this,也就是init这个方法的this,也就是pageHandler这个对象,这样就可以达到目的不报错啦。

需要注意的是,箭头函数不能改变this的值,普通函数可以通过call、apply、bind来指定this,但是箭头函数的this是不能改的。

没有arguments

访问箭头函数的arguments,其实也是访问包在它外面的非箭头函数的arguments。

function foo(x, y) {
    return () => arguments[0];
}
console.log(foo(1,2)()); //1

不能通过new关键字调用。

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

没有原型

没有prototype, 但是有__proto__指向function。

没有super,也是通过包在它外面的非箭头函数来决定的。