對javascript中的call()和apply()的理解

慕斯不想說話發表於2019-01-02

 在工作中經常看到有使用call和apply這連個方法,每次看到後都會去網上搜一下用法,然而過一段時間就又不會了,歸根到底是自己沒有理解他的原理,這次準備徹底弄懂,並把自己的理解總結下來

作用主要有兩點:

1、允許為不同的物件分配和呼叫屬於一個物件的函式/方法,也就是改變函式執行的作用域;
2、提供新的 this 值給當前呼叫的函式/方法。

1、fun.call(thisArg, arg1, arg2, ...)

引數 描述
thisArg 在fun函式執行時指定的this值。
arg1,arg2 指定的引數列表,必須一個一個的列出來

下面來看幾個例子:

function Person(name, age) {
	this.name = name;
	this.age = age;
}
Person.prototype.sayHi = function(a,b) {
	console.log("this的值:" + this)
	console.log("sayhi:" + this.name + ":" + this.age + ",引數的個數:" + arguments.length);
}
var p1 = new Person("小白", 2);
p1.sayHi.call();
p1.sayHi.call(null);
p1.sayHi.call(undefined);
p1.sayHi.call("1");
p1.sayHi.call(true);
var obj = {
	name: "張三",
	age: 21
}
p1.sayHi.call(obj);
function Teacher(name, age) {
	this.name = name;
	this.age = age;
}
var t1 = new Teacher("張三", 18);
p1.sayHi.call(t1, 1, 2, 3); 
複製程式碼

輸出結果如下:

對javascript中的call()和apply()的理解

  結果分析:當給fun.call()中的thisObj賦值為空、null、undefined時,函式fun中的this值指向window。

1、fun.apply(thisArg, [arguments])

引數 描述
thisArg 在fun函式執行時指定的this值。
arguments 指定的引數陣列

  apply()和call()這兩個方法的用途是一樣的,都是在特定的作用域中呼叫函式,實際上就是設定函式fun內的this物件的值。call()和apply()的區別在於call()裡傳遞的引數必須一個一個的列出來,apply裡傳遞的引數可以是陣列也可以是arguments物件。

區別可見如下程式碼:

function Person(name, age) {
	this.name = name;
	this.age = age;
}
Person.prototype.sayHi = function(a,b) {
	console.log("a的值:"+a);
	console.log("b的值:"+b);
	console.log("this的值:" + this)
	console.log("sayhi:" + this.name + ":" + this.age + ",引數的個數:" + arguments.length);
}	
var obj={
	name:"李四",
	age:25
}
var p1=new Person("張三",30);
p1.sayHi.call(obj, 1, 2, 3);
p1.sayHi.call(obj, [1,2,3]);
p1.sayHi.apply(obj, [1,2,3]); 
複製程式碼

輸出結果如下:

對javascript中的call()和apply()的理解

3、call()和apply的常見用法:apply常常被用於陣列操作。

1、如合併兩個陣列,且改變原陣列。

var array = ['a', 'b'];     
var elements = [0, 1, 2];   
array.push.apply(array, elements);  
console.log(array); // ["a", "b", 0, 1, 2]  
複製程式碼

2、如求取陣列中的最大最小值。

var numbers = [5, 6, 2, 3, 7];  
var max = Math.max.apply(null, numbers);    
/* 基本等同於 Math.max(5, 6, 2, 3, 7)  */   
var min = Math.min.apply(null, numbers);  
 /* 基本等同於 Math.min(5, 6, 2, 3, 7)  */ 
複製程式碼

3、實現繼承

function Person(name, age) {
	this.name = name;
	this.age = age;
	this.showName = function() {
		console.log(this.name);
	};
	this.showAge = function() {
		console.log(this.age);
	}
}
function Teacher(name, age) {
	Person.apply(this, [age,name]);
}
var p1=new Person("李四",25);
var t1 = new Teacher("張三", 30);
t1.showName();//"張三"
t1.showAge();//30
複製程式碼

  呼叫var p1=new Person("李四",25)時返回的是如下物件。Person建構函式中的this指的是Person。

對javascript中的call()和apply()的理解

  呼叫var 11=new Teacher("張三",30)時,因為呼叫了Person.apply(this, [age,name])。Person建構函式中的this指的是Teacher。所有返回的是如下物件。

對javascript中的call()和apply()的理解

  分析:Person.apply(this, [age,name])中的this在new Teacher()時指的是Teacher,所以Person.apply(this, [age,name])這句程式碼的返回的是一個Teacher例項物件。

相關文章