標籤:
為什麼要使用call,apply,bind
先看一個普通的對象:
var obj = {};obj.name = "多啦A夢";obj.say = function(){ console.log("大雄你好我是"+this.name);}obj.say();//大雄你好我是多啦A夢
我們對上面的函數做一些調整:
var obj = {};obj.name = "多啦A夢";obj.say = function(){ console.log("大雄你好我是"+this.name);}var fn = obj.say;fn();//大雄你好我是
這個時候不會再輸出“大雄你好我是多啦A夢”因為在第二個例子中this已經不是obj而變成了window而window中並沒有name屬性。
為了能夠達到我們預期的效果我們,我們可以使用call,apply或者bind,來實現我們的目的:
var obj = {};obj.name = "多啦A夢";obj.say = function(){ console.log("大雄你好我是"+this.name);}var fn = obj.say;fn.call(obj);//大雄你好我是多啦A夢
在我們平時的開發中,可能我們會無意或者有意的改變函數運行時this的指向,為了能達到我們預期的效果我們可以使用call,apply,bind來改變函數運行時this的指向,讓函數運行是的this指向第一個參數,這三個函數都可以改變函數運行時this的指向,當時他們也有一些不同,call和apply會立即執行函數,bind則是建立一個新的函數,更改新函數的this的指向。
call,apply
首先call和apply在我們平時的開發中有兩個妙用
Array.prototype.slice.call(obj)//obj是一個類數組,通過他這個函數可以把參數的類數群組轉換成一個真正的數組
Object.prototype.toString.call(arg)//arg可以是任意一個類型的值,這個函數最精確的判斷出參數的類型
call,apply在使用時會修正函數運行時this的指向,並且會立即執行函數。在只接受一個參數時兩個函數的使用方式是一樣的,使用方式如下:
//call使用var obj = {};obj.name = "多啦A夢";obj.say = function(){ console.log("大雄你好我是"+this.name);}var fn = obj.say;fn.call(obj);//apply使用var obj = {};obj.name = "多啦A夢";obj.say = function(){ console.log("大雄你好我是"+this.name);}var fn = obj.say;fn.apply(obj);
call和apply這兩個函數在使用時也是有一些不同的,這個我們稍後再介紹。
bind
bind函數的作用是建立一個新的函數,修改新函數運行時this的指向。
var obj = {};obj.name = "多啦A夢";obj.say = function(){ console.log("大雄你好我是"+this.name);}var fn = obj.say.bind(obj);fn();
如果函數中需要參數則把參數放在bind的第二個參數或者後面
var skin= "藍皮膚";var eye = "大眼睛";var obj = {};obj.name = "多啦A夢";obj.say = function(skin,eye){ console.log("大雄你好我是"+skin+eye+"的"+this.name);}var fn = obj.say.bind(obj,skin,eye);fn();
call
call基本的使用方法我們已經知道,當call函數需要使用多個參數是和bind函數時一樣的,第一個參數必須是this的指向,需要原函數需要參數,則在使用call時把參數挨個放在第一個參數的後面
var skin= "藍皮膚";var eye = "大眼睛";var obj = {};obj.name = "多啦A夢";obj.say = function(skin,eye){ console.log("大雄你好我是"+skin+eye+"的"+this.name);}var fn = obj.say;fn.call(obj,skin,eye);
apply
apply函數最多可以接收兩個參數,第一個參數表示this的指向,第二個參數必須是一個數組或者類數組,數組的每一個元素表示原函數需要使用的參數
var skin= "藍皮膚";var eye = "大眼睛";var obj = {};obj.name = "多啦A夢";obj.say = function(skin,eye){ console.log("大雄你好我是"+skin+eye+"的"+this.name);}var fn = obj.say;fn.apply(obj,[skin,eye]);
apply在我們對一些函數做簡便封裝是會非常有用,比如我們簡化console.log函數的操作我們可以這樣:
function print(arg){ console.log(arg);}print("hello");//console.log是可以接收多個參數的所以為了更加符合console.log函數的特性我們可以稍加改造function print(){ console.log.apply(this,arguments);}print("hello",1,true);
call apply bind