乐趣区

关于javascript:每日一问箭头函数与普通函数有啥区别

箭头函数与一般函数有啥区别?

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 的个性

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

因而在①中,这个回调函数作用域链的父级是window,因而打印进去的后果是window

事件回调的函数如果是一般函数,此时 this 将会指向以后被点击的元素,因而②中打印出的后果是<button id="regular-function"> 一般函数 </button>

执行后果如下:

请留神,箭头函数会依据应用地位而不是定义地位继承词法作用域。当应用 new 运算符时,像执行对象的构造函数那样来执行函数。因而函数外部的每条语句都将在实例化对象 object 的语境中执行,而不是在 window 的语境中执行。因而在③中,咱们能够晓得,this指向实例化的object

执行后果如下:

例子 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

执行后果如下:

因为箭头函数的 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);

执行后果如下:

因为箭头函数没有本人的 this,将会导致通过callapplybind 调用一个箭头函数时,疏忽第一个参数。当没有指定第一个参数时,将会默认绑定window。前面传入的参数仍旧无效。

arguments 对象

箭头不绑定 arguments 对象,一般函数绑定 arguments 对象。

如果你在箭头函数中想要拜访 arguments 对象,将会产生援用谬误:

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

执行后果如下:

在一般函数中,咱们能够应用 arguments 对象

function hasArguments() {console.log(arguments);
}

hasArguments();

执行后果如下:

小提示
如果你心愿在箭头函数中获取函数传入参数,请间接应用 残余参数 来获取

const restParameters = (...args) => console.log(args);

无构造函数

应用 new 操作符报错

箭头函数不能用于结构,因而应用 new 将会报错

const ErrorNew = () => {};
new ErrorNew;

执行后果如下:

new.target

因为无奈被 new 运算符调用,因而箭头函数同样不领有new.target

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

执行后果如下:

prototype 属性

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

const NoPrototype = () => {};
console.log(NoPrototype.prototype); // undefined

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

执行后果如下:

退出移动版