【JS】「每日一问」箭头函数与普通函数有啥区别?

「每日一问」箭头函数与普通函数有啥区别?

修仙大橙子发布于 21 分钟前

箭头函数与普通函数有啥区别?

ES6普及后,箭头函数越来越多的出现在我们的日常开发中,那么箭头函数与普通函数究竟由什么区别呢?

涉及相关知识点

  • new操作符
  • new.target
  • prototype
  • 浏览器事件
  • Object.prototype.defineProperty
  • call、bind、apply
  • prototype
  • arguments对象

this绑定

箭头函数没有自己的this,它会从自己的作用域链的父级继承this

为了更好的理解上面的这段话,我们来举几个例子

如何理解无this绑定?

例子1:页面的事件回调函数

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<title>事件回调中函数的this</title>

</head>

<body>

<button id="arrow-function">箭头函数</button>

<button id="regular-function">普通函数</button>

</body>

<script>

const arrowFunctionButton = document.querySelector("#arrow-function");

const regularFunctionButton = document.querySelector("#regular-function");

arrowFunctionButton.addEventListener("click", () => {

console.log(this); // this指向window ①

});

regularFunctionButton.addEventListener("click", function () {

console.log(this); // this指向当前的点击元素 ②

});

function Wrapper() {

let arrowFunction = () => {

console.log('我是被包裹箭头函数的this >>>', this);

}

document.addEventListener('click', arrowFunction);

}

let object = new Wrapper(); // ③

</script>

</html>

让我们再来回顾一遍箭头函数中this的特性

因此在①中,这个回调函数作用域链的父级是window,因此打印出来的结果是window

事件回调的函数如果是普通函数,此时this将会指向当前被点击的元素,因此②中打印出的结果是<button id="regular-function">普通函数</button>

执行结果如下:
【JS】「每日一问」箭头函数与普通函数有啥区别?

请注意,箭头函数会根据使用位置而不是定义位置继承词法作用域。当使用new运算符时,像执行对象的构造函数那样来执行函数。因此函数内部的每条语句都将在实例化对象object的语境中执行,而不是在window的语境中执行。因此在③中,我们可以知道,this指向实例化的object

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

例子2:Object.prototype.defineProperty方法

下面是一个来自MDN的例子,解释了为何我们很少看见在definePrototype中使用箭头函数

var obj = {

a: 10

};

Object.defineProperty(obj, "b", {

get: () => {

console.log(this.a, typeof this.a, this); // this指向window

return this.a+10;

}

});

obj.b; // NaN

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

由于箭头函数的this指向window,而window内并未定义a属性,因此:
this等价于windowthis.a等价于undefined,而this.a + 10实际上等价于undefined + 10结果为NaN

callapplybind调用将会忽略第一个参数

window.a = 1;

const obj = {

a: 2

};

const uselessCall = (arg) => {

console.log('我是this >>>', this, '我是this.a >>>', this.a, '我是传入值 >>>', arg);

}

function usefulCall (arg) {

console.log('我是this >>>', this, '我是this.a >>>', this.a, '我是传入值 >>>', arg);

}

uselessCall.call(obj, 10);

usefulCall.call(obj, 10);

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

由于箭头函数没有自己的this,将会导致通过callapplybind调用一个箭头函数时,忽略第一个参数。当没有指定第一个参数时,将会默认绑定window。后面传入的参数依旧有效。

arguments对象

箭头不绑定arguments对象,普通函数绑定arguments对象。

如果你在箭头函数中想要访问arguments对象,将会发生引用错误:

const noArguments = () => console.log(arguments);

noArguments();

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

在普通函数中,我们可以使用arguments对象

function hasArguments() {

console.log(arguments);

}

hasArguments();

执行结果如下:
【JS】「每日一问」箭头函数与普通函数有啥区别?

无构造函数

使用new操作符报错

箭头函数不能用于构造,因此使用new将会报错

const ErrorNew = () => {};

new ErrorNew;

执行结果如下:
【JS】「每日一问」箭头函数与普通函数有啥区别?

new.target

由于无法被new运算符调用,因此箭头函数同样不拥有new.target

const noNewTarget = () => console.log(new.target);

执行结果如下:
【JS】「每日一问」箭头函数与普通函数有啥区别?

prototype属性

箭头函数没有prototype属性,如果试图设置prototype属性,将会报错!

const NoPrototype = () => {};

console.log(NoPrototype.prototype); // undefined

NoPrototype.prototype.age = 11; // 抛出错误

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

javascript箭头函数每日一问

阅读 18更新于 8 分钟前

本作品系原创,采用《署名-非商业性使用-禁止演绎 4.0 国际》许可协议


前端小站

前端的内容小记

avatar

修仙大橙子

