標籤:eof rspec 運行 int 瀏覽器 firefox 代碼 function 上下文
函數綁定(Function binding)很有可能是你在開始使用JavaScript時最少關注的一點,但是當你意識到你需要一個解決方案來解決如何在另一個函數中保持this內容相關的時候,你真正需要的其實就是 Function.prototype.bind(),只是你有可能仍然沒有意識到這點。
第一次遇到這個問題的時候,你可能傾向於將this設定到一個變數上,這樣你可以在改變了上下文之後繼續引用到它。很多人選擇使用 self, _this 或者 context 作為變數名稱(也有人使用 that)。這些方式都是有用的,當然也沒有什麼問題。但是其實有更好、更專用的方式。
我們真正需要解決的問題是什嗎?
在下面的例子代碼中,我們可以名正言順地將上下文緩衝到一個變數中:
1 var myObj = { 2 3 specialFunction: function () { 4 5 }, 6 7 anotherSpecialFunction: function () { 8 9 },10 11 getAsyncData: function (cb) {12 cb();13 },14 15 render: function () {16 var that = this;17 this.getAsyncData(function () {18 that.specialFunction();19 that.anotherSpecialFunction();20 });21 }22 };23 24 myObj.render();
如果我們簡單地使用 this.specialFunction() 來調用方法的話,會發現程式有錯誤。
我們需要為回呼函數的執行保持對 myObj 物件內容的引用。 調用 that.specialFunction()讓我們能夠維持範圍上下文並且正確執行我們的函數。
然而使用 Function.prototype.bind() 可以有更加簡潔乾淨的方式:
1 render: function () { 2 3 this.getAsyncData(function () { 4 5 this.specialFunction(); 6 7 this.anotherSpecialFunction(); 8 9 }.bind(this));10 11 }我們剛才做了什嗎?
.bind()建立了一個函數,當這個函數在被調用的時候,它的 this 關鍵詞會被設定成被傳入的值(這裡指調用bind()時傳入的參數)。
因此,我們傳入想要的上下文,this(其實就是 myObj),到.bind()函數中。
然後,當回呼函數被執行的時候, this 便指向 myObj 對象。
瀏覽器支援
| Browser |
Version support |
| Chrome |
7 |
| Firefox (Gecko) |
4.0 (2) |
| Internet Explorer |
9 |
| Opera |
11.60 |
| Safari |
5.1.4 |
正如你看到的,很不幸,Function.prototype.bind 在IE8及以下的版本中不被支援,所以如果你沒有一個備用方案的話,可能在運行時會出現問題。
if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 internal IsCallable function throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; };}
理解 JavaScript 中的 Function.prototype.bind