js 裏函數調用有 4 種模式:方法調用、正常函數調用、構造器函數調用、apply/call 調用。

/**
 * js 裏函數調用有 4 種模式:方法調用、正常函數調用、構造器函數調用、apply/call 調用。
 */
//方法調用:
var a = {
	v:5,
	func : function(value){
		this.v  = value;
		console.log("這是一個方法調用:a.v == " + this.v);
	}
	//這個時候,上面函數裏的 this 就綁定的是這個對象 a。所以 this.v 可以取到對象 a 的屬性 v。
}
a.func(5);

console.log("這個時候,上面函數裏的 this 就綁定的是這個對象 a。所以 this.v 可以取到對象 a 的屬性 v。");


//正常的函數調用:
function f(value){
	this.x = value;
	console.log("這是一個正常的函數調用:this.x == " + this.x + "this 是調用對象,也就是綁定的windows");
	//這個時候,函數 f 裏的 this 綁定的是全局對象,如果是在瀏覽器運行的解釋器中,一般來說是 window 對象。所以這裏 this.x 訪問的其實是 window.x ,當然,如果 window 沒有 x 屬性,那麼你這麼一寫,按照 js 的坑爹語法,就是給 window 對象添加了一個 x 屬性,同時賦值。
}
f(6);


//構造器函數調用:
let handler = function(app){
	this.app = app;
	console.log("this.app=%o", app);
	console.log("this=%o", this);
	console.log("this.prototype=%o", this.prototype); 
	console.log("這是一個構造器函數調用 this.app.name = " + this.app.name + "this 是調用對象,也就是綁定的new出來的Handler對象本身");
}

let app = {
	name:"lxkTest",
	age: 25
}
let Handler = new handler(app);
//如果你在一個函數前面帶上 new 關鍵字來調用,那麼 js 會創建一個 prototype 屬性是此函數的一個新對象,同時在調用這個函數的時候,把 this 綁定到這個新對象上。
//上面這個函數和正常調用的函數寫法上沒什麼區別,只不過在調用的時候函數名前面加了關鍵字 new罷了,這麼一來,this 綁定的就不再是前面講到的全局對象了,而是這裏說的創建的新對象,所以說這種方式其實很危險,因爲光看函數,你不會知道這個函數到底是準備拿來當構造函數用的,還是一般函數用的。


//apply/call 調用:
//上面的 3 種函數調用方式,你可以看到,this 都是自動綁定的
console.log("call() 方法和 apply() 方法很類似,它們的存在都是爲了改變 this 的綁定");
function handlerAbc(app1, app2){
	console.log("this=%o" ,this)
	this.app1 = app1;
	this.app2 = app2;
}
var o = {}; 
handlerAbc.apply(o, [5]);  //第一個參數是綁定給 this 的值,後面接受的是一個數組.
handlerAbc.call(o,66,88);  //第一個參數也是綁定給 this 的值,但是後面接受的是不定參數,而不再是一個數組,也就是說你可以像平時給函數傳參那樣把這些參數一個一個傳遞。
//是不是很神奇,函數 handlerAbc 居然可以給 o 加屬性值。當然,如果你 apply 的第一個參數傳遞 null,那麼在函數 handlerAbc 裏面 this 指針依然會綁定全局對象。

console.log(handlerAbc.app1 + " --- " + handlerAbc.app1);    // undefined 
console.log(o.app1 + " --- " + o.app2);    // 5 


console.log("上面講的無論是 call() 也好, apply() 也好,都是立馬就調用了對應的函數,而 bind() 不會");
//再來說 bind() 函數,上面講的無論是 call() 也好, apply() 也好,都是立馬就調用了對應的函數,而 bind() 不會, 
//bind() 會生成一個新的函數,bind() 函數的參數跟 call() 一致,第一個參數也是綁定 this 的值,後面接受傳遞給函數的不定參數。 
//bind() 生成的新函數返回後,你想什麼時候調就什麼時候調,看下代碼就明白了

var m = {    
    "x" : 1 
}; 
function foo(y) { 
	console.log("y = " + y);
	console.log(this.x + y); 
	console.log("this=%o" ,this);
} 
foo.apply(m, [5]); //立即調用
foo.call(m, 5);    //立即調用
var foo1 = foo.bind(m, 7); //不是立即調用,想什麼時候調就什麼時候調, 當調用foo的時候,this就是m, 在foo函數內當然可以對m進行各種操作,比如說賦值。

console.log("m.x = " + m.x);
foo1(); 



var sum = function(x, y){
    return x+y;
}
//創建一個類似於sum的新函數,但this的值綁定到null
//並且第一個參數綁定到1, 這個新函數的期望只傳入一個實參
var succ = sum.bind(null, 1);
 
console.log(succ(2)); //輸出 3; x 綁定到1,並傳入2作爲實參
 
//另外一個做累計計算的函數
var sum2 = function(y ,z){
    return this.x + y + z;
}
 
//綁定this 和 y
var bindSum2 = sum2.bind({x : 1}, 2);
console.log(bindSum2(3)); //輸出 6; this.x 綁定到1,y綁定到2, z 綁定到3
--------------------- 
作者:Tim貓 
來源:CSDN 
原文:https://blog.csdn.net/zhou_xtao/article/details/17581743 
版權聲明:本文爲博主原創文章,轉載請附上博文鏈接!
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章