JavaScript之bind及bind的模擬實現
阿新 • • 發佈:2019-01-30
在JavaScript程式設計中有很多改變this的方法和方式,今天說的bind與眾不同,像call、apply改變this指向的時候會直接執行。而bind則不是,話不多說,直接進入正題。
bind
bind是函式原型上的一個方法,作用是改變this指向並且返回一個函式等待被執行。Function.prototype.bind()
bind()可以傳入多個引數,第一個引數作為改變this的一個物件,後面的引數作為返回函式的形參。然而傳入的第一個引數不同的話,指向也不同,看程式碼
由此我們可以看出,當第一個引數是物件的時候,改變this的指向指向物件,當第一個引數為null的時候,此時的this指向window,當我們用 new newShow() 產生一個物件例項的時候,無論第一個引數填的什麼,this都是指向物件例項。var value = 0; var obj = { value : 1, } function(name,age){ console.log(value); console.log(name + " " + age); } var newShow = show.bind(obj,abc,18); newShow(); //返回 1 abc 18 var newShow = show.bind(null,abc,18); newShow(); //返回 0 abc 18 new newShow(); // 返回 undefined abc 18
bind的運用環境
當我們在後面進行模組化開發的時候,程式碼量大的時候,最容易犯的錯誤就是變數汙染全域性了,我們可以選擇單變數程式設計來防止這件事情的發生。程式碼如下:這種方式就是模組化程式設計,當我們在物件函式中寫進東西的時候,我們想讓這三個函式建立起來聯絡,想讓他們每次的初始this指向這個物件。這是時候就用到bind了。var obj = { init : fucntion(){ }, bindEvent : function(){ }, show : function(){ } }
此時我們在這樣呼叫的時候不會因為this指向的問題而 弄不清作用域是什麼。 現在我們開始想著用原生的方法模擬一下這個bind。var obj = { init : function(){ var btn = document.getElementById('btn'); }, bindEvent : function(){ btn.onclick = this.show.bind(this); }, show : function(){ console.log(this); } } obj.init()
bind的模擬實現
我們現在想一下這個bind需要什麼。由上面可知,bind第一個引數不用,this所指向不同。而且返回的是一個新的函式。當函式有返回值的時候還需要返回值Function.prototype.newBind = function(target){ var target = target || window; return function(){ return this.apply(target); } }我們還知道,在newBind方法呼叫的時候是可以用多個形參的。作為返回函式的引數,而新返回的函式也是可以傳參的,由於引數個數的不同我們可以選擇用arguments來確定引數,這時我們可以用 [].slice.call(grguments);這種方式把類陣列切成陣列
Function.prototype.newBind = function(target){
var target = target || window;
var self = this;
var args = [],slice.call(arguments,1);
return function(){
var _args = [].slice.call(arguments,0);
return self.apply(target,args.concat(_args));
}
}
當我們在原型鏈上程式設計的時候,避免不了用原型上的東西,此時我們bind的方法也是可以繼承原型上的屬性和方法的,這裡是使用聖盃模式的一種思想實現Function.prototype.newBind = function(target){
var target = target || window;
var self = this;
var args = [].slice.call(arguments,1);
var temp = function(){};
var F = function(){
var _args = [].slice.call(arguments,0);
return self.apply(this instanceof temp ? this : target , args.concat(_args));
}
temp.prototype = this.prototype;
F.prototype = new temp;
return F;
}
這樣我們的bind方法就完全實現了。自己試著用原聲的方法模擬一下bind的實現,也會加深對bind 的理解。