一般用來指定this的環(huán)境算凿,在沒有學(xué)之前囱井,通常會(huì)有這些問題。
var a = {
user:"追夢(mèng)子",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
b(); //undefined
我們是想打印對(duì)象a里面的user卻打印出來undefined是怎么回事呢?如果我們直接執(zhí)行a.fn()是可以的晚顷。
var a = {
user:"追夢(mèng)子",
fn:function(){
console.log(this.user);
}
}
a.fn(); //追夢(mèng)子
這里能夠打印是因?yàn)榉寤铮@里的this指向的是函數(shù)a艾扮,那為什么上面的不指向a烛亦?我們?nèi)绻枰私鈚his的指向問題脂矫,請(qǐng)看徹底理解js中this的指向疲憋,不必硬背這篇文章擅憔。
雖然這種方法可以達(dá)到我們的目的具伍,但是有時(shí)候我們不得不將這個(gè)對(duì)象保存到另外的一個(gè)變量中萤皂,那么就可以通過以下方法敛苇。
1叽赊、call()
(1)call 方法可以用來代替另一個(gè)對(duì)象調(diào)用一個(gè)方法恋沃。call 方法可將一個(gè)函數(shù)的對(duì)象上下文從初始的上下文改變?yōu)橛?thisObj 指定的新對(duì)象。
obj1.method1.call(obj2,argument1,argument2)
如上必指,call的作用就是把obj1的方法放到obj2上使用囊咏,后面的argument1..這些做為參數(shù)傳入.
舉一個(gè)具體的例子
function add(a, b) {
alert(a + b);
}
function sub(a, b) {
alert(a - b);
}
add.call(sub, 3, 1);
這個(gè)例子中的意思就是用 add 來替換 sub,add.call(sub,3,1) == add(3,1) 塔橡,所以運(yùn)行結(jié)果為:alert(4); // 注意:js 中的函數(shù)其實(shí)是對(duì)象梅割,函數(shù)名是對(duì) Function 對(duì)象的引用。
看一個(gè)稍微復(fù)雜一點(diǎn)的例子
function Class1() {
this.name = "class1";
this.showNam = function() {
alert(this.name);
}
}
function Class2() {
this.name = "class2";
}
var c1 = new Class1();
var c2 = new Class2();
c1.showNam.call(c2);
注意葛家,call 的意思是把 c1 的方法放到c2上執(zhí)行户辞,原來c2是沒有showNam() 方法,現(xiàn)在是把c1 的showNam()方法放到 c2 上來執(zhí)行癞谒,所以this.name 應(yīng)該是 class2底燎,執(zhí)行的結(jié)果就是 :alert("class2");
還有更有趣的,可以用 call 來實(shí)現(xiàn)繼承
function Class1() {
this.showTxt = function(txt) {
alert(txt);
}
}
function Class2() {
Class1.call(this);
}
var c2 = new Class2();
c2.showTxt("cc");
這樣 Class2 就繼承Class1了弹砚,Class1.call(this) 的 意思就是使用 Class1 對(duì)象代替this對(duì)象双仍,那么 Class2 中不就有Class1 的所有屬性和方法了嗎,c2 對(duì)象就能夠直接調(diào)用Class1 的方法以及屬性了桌吃,執(zhí)行結(jié)果就是:alert(“cc”);
對(duì)的朱沃,就是這樣,這就是 javaScript 如何來模擬面向?qū)ο笾械睦^承的茅诱,還可以實(shí)現(xiàn)多重繼承为流。
function Class10() {
this.showSub = function(a,b) {
alert(a-b);
}
}
function Class11() {
this.showAdd = function(a,b) {
alert(a+b);
}
}
function Class2() {
Class10.call(this);
Class11.call(this);
}
很簡(jiǎn)單,使用兩個(gè) call 就實(shí)現(xiàn)多重繼承了
當(dāng)然让簿,js的繼承還有其他方法,例如使用原型鏈秀睛,這個(gè)不屬于本文的范疇尔当,只是在此說明call 的用法
說了call ,當(dāng)然還有 apply,這兩個(gè)方法基本上是一個(gè)意思
區(qū)別在于 call 的第二個(gè)參數(shù)可以是任意類型椭迎,而apply的第二個(gè)參數(shù)必須是數(shù)組
(2)
var a = {
user:"追夢(mèng)子",
fn:function(){
console.log(this.user); //追夢(mèng)子
}
}
var b = a.fn;
b.call(a);
通過在call方法锐帜,給第一個(gè)參數(shù)添加要把b添加到哪個(gè)環(huán)境中,簡(jiǎn)單來說畜号,this就會(huì)指向那個(gè)對(duì)象缴阎。
call方法除了第一個(gè)參數(shù)以外還可以添加多個(gè)參數(shù),如下:
var a = {
user:"追夢(mèng)子",
fn:function(e,ee){
console.log(this.user); //追夢(mèng)子
console.log(e+ee); //3
}
}
var b = a.fn;
b.call(a,1,2);
2简软、apply()
var a = {
user:"追夢(mèng)子",
fn:function(){
console.log(this.user); //追夢(mèng)子
}
}
var b = a.fn;
b.apply(a);
同樣apply也可以有多個(gè)參數(shù)蛮拔,但是不同的是,第二個(gè)參數(shù)必須是一個(gè)數(shù)組痹升,如下:
var a = {
user:"追夢(mèng)子",
fn:function(e,ee){
console.log(this.user); //追夢(mèng)子
console.log(e+ee); //11
}
}
var b = a.fn;
b.apply(a,[10,1]);
或者
var a = {
user:"追夢(mèng)子",
fn:function(e,ee){
console.log(this.user); //追夢(mèng)子
console.log(e+ee); //520
}
}
var b = a.fn;
var arr = [500,20];
b.apply(a,arr);
//注意如果call和apply的第一個(gè)參數(shù)寫的是null建炫,那么this指向的是window對(duì)象
var a = {
user:"追夢(mèng)子",
fn:function(){
console.log(this); //Window {external: Object, chrome: Object, document: document, a: Object, speechSynthesis: SpeechSynthesis…}
}
}
var b = a.fn;
b.apply(null);
3、bind()
bind方法和call疼蛾、apply方法有些不同肛跌,但是不管怎么說它們都可以用來改變this的指向。
先來說說它們的不同吧察郁。
var a = {
user:"追夢(mèng)子",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
b.bind(a);
我們發(fā)現(xiàn)代碼沒有被打印衍慎,對(duì),這就是bind和call皮钠、apply方法的不同稳捆,實(shí)際上bind方法返回的是一個(gè)修改過后的函數(shù)。
var a = {
user:"追夢(mèng)子",
fn:function(){
console.log(this.user);
}
}
var b = a.fn;
var c = b.bind(a);
console.log(c); //function() { [native code] }
那么我們現(xiàn)在執(zhí)行一下函數(shù)c看看鳞芙,能不能打印出對(duì)象a里面的user
var a = {
user:"追夢(mèng)子",
fn:function(){
console.log(this.user); //追夢(mèng)子
}
}
var b = a.fn;
var c = b.bind(a);
c();
ok眷柔,同樣bind也可以有多個(gè)參數(shù),并且參數(shù)可以執(zhí)行的時(shí)候再次添加原朝,但是要注意的是驯嘱,參數(shù)是按照形參的順序進(jìn)行的。
var a = {
user:"追夢(mèng)子",
fn:function(e,d,f){
console.log(this.user); //追夢(mèng)子
console.log(e,d,f); //10 1 2
}
}
var b = a.fn;
var c = b.bind(a,10);
c(1,2);
總結(jié):call和apply都是改變上下文中的this并立即執(zhí)行這個(gè)函數(shù)喳坠,bind方法可以讓對(duì)應(yīng)的函數(shù)想什么時(shí)候調(diào)就什么時(shí)候調(diào)用鞠评,并且可以將參數(shù)在執(zhí)行的時(shí)候添加,這是它們的區(qū)別壕鹉,根據(jù)自己的實(shí)際情況來選擇使用剃幌。