轉自--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()
最簡單的用法是建立一個函數,使這個函數不論怎麼調用都有一樣的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>
這是一個很好的特性,使用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()
的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