本文討論如何“修改”function中的this
有兩個(gè)要點(diǎn):
(1)為什么要修改怀酷?
關(guān)鍵字:共享
(2)如何修改次泽?
關(guān)鍵字:call,apply,bind
如何修改
前面提到 this是一個(gè)對象烟勋,并且 是只讀的:你不能手動(dòng)修改this的值蚌卤。
<script>
this = {};//這是錯(cuò)誤的
</script>
那為什么我們要如何去修改this的值呢?
使用call幽钢。
call是什么歉备?
call是Function.prototype的一個(gè)屬性。在chrome瀏覽器的控制臺(tái)中輸入如下:
console.dir(Function.prototype)
你就可以看到:
上圖中還有apply,后面我們會(huì)說到匪燕。
解釋一下上面的那一句代碼蕾羊。
Function是js的內(nèi)置對象,是一個(gè)構(gòu)造器帽驯,js中所有的function都是由它創(chuàng)造出來的龟再。prototype是Function的原型對象,call是 prototype的一個(gè)屬性尼变。因?yàn)樗膶傩灾凳呛瘮?shù)利凑,更準(zhǔn)確地來說,它是一個(gè)方法享甸。
按原型鏈的規(guī)則:定義在Function.prototype對象中的屬性 可以被任意的function使用截碴。
call的作用和格式
作用
修改函數(shù)內(nèi)部的this。
格式
函數(shù)f.call(newObj蛉威,參數(shù)1,參數(shù)2.....)
形參:
newObj :用newObj替換函數(shù)f中的this
參數(shù)1...參數(shù)n : 函數(shù)f 的參數(shù)走哺。
示例
function f(){ console.info( this.p);}
var obj1 = {"p":"obj1"}
var obj2 = {"p":"obj2"}
f.call(obj1 ); //輸出obj1
f.call(obj2 ); //輸出obj2
對f.call(obj1) 解釋如下:
(1)調(diào)用函數(shù)f蚯嫌。
(2)用obj1來替換函數(shù)f中的this。
為什么要替換函數(shù)中的this?
關(guān)鍵字:共享丙躏。
函數(shù)是動(dòng)態(tài)的择示,它可以執(zhí)行特定的功能。
對象是屬性的集合晒旅,它用來保持復(fù)雜的數(shù)據(jù)栅盲,當(dāng)然,它也有自己的方法废恋。
call的意義在于:把函數(shù)共享出來谈秫,讓多個(gè)對象來共同使用。
示例:
var obj1 = {
"p":"obj1",
"f":function(){console.info(this.p);}
}
var obj2 = {
"p":"obj2",
"f":function(){console.info(this.p);}
}
上面定義了兩個(gè)對象鱼鼓,它們的結(jié)構(gòu)大致相同拟烫。
我們通過調(diào)用他們各自的f方法去訪問它們的p屬性:
obj1.f();//obj1
obj2.f();//obj2
上面的代碼中,obj1,obj2中保存的f屬性是完全一樣的迄本,但在內(nèi)存是保存了兩份拷貝:
obj1.f === obj2.f硕淑;//false
這是浪費(fèi)空間。可以改進(jìn)一下:
function f(){console.info(this.p);}
var obj1 = {
"p":"obj1",
"f":f
}
var obj2 = {
"p":"obj2",
"f":f
}
//如下效果是一樣的
obj1.f();//obj1
obj2.f();//obj2
改進(jìn)之在于:
obj1.f === obj2.f置媳;//true
如果你連這個(gè)f屬性都不想要于樟,則就可以把代碼寫成我們前面的樣子:
function f(){ console.info( this.p);}
var obj1 = {"p":"obj1"}
var obj2 = {"p":"obj2"}
f.call(obj1 ); //輸出obj1
f.call(obj2 ); //輸出obj2
保持對象中只存數(shù)據(jù),而具體的操作通過借用函數(shù)來實(shí)現(xiàn)拇囊。