前端工程师

86 声望

3 粉丝

0 条评论

得票时间

avatar

修仙大橙子

前端工程师

86 声望

3 粉丝

宣传栏

箭头函数与普通函数有啥区别?

ES6普及后,箭头函数越来越多的出现在我们的日常开发中,那么箭头函数与普通函数究竟由什么区别呢?

涉及相关知识点

  • new操作符
  • new.target
  • prototype
  • 浏览器事件
  • Object.prototype.defineProperty
  • call、bind、apply
  • prototype
  • arguments对象

this绑定

箭头函数没有自己的this,它会从自己的作用域链的父级继承this

为了更好的理解上面的这段话,我们来举几个例子

如何理解无this绑定?

例子1:页面的事件回调函数

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8" />

<title>事件回调中函数的this</title>

</head>

<body>

<button id="arrow-function">箭头函数</button>

<button id="regular-function">普通函数</button>

</body>

<script>

const arrowFunctionButton = document.querySelector("#arrow-function");

const regularFunctionButton = document.querySelector("#regular-function");

arrowFunctionButton.addEventListener("click", () => {

console.log(this); // this指向window ①

});

regularFunctionButton.addEventListener("click", function () {

console.log(this); // this指向当前的点击元素 ②

});

function Wrapper() {

let arrowFunction = () => {

console.log('我是被包裹箭头函数的this >>>', this);

}

document.addEventListener('click', arrowFunction);

}

let object = new Wrapper(); // ③

</script>

</html>

让我们再来回顾一遍箭头函数中this的特性

因此在①中,这个回调函数作用域链的父级是window,因此打印出来的结果是window

事件回调的函数如果是普通函数,此时this将会指向当前被点击的元素,因此②中打印出的结果是<button id="regular-function">普通函数</button>

执行结果如下:
【JS】「每日一问」箭头函数与普通函数有啥区别?

请注意,箭头函数会根据使用位置而不是定义位置继承词法作用域。当使用new运算符时,像执行对象的构造函数那样来执行函数。因此函数内部的每条语句都将在实例化对象object的语境中执行,而不是在window的语境中执行。因此在③中,我们可以知道,this指向实例化的object

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

例子2:Object.prototype.defineProperty方法

下面是一个来自MDN的例子,解释了为何我们很少看见在definePrototype中使用箭头函数

var obj = {

a: 10

};

Object.defineProperty(obj, "b", {

get: () => {

console.log(this.a, typeof this.a, this); // this指向window

return this.a+10;

}

});

obj.b; // NaN

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

由于箭头函数的this指向window,而window内并未定义a属性,因此:
this等价于windowthis.a等价于undefined,而this.a + 10实际上等价于undefined + 10结果为NaN

callapplybind调用将会忽略第一个参数

window.a = 1;

const obj = {

a: 2

};

const uselessCall = (arg) => {

console.log('我是this >>>', this, '我是this.a >>>', this.a, '我是传入值 >>>', arg);

}

function usefulCall (arg) {

console.log('我是this >>>', this, '我是this.a >>>', this.a, '我是传入值 >>>', arg);

}

uselessCall.call(obj, 10);

usefulCall.call(obj, 10);

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

由于箭头函数没有自己的this,将会导致通过callapplybind调用一个箭头函数时,忽略第一个参数。当没有指定第一个参数时,将会默认绑定window。后面传入的参数依旧有效。

arguments对象

箭头不绑定arguments对象,普通函数绑定arguments对象。

如果你在箭头函数中想要访问arguments对象,将会发生引用错误:

const noArguments = () => console.log(arguments);

noArguments();

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

在普通函数中,我们可以使用arguments对象

function hasArguments() {

console.log(arguments);

}

hasArguments();

执行结果如下:
【JS】「每日一问」箭头函数与普通函数有啥区别?

无构造函数

使用new操作符报错

箭头函数不能用于构造,因此使用new将会报错

const ErrorNew = () => {};

new ErrorNew;

执行结果如下:
【JS】「每日一问」箭头函数与普通函数有啥区别?

new.target

由于无法被new运算符调用,因此箭头函数同样不拥有new.target

const noNewTarget = () => console.log(new.target);

执行结果如下:
【JS】「每日一问」箭头函数与普通函数有啥区别?

prototype属性

箭头函数没有prototype属性,如果试图设置prototype属性,将会报错!

const NoPrototype = () => {};

console.log(NoPrototype.prototype); // undefined

NoPrototype.prototype.age = 11; // 抛出错误

执行结果如下:

【JS】「每日一问」箭头函数与普通函数有啥区别?

以上是 【JS】「每日一问」箭头函数与普通函数有啥区别? 的全部内容, 来源链接: utcz.com/a/114631.html

回到顶部