目錄html
1.序言git
在 深刻理解JS:執行上下文中的this(一) 中,咱們主要深刻分析全局環境和函數環境中函數調用的 this,還留下 bind 方法以及箭頭函數的 this 還沒有分析,所以咱們將在這篇文章進行講解。es6
2.Function.prototype.bind() 方法github
bind() 方法將會建立返回一個新的函數。在 bind() 被調用時,這個新函數的 this 將被指定爲 bind() 的第一個參數,而其他參數將做爲新函數的參數,供調用時使用。算法
ES5 引入了 bind 方法來設置函數的 this 值,而不用考慮函數如何被調用的。app
這裏給出一種 bind() 的實現算法:函數
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-bindthis
但不論哪一種實現,其實質上都是經過相似 Function.prototype.apply(thisArg, argArray)
來是實現指定調用函數 this 的。es5
3.箭頭函數prototype
箭頭函數表達式的語法比函數表達式更簡潔,而且沒有本身的 this,arguments,super 或 new.target。它很適合用做匿名函數,而且不能用做構造函數(爲何呢?詳情點擊查看)。
ES6 引入了支持 this 詞法解析的箭頭函數(它在閉合的執行環境內設置 this 的值)。
如何理解箭頭函數在閉合的執行環境內設置 this 的值?
簡單理解,箭頭函數不會建立本身的 this,它的 this 與封閉詞法環境的 this 保持一致,即若是箭頭函數在全局環境中,那麼它的 this 就指向全局對象,若是箭頭函數在某一個函數中,那麼它的 this 就指向所在函數的 this。
咱們來看幾個示例:
(1)全局環境
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的語法:
function foo() { this.value = 1 // 箭頭函數表達式 var arr = () => { console.log(this.value) } arr() }
轉化爲ES5:
function foo() { var _this = this; this.value = 1; // 轉化爲普通函數表達式 var arr = function arr() { console.log(_this.value); }; arr(); }
對比轉化先後的代碼能夠看出:箭頭函數會轉化爲一個普通函數,經過一個臨時變量 _this 來傳遞,它以前的 this 就是所在函數的 this
(3)call() 、 apply() 或 bind() 方法
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