【一個對象 A】的方法被【另外一個對象 B】【引用】的時候(請注意
引用 的意思,區分
調用 );【對象A】的方法內的this做用域就不指向【對象A】了,這個時候你再用this.XX項調用【對象A】的某個屬性就會發生錯誤。
舉個例子吧;
var aHello = {
name : "hello",
showName : function(){
console.log(this.name);
//console.log(this.tagName);
}
}
document.querySelector('a').onclick = aHello.showName;
這個時候由於【對象aHello】的方法showName被【對象document.querySelector('a')】
引用,因此showName內的this就不指向【aHello】了,指向【對象document.querySelector('a')】,能夠去掉註釋進行驗證。
可是咱們的需求是,點擊a的時候就顯示aHello的名稱。
這個時候該怎麼作呢?
方法一:在onclick的時候改用匿名函數,匿名函數內再
調用 【對象aHello】的方法;
如:
var aHello = {
name : "hello",
showName : function(){
console.log(this.name);
}
}
document.querySelector('a').onclick = function(){
aHello.showName();
}
ok!開心的解決了;
然而,是否是以爲太慫了。咱們來衍生一下第二種方法,而後再說bind和call和apply的區別;
方法二:由於
引用, onclick改變了【對象aHello】showName內this的指向。因此咱們必須在【
引用】的時候對showName方法進行從新綁定新的指向;
如:
var aHello = {
name : "hello",
showName : function(){
console.log(this.name);
}
}
document.querySelector('a').onclick = aHello.showName.bind(aHello);
恩!高大上,不用寫太多代碼。
接下來說一下bind和apply、call的區別;
首先這些方法多屬於【原型prototype】的方法。
題主的老師 可能沒聽過【引用】與【調用】因此用了一個臨時與永久的概念來說解,作技術,最好不要聽老師的......
還用前面例子來說(隨便舉的主要區分區別,你們別挑刺);
var aHello = {
name : "hello",
setYourAge : function(name,age){
console.log(name);
console.log(age);
}
}
document.querySelector('a').onclick = aHello.setYourAge.call(aHello,'王佳欣',25);
這個時候你能夠看到打開頁面,瀏覽器控制檯就會立刻輸出 「王佳欣」,「25」;
而後,你再點擊的時候,根本不會,再輸出的;ok,這就是 【調用】含義;
call和apply是調用對象方法的意思;也就是說下面的3句代碼其實實現是同樣的;
aHello.setYourAge.call(aHello,'王佳欣',25);
aHello.setYourAge.apply(aHello,['王佳欣',25]);
aHello.setYourAge('王佳欣',25);
既然能夠直接調用幹嗎還要call、apply方法呢,我先說一下
call、apply 和bind的區別吧;
var aHello = {
name : "hello",
setYourAge : function(name,age){
console.log(name);
console.log(age);
}
}
document.querySelector('a').onclick = aHello.setYourAge.bind(aHello,'王佳欣',25);
bind的做用是【引用】,這個時候你打開瀏覽器控制檯不會有輸出。你點擊a 標籤的後,纔會有輸出,點一次,輸出一次。
粗暴一點說,這就是區別立刻【調用】和【引用】的區別。
上面咱們說到,下面三局代碼實現是同樣的。那麼call、apply有什麼做用呢?
aHello.setYourAge.call(aHello,'王佳欣',25);
aHello.setYourAge.apply(aHello,['王佳欣',25]);
aHello.setYourAge('王佳欣',25);
call、apply有什麼做用
你們開發中是否是有這樣的需求(我老是喜歡用需求來做爲入口)
咱們常常會在咱們項目中作一些通用的對象,這些對象用來處理咱們的一些通用的過程。好比:通用驗證方法;(注:不少人喜歡用 繼承的基礎類 來做爲例子.....我一時想不到好的繼承例子,就用通用類的例子吧!)
/*通用驗證對象*/
var validator = {
validateName : function(){
console.log(this.name);
},
validateAge : function(){
console.log(this.age)
}
//.....
}
你們能夠看到咱們的 【通用對象validator】內,是沒有定義屬性(name、age)的。
這個時候好比咱們有兩個對象須要驗證;
/*對象kobe*/
var kobe = {
name : 'kobe bryant',
age : -1
}
/*對象 allen*/
var allen = {
name : 'allen iverson',
age : 10
}
那咱們調用驗證的時候就須要用到call或者apply了
如:
var isKobeAgeValid = validator.call(kobe);
var isAllenAgeValid = validator.call(allen);
額!差很少了了.....
轉載自 王佳欣 連接:http://www.zhihu.com/question/20289071/answer/93261557 來源:知乎 著做權歸做者全部,轉載請聯繫做者得到受權。