【笔记13】Javascript - call 、apply

一般我们在执行一个函数时的写法是:

// test();   实际相当于 test.call(); 即不传参数的call

call / apply

作用:改变 this 指向。

区别:后面传的参数形式不同。

这个call是怎么改变 this 指向的? 

function Person(name, age) {
this.name = name;
this.age = age;
}
var obj = {};

这是一个构造函数和一个空对象。

我们来个:

Person.call(obj);

会发生什么?他会让 Person 里面预设的 this 全部变成 obj。

这里的 this 默认指向 window ,这个时候call 一个 obj 进去,这里的 this 就不再指向 window了,而是 obj,相当于Person里的this等于 obj 。

function Person(name, age) {
// this == obj
// obj.name = name;
// obj.age = age;
}
var obj = {};
Person.call(obj);

而且可以传递参数: name 和 age ,传参的时候写在 obj 的后面就可以了。

function Person(name, age) {
// this == obj
this.name = name;
this.age = age;
}
var obj = {};
Person.call(obj,"Jack",30);

在控制台看一下 obj :

Javascript(笔记13) - call 、apply_javascript

call 的第一个参数,可以改变 this 的指向,第二位以后的参数,会当做正常的实参传进去。

obj 通过 call 借用了 Person 的方法,成全了自己的功能。

示例1:

function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade) {
this.name = name;
this.age = age;
this.sex = sex;
this.tel = tel;
this.grade = grade;
}
var student = new Student();

Strudent 是不是完美涵盖了 Person 的功能,重复了,我们可以通过 call 来简化这个函数。

function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade) {
// var this = {name:"",age:"",sex:""}
Person.call(this, name, age, sex);
this.tel = tel;
this.grade = grade;
}
var student = new Student("Jack", 30, "male", 153, "2022");

看下控制台输出:

Javascript(笔记13) - call 、apply_apply_02

通过 call 来改变了 this 的指向,Student 成功借用了 Person 实现了重复部分的功能。


示例2:

function Wheel(size,style){
this.size = size;
this.style = style;
}
function Sit(comfort,color){
this.comfort = comfor;
this.color = color;
}
function Model(height,width){
this.height = height;
this.width = width;
}
function Car(size,style,comfort,color,height,width){
Wheel.call(this,size,style);
Sit.call(this,comfort,color);
Model.call(this,height,width);
}
var car = new Car();

造车工厂,很多车间,最后组装成车,可以把各车间的方法全部 call 过来。

Javascript(笔记13) - call 、apply_javascript_03

实际开发中,总有人要写零部件,最后拿去组装。


apply

和 call 的主要区别是传参列表不一样。他们传参的时候,第一位都是改变 this 指向的对象。

call 需要把实参按照形参的个数传进去;

apply 需要传一个arguments;

所以,上面的代码可以改用 apply 

function Wheel(size,style){
this.size = size;
this.style = style;
}
function Sit(comfort,color){
this.comfort = comfor;
this.color = color;
}
function Model(height,width){
this.height = height;
this.width = width;
}
function Car(size,style,comfort,color,height,width){
Wheel.apply(this,[size,style]); // 传了一个 arguments
Sit.apply(this,[comfort,color]);
Model.apply(this,[height,width]);
}
var car = new Car();