01-箭头函数

232 阅读3分钟

前言

箭头函数是 ES6 的新特性,箭头函数本质上也是一个匿名函数。箭头函数表达式的语法比函数表达式更简洁。它有以下特性:

  • 没有自己的 this
  • 没有自己的 arguments
  • 没有自己的 super 或 new.target ,所以它不能用作构造函数。

创造箭头函数的初衷就是为了简化函数的定义,以及规避 this 指向带来的问题

1. 没有自己的 this

普通函数 vs 箭头函数:

  • 普通函数 this :
    • 指向它的调用者,如果没有调用者则默认指向 window (严格模式指向 undefined)
    • 可以理解为普通函数的 this 只有在被调用的时候才能确定,它是动态的
  • 箭头函数:
    • 箭头函数本身并无this,箭头函数的this由定义箭头函数时所处的作用域决定,即箭头函数的this永远指向定义箭头函数时所在的作用域的this(也可以说是上层作用域,强调的是作用域!)。
    • 因为没有 this 所以不能作为构造函数
    • 可以理解为箭头函数的 this 只和定义时的作用域 this 有关,和调用者无关,和调用环境无关,也永远不会改变(因此不能使用call\apply\bind改变箭头函数的this指向,这里说的不会改变是指它查找 this 的规则,而非最终查找到的 this 值不会改变)。

1.1 箭头函数 this 继承声明时父级作用域的 this

const obj = {
    age: 1,
    say: function() {
        setTimeout(function() {
            console.log(this, this.age); // window undefined
        }, 0);
    },
}

const obj1 = {
    age: 1,
    say: function() {
        setTimeout(() => {
            console.log(this, this.age); // obj1 1
        }, 0);
    }
};

1.2 箭头函数不可以用作构造函数

const test = () => {
    // Uncaught SyntaxError: new.target expression is not allowed here
    console.log(new.target)
}

const Person = (name) => {
    this.name = name;
}

// Uncaught TypeError: Person is not a constructor
new Person('Jack');

便于理解,顺便复习一下构造函数创建对象的过程:

  • 函数内部首先会生成一个对象;
  • 再把函数中的this指向该对象;
  • 然后执行构造函数中的语句;
  • 如果函数中的语句最终没有返回一个对象,则返回预先生成的对象;否则返回函数语句返回的对象。

1.3 箭头函数不能通过 call/apply/bind 改变 this

箭头函数 this 查找规则类似作用域查找,规则是固定的,故无法被改变

1.4 箭头函数没有 prototype 属性

走到这里应该很好理解了:箭头函数没有自己的 this --> 箭头函数不能用作构造函数 --> 箭头函数没有 prototype 属性

2. 不绑定arguments

箭头函数如果要访问参数可以使用 es6 新增的 rest参数

var foo = (val) => {
    // Uncaught ReferenceError: arguments is not defined
    console.log(arguments);
};

// 在箭头函数中访问 arguments 对象,实际上访问的是外部作用域的 arguments 对象
function bar() {
    const args = arguments
    const foo = () => {
        // 返回 true
        console.log(arguments === args)
    }
    return foo
}
bar(1, 2, 3)(4, 5, 6)

// 使用 rest 参数可以代替 arguments
var foo = (...args) => {
    console.log(args); // [1, 2, 3]
};
foo(1, 2, 3);

3. 不可以用作 generator

这个应该是语法层面的限制