1. 程式人生 > >修改this指向(bind、call 和 apply)

修改this指向(bind、call 和 apply)

self 全局 () 用法 兼容 {} ins his post

一、bind

首先:

var alertWrite = document.write;
alertWrite(‘who am I?‘);

這兩行代碼的運行結果是什麽呢?不要急著回答,看完下面的內容再回答。

bind 的其中一個用法就是:綁定函數,使其無論怎麽樣調用都用相同的 this

看下面的例子:

var obj = {
    getThis: function() {
        console.log(this);
    }
};
obj.getThis();
var getThisCopy = obj.getThis; getThisCopy();

運行結果如下:

技術分享圖片

技術分享圖片

通過上述例子我們會發現,雖然是 getThisCopy 是復制了 obj 的 getThis 方法,但是他們所屬的對象卻不一樣。在對象裏面,所有的 this 都指向對象本身,而在全局作用域定義的變量的 this 指向 Window。

所以,下面這段代碼的運行結果,能猜的出來結果嗎?

1 var obj = {
2     num: 100,
3     numFun: function() {
4         console.log(this.num);
5     }
6 };
7 var numFunCopy = obj.numFun;
8 numFunCopy();

bind 的存在就是 為了解決 this 不能夠指向原來的問題。

所以,試試這段代碼:

 1 var alertWrite = document.write;
 2 alertWrite.bind(document)(‘hello‘);
 

4
var obj = { 5 getThis: function(){ 6 console.log(this); 7 } 8 } 9 var getThisCopy = obj.getThis; 10 getThisCopy.bind(obj)(); 11 12

13 var obj = {
14     num: 100,
15     numFun: function(){
16         console.log(this.num);
17     }
18 }
19 var numFunCopy = obj.numFun;
20 numFunCopy.bind(obj)();

總結bind使用方法:

fun.bind(thisObj, 參數1, 參數2...)()

thisObj:this調用綁定函數時作為參數傳給目標函數值,如果綁定函數時使用 new 運算符構造的,則該值將被忽略。

參數1,參數2...:在調用目標函數時加入提供給綁定函數的參數的參數

返回值:具有指定 this 值和初始參數的給定函數的副本

技術分享圖片

技術分享圖片

但是 bind 是 ES5 的內容,有一定的兼容性問題。

解決bind兼容性方案(1)

 1 //解決IE10以下不支持Function.bind
 2 if (!Function.prototype.bind) {
 3     Function.prototype.bind = function(oThis) {
 4         if (typeof this !== "function") {
 5             throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
 6         }
 7         var aArgs = Array.prototype.slice.call(arguments, 1),
 8             fToBind = this,
 9             fNOP = function() {},
10             fBound = function() {
11                 return fToBind.apply(this instanceof fNOP && oThis ? this : oThis,
12                     aArgs.concat(Array.prototype.slice.call(arguments)));
13             };
14         fNOP.prototype = this.prototype;
15         fBound.prototype = new fNOP();
16         return fBound;
17     };
18 }

解決bind兼容性方案(2)

1 if (!function() {}.bind) {
2     Function.prototype.bind = function(context) {
3         var self = this
4             , args = Array.prototype.slice.call(arguments);     
5         return function() {
6             return self.apply(context, args.slice(1));    
7         }
8     };
9 }

二、call

修改this指向(bind、call 和 apply)