Javascript中bind()方法的使用與實現

轉自--https://www.cnblogs.com/chenpingzhao/p/4883995.htmljavascript

咱們先來看一道題目html

var write = document.write; 
write("hello"); 
//1.以上代碼有什麼問題
//2.正確操做是怎樣的

不能正確執行,由於write函數丟掉了上下文,此時this的指向global或window對象,致使執行時提示非法調用異常,因此咱們須要改變this的指向java

正確的方案就是使用 bind/call/apply來改變this指向web

bind方法app

var write = document.write;
write.bind(document)('hello');

call方法dom

var write = document.write;
write.call(document,'hello');

apply方法函數

var write = document.write;
write.apply(document,['hello']);

bind函數

bind()最簡單的用法是建立一個函數,使這個函數不論怎麼調用都有一樣的this值。常見的錯誤就像上面的例子同樣,將方法從對象中拿出來,而後調用,而且但願this指向原來的對象。若是不作特殊處理,通常會丟失原來的對象。使用bind()方法可以很漂亮的解決這個問題:this

<script type="text/javascript">
 
this.num = 9; 
var module = { 
    num: 81,
    getNum: function(){
        console.log(this.num);
    }
};
 
module.getNum(); // 81 ,this->module
 
var getNum = module.getNum;
getNum(); // 9, this->window or global
 
var boundGetNum = getNum.bind(module); 
boundGetNum(); // 81,this->module
 
</script>

偏函數(Partial Functions)

這是一個很好的特性,使用bind()咱們設定函數的預約義參數,而後調用的時候傳入其餘參數便可:spa

<script type="text/javascript">
 
function list() { 
  return Array.prototype.slice.call(arguments);
}
 
var list1 = list(1, 2, 3);
console.log(list1);// [1, 2, 3]
 
// 預約義參數37
var leadingThirtysevenList = list.bind(undefined, 37);
 
var list2 = leadingThirtysevenList();
console.log(list2);// [37] 
 
var list3 = leadingThirtysevenList(1, 2, 3);
console.log(list3);// [37, 1, 2, 3] 
</script>

和setTimeout or setInterval一塊兒使用

通常狀況下setTimeout()的this指向window或global對象。當使用類的方法時須要this指向類實例,就可使用bind()將this綁定到回調函數來管理實例。prototype

<script type="text/javascript">
 
function Bloomer() { 
  this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
 
// 1秒後調用declare函數
Bloomer.prototype.bloom = function() { 
  window.setTimeout(this.declare.bind(this), 1000);
};
 
Bloomer.prototype.declare = function() { 
  console.log('我有 ' + this.petalCount + ' 朵花瓣!');
};
 
var test = new Bloomer();
 
test.bloom();
 
</script>

綁定函數做爲構造函數

綁定函數也適用於使用new操做符來構造目標函數的實例。當使用綁定函數來構造實例,注意:this會被忽略,可是傳入的參數仍然可用。

<script type="text/javascript">
 
function Point(x, y) { 
 
  this.x = x;
  this.y = y;
}
 
Point.prototype.toString = function() { 
  console.log(this.x + ',' + this.y);
};
 
var p = new Point(1, 2); 
p.toString(); // 1,2
 
var YAxisPoint = Point.bind(null,10);
var axisPoint = new YAxisPoint(5); 
axisPoint.toString(); // 10,5
 
console.log(axisPoint instanceof Point); // true 
console.log(axisPoint instanceof YAxisPoint); // true 
console.log(new Point(17, 42) instanceof YAxisPoint); // true  
</script>

上面例子中Point和YAxisPoint共享原型,所以使用instanceof運算符判斷時爲true

相關文章
相關標籤/搜索