箭头函数是 ES6 引入的一种新的函数声明方式。它的语法更简洁,但是有一些特性与普通的 function 声明的函数是不同的。
- 更简洁的语法:箭头函数的语法更为简洁。例如,一个普通的函数可以写成
function (x) { return x * x },而使用箭头函数,可以简写成x => x * x。 - 没有自己的
this值:箭头函数不会创建自己的this值。在箭头函数内部,this是词法层面上的;也就是说,它是由上下文决定的,而不是由函数调用方式决定的。这与普通函数不同,普通函数的this值是由它的调用方式决定的。 - 不能作为构造函数:你不能使用
new关键字来调用箭头函数。如果你尝试这样做,JavaScript 引擎会抛出错误。 - 没有
arguments对象:在普通函数中,arguments是一个类数组对象,包含了函数被调用时的参数列表。但在箭头函数中,arguments对象并不存在。如果你需要使用所有参数,可以使用剩余参数(...args)的方式。 - 没有
prototype属性:由于箭头函数不能作为构造函数,所以它也没有prototype属性。 - 隐式返回:如果箭头函数的函数体只有一行并且没有大括号,那么这一行的结果会被隐式返回。也就是说,你不需要(也不能)在这种箭头函数中使用
return关键字。
没有自己的 this 值
在 JavaScript 中,函数有它们自己的上下文,也就是它们的 "this"。这个 "this" 指向的是调用这个函数的对象。让我们来看一个例子:
let myObject = {
value: "Hello",
sayHello: function() {
console.log(this.value);
}
};
myObject.sayHello(); // 输出 "Hello"
在这个例子中,sayHello 函数的 "this" 就是 myObject,因为是 myObject 调用了这个函数。
所以,当我们在函数内部打印 this.value 时,它打印的是 myObject 的 value 属性。
然而,当我们在函数中创建一个新的函数时,新的函数会有它自己的 "this":
let myObject = {
value: "Hello",
sayHello: function() {
console.log(this.value); // 输出 "Hello"
function innerFunction() {
console.log(this.value);
}
innerFunction(); // 输出 "undefined"
}
};
myObject.sayHello();
在这个例子中,innerFunction 的 "this" 不是 myObject,而是全局对象(在浏览器中就是 window)。因为 window 上没有 value 属性,所以 this.value 是 undefined。
然而,箭头函数不会创建它自己的 "this",它会从外部函数(或者全局作用域)继承 "this":
let myObject = {
value: "Hello",
sayHello: function() {
console.log(this.value); // 输出 "Hello"
let innerFunction = () => {
console.log(this.value); // 输出 "Hello"
}
innerFunction();
}
};
myObject.sayHello();
在这个例子中,innerFunction 是一个箭头函数,所以它没有自己的 "this",而是从 sayHello 函数中继承了 "this"。因此,当我们在箭头函数内部打印 this.value 时,它打印的是 myObject 的 value 属性。
没有 arguments 对象
首先,我们需要先搞懂,什么是类数组对象?
类数组对象,就是其结构和数组类似,即具有一个索引(例如,0, 1, 2, 3等)和长度(length)属性,但并不具备数组的内置方法(如 push, pop, forEach等)。JavaScript 中的一些内置对象,例如 arguments 和 NodeList,就是类数组对象。
比如说,我们创建一个对象,赋予它索引和长度属性:
javascriptCopy code
let arrayLike = {
0: 'Hello',
1: 'World',
length: 2
};
这个 arrayLike 就是一个类数组对象,它有索引和长度,但它并不是一个真正的数组,因为它没有数组的方法,例如 push 或 pop。
关于 arguments 对象和箭头函数,让我再详细解释一下。arguments 对象是一个特殊的对象,它在函数内部可用,包含了传递给函数的所有参数。然而,箭头函数并不创建自己的 arguments 对象。如果在箭头函数中访问 arguments,会引用其外部的(箭头函数外层的最近的非箭头函数)arguments 对象。
让我们来看这个例子:
function outerFunction(arg1, arg2) {
const innerFunction = () => {
console.log(arguments[0]); // 这里的 arguments 是 outerFunction 的 arguments
console.log(arguments[1]); // 这里的 arguments 是 outerFunction 的 arguments
};
innerFunction('innerArg1', 'innerArg2');
}
outerFunction('outerArg1', 'outerArg2');
// 输出 "outerArg1",然后输出 "outerArg2"
在这个例子中,innerFunction 是一个箭头函数,它没有自己的 arguments 对象。所以,当我们在 innerFunction 中访问 arguments,我们实际上访问的是 outerFunction 的 arguments 对象。
在JavaScript中,arguments对象是一个类数组对象,它包含了函数被调用时的参数列表。在普通函数中,你可以通过arguments对象来访问函数的参数,即使你在函数定义的时候没有明确地声明这些参数。例如:
function myFunction() {
console.log(arguments[0]);
console.log(arguments[1]);
}
myFunction('Hello', 'World'); // 输出 "Hello",然后输出 "World"
在上述例子中,尽管myFunction没有定义任何参数,但我们仍然可以通过arguments对象来访问传给函数的参数。
然而,箭头函数并不绑定自己的arguments对象。如果你在箭头函数内部尝试访问arguments,你实际上会得到箭头函数外部(即包裹箭头函数的最近的非箭头函数)的arguments对象。例如:
function myFunction() {
let arrowFunction = () => {
console.log(arguments[0]);
console.log(arguments[1]);
}
arrowFunction('Goodbye', 'World');
}
myFunction('Hello', 'World'); // 输出 "Hello",然后输出 "World"
在上述例子中,我们在箭头函数内部尝试访问arguments,但我们得到的是myFunction的arguments对象,而不是arrowFunction的参数。
如果你需要在箭头函数内部访问函数的参数,你需要在箭头函数定义的时候显式地声明这些参数:
let arrowFunction = (arg1, arg2) => {
console.log(arg1);
console.log(arg2);
}
arrowFunction('Hello', 'World'); // 输出 "Hello",然后输出 "World"
这就是箭头函数没有自己的arguments对象的含义。
没有 prototype 属性
在 JavaScript 中,每个函数都有一个 prototype 属性,这个 prototype 属性是一个对象,它包含一个 constructor 属性,该属性指向函数自身。这个 prototype 对象主要用于实现继承和共享属性。
当我们使用 new 关键字创建一个新的对象实例时,这个新对象会从它的构造函数(也就是我们调用 new 的那个函数)的 prototype 对象中继承属性和方法。
然而,箭头函数是一个例外。箭头函数并没有 prototype 属性,也就是说,你不能使用箭头函数作为构造函数来通过 new 关键字创建新的对象实例。这是因为箭头函数主要被设计为匿名函数,用于执行简单的操作,而不是定义新的类型。
下面是一个示例,展示了普通函数和箭头函数在这方面的区别:
function regularFunction() {}
const arrowFunction = () => {};
console.log(regularFunction.prototype); // 输出 { constructor: f }
console.log(arrowFunction.prototype); // 输出 undefined
在这个例子中,你可以看到,对于普通函数 regularFunction,它的 prototype 属性是一个对象,
而对于箭头函数 arrowFunction,它的 prototype 属性是 undefined。这说明了箭头函数没有 prototype 属性,也就不能作为构造函数使用。