1. 程式人生 > >我對call與apply的一些理解

我對call與apply的一些理解

call與apply: call與apply最重要的一個作用就是改變函式內的上下文(其實就是改變函式內this的指向) 如果不是一個物件內的方法 this均為當前window物件(可自行在控制檯下測試):

 
function testCall(){
	function yep(){
		for(var i in this){		//取出當前this指向裡的屬性名或方法名
			console.log(i);
		}
	}
	//yep.call(this);
	yep(); 
}
testCall();

	//yep.call(this)與yep()	這兩句無論哪一句執行效果也一樣,預設的this就是當前window,所以call傳this進去也是當前window,
	將yep放在testCall裡面是讓你們知道,只要一個函式不是某個物件的方法,那它的this都是指向window
	即使它不是在全域性區域鏈而是在區域性區域鏈裡


var o = {
"name" : "GaryCheung",
"age" :18
}
testCall();
function testCall(){
	function yep(){
		for(var i in this){		//取出當前this指向裡的屬性名或方法名
			console.log(i);
		}
	}
	yep.call(o);	
}
testCall();
//此處傳了物件o進去,將yep裡面預設指向當前window的this改為了指向物件o的this,所以執行後在控制檯輸出的只有name跟age;



上面都是以call為例子,實際上apply也是一樣的,將上面例子中的call改為apply執行效果也是一樣,call與apply兩者的差別在於引數的傳入。 沒錯,call與apply不僅可以改變上下文(this的指向,也是call與apply最重要的一點),還可以傳入引數,至於為什麼要傳入引數?你定義的函式,沒有引數怎麼可以正常執行? 例如
 function name(arg1,arg2){
var sum = arg1 + arg2;
sum  += this.age;
console.log(sum);
}
var o = {
"name" : "GaryCheung",
"age" :18
}
name.apply(o);
//執行後控制檯輸出的為NaN,因為name需要的引數你沒有給它,即函式內有aarg1與arg2的定義,但是沒有初始化,所以用起來就是undefined
所以最後的sum就是一個NaN;
那麼:
name.apply(o,[12,30]);	//就可以輸出60了;



而引數的傳入方法區別在於 call只能一個一個引數列舉出來,而apply則可以傳一個引數陣列(如果用到apply的函式在內部,那麼arguments也可以傳過去),還是用我們上面的函式例子:
name.call(o,18,20);
name.apply(0,[18,20]);
var array = [18,20];
name.apply(0,array);

在我看來,只要記住 call與apply均能改變他們內部this的指向就可以了(用call或者apply傳進的第一個引數就是內部this的指向)