在工作中經常看到有使用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);
複製程式碼
輸出結果如下:
結果分析:當給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]);
複製程式碼
輸出結果如下:
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。
呼叫var 11=new Teacher("張三",30)時,因為呼叫了Person.apply(this, [age,name])。Person建構函式中的this指的是Teacher。所有返回的是如下物件。
分析:Person.apply(this, [age,name])中的this在new Teacher()時指的是Teacher,所以Person.apply(this, [age,name])這句程式碼的返回的是一個Teacher例項物件。