1. 程式人生 > >深入理解JS:執行上下文中的this(二)

深入理解JS:執行上下文中的this(二)

**目錄** - 序言 - Function.prototype.bind() 方法 - 箭頭函式 - 參考
**1.序言** 在 [深入理解JS:執行上下文中的this(一)](https://www.cnblogs.com/forcheng/p/12960972.html) 中,我們主要深入分析全域性環境和函式環境中函式呼叫的 this,還留下 bind 方法以及箭頭函式的 this 尚未分析,因此我們將在這篇文章進行講解。
**2.Function.prototype.bind() 方法** bind() 方法將會建立返回一個新的函式。在 bind() 被呼叫時,這個新函式的 this 將被指定為 bind() 的第一個引數,而其餘引數將作為新函式的引數,供呼叫時使用。 > ES5 引入了 [bind](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) 方法來設定函式的 this 值,而不用考慮函式如何被呼叫的。 這裡給出一種 bind() 的實現演算法: ```js var slice = Array.prototype.slice; Function.prototype.bind = function() { var thatFunc = this, thatArg = arguments[0]; var args = slice.call(arguments, 1); if (typeof thatFunc !== 'function') { throw new TypeError('Function.prototype.bind called on incompatible ' + thatFunc); } return function(){ var funcArgs = args.concat(slice.call(arguments)) return thatFunc.apply(thatArg, funcArgs); }; }; ``` *注:上述程式碼並沒有完全按照ES5規範實現,只是作為一種實現參考,更加完善的解決方案可以參考 [function-bind](https://github.com/Raynos/function-bind)* 但不論哪種實現,其實質上都是通過類似 `Function.prototype.apply(thisArg, argArray)` 來是實現指定呼叫函式 this 的。
**3.箭頭函式** 箭頭函式表示式的語法比[函式表示式](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/function)更簡潔,並且沒有自己的 this,arguments,super 或 new.target。它很適合用作匿名函式,並且不能用作建構函式(為什麼呢?[詳情點選檢視](https://www.cnblogs.com/forcheng/p/12883983.html))。 > ES6 引入了支援 this 詞法解析的[箭頭函式](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions)(它在閉合的執行環境內設定 this 的值)。 如何理解箭頭函式在閉合的執行環境內設定 this 的值? 簡單理解,箭頭函式不會建立自己的 this,它的 this 與封閉詞法環境的 this 保持一致,即如果箭頭函式在全域性環境中,那麼它的 this 就指向全域性物件,如果箭頭函式在某一個函式中,那麼它的 this 就指向所在函式的 this。
我們來看幾個示例: (1)全域性環境 ```js var global = this var foo = () => { return this } var value = 1 var bar = { value: 2, getValueByArrowFunc: () => { return this.value }, getValue: function (){ return this.value }, } console.log(foo() === global) // true // 箭頭函式 this => global console.log(bar.getValueByArrowFunc()) // 1 // 普通函式 this => bar console.log(bar.getValue()) // 2 ```
(2)函式環境 ES6的語法: ```js function foo() { this.value = 1 // 箭頭函式表示式 var arr = () => { console.log(this.value) } arr() } ``` 轉化為ES5: ```js function foo() { var _this = this; this.value = 1; // 轉化為普通函式表示式 var arr = function arr() { console.log(_this.value); }; arr(); } ``` 對比轉化前後的程式碼可以看出:箭頭函式會轉化為一個普通函式,通過一個臨時變數 _this 來傳遞,它之前的 this 就是所在函式的 this
(3)call() 、 apply() 或 bind() 方法 ```js var global = this var foo = { bar: () => { return this } } var obj = { value : 1 } console.log(foo.bar() === global) // true console.log(foo.bar.call(obj) === global) // true console.log(foo.bar.apply(obj) === global) // true var bind = foo.bar.bind(obj) console.log(bind() === global) // true ``` 由於箭頭函式不會建立自己的 this,那麼通過 call() 、 apply() 或 bind() 方法呼叫一個箭頭函式時,只能傳遞引數,第一個引數會被忽略。
**4.參考** [this 關鍵字 - JavaScript | MDN - Mozilla](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this) [Function.prototype.bind() - JavaScript - MDN - Mozilla](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind) [箭頭函式- JavaScript | MDN](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions) [ECMAScript5.1中文版](https://yanhaijing.com/es5) [ES6 - Arrow functions](https://exploringjs.com/es6/ch_arrow-function