js中 Call Apply 解析
2020-10-20 本文已影响0人
Viker_bar
需要提前知道的知识
一:基本语法
/*
*
*@Des Call语法
*@Param thisArg: 可选的 在function 函数运行时使用的 this 值
*@Param arg1, arg2, ... 可选的 指定的参数列表
*
**/
function.call(thisArg, arg1, arg2, ...)
/*
*
*@Des Apply语法
*@Param thisArg: 可选的 在function函数运行时使用的this值
*@Param [argsArray] 可选的 一个数组或者类数组对象
*
**/
function.apply(thisArg, [argsArray])
二:Apply、Call 方法都会使函数立即执行,因此它们也可以用来调用函数
function func() {
console.log('Hello');
}
func.call(); // Hello
先看一段代码?
function Aee(){
this.userName = "Aee";
this.userAge = "18";
this.userPhone = "15699999999";
this.getUserName = function(){
return this.userName;
}
this.getUserAge = function(){
return this.userAge;
}
}
function Bee(){
Aee.call(this);
this.userAge = "Bee19";
}
function Cee(){
Bee.call(this);
this.userName = "Cee";
}
var cec = new Cee();
console.log(cec.userName); //Cee
console.log(cec.userAge); //Bee19
console.log(cec.userPhone); //15699999999
我们来翻译一下上面的代码:
function Aee(){
this.userName = "Aee";
this.userAge = "18";
this.userPhone = "15699999999";
this.getUserName = function(){
return this.userName;
}
this.getUserAge = function(){
return this.userAge;
}
this.getUserPhone = function(){
return this.userPhone;
}
}
function Bee(){
Aee.call(this); //这句话相当于新增一个指向Aee构造函数的指针(注意:不是改变指针指向,是新增一个新的指针)
//新增指针指向的内容如下:(我继承于Aee构造函数中的内容)
this.userName = "Aee";
this.userAge = "18";
this.userPhone = "15699999999";
this.getUserName = function(){
return this.userName;
}
this.getUserAge = function(){
return this.userAge;
}
this.getUserPhone = function(){
return this.userPhone;
}
//我本来就有,不是继承的
this.userAge = "Bee19";
}
function Cee(){
Bee.call(this); //这句话相当于新增一个指向Bee构造函数的指针(注意:不是改变指针指向,是新增一个新的指针)
//新增指针指向的内容如下:(我继承于Aee构造函数中的内容)
this.userName = "Aee";
this.userAge = "18";
this.userPhone = "15699999999";
this.getUserName = function(){
return this.userName;
}
this.getUserAge = function(){
return this.userAge;
}
this.getUserPhone = function(){
return this.userPhone;
}
//新增指针指向的内容如下:(我继承于Bee构造函数中的内容)
this.userAge = "Bee19";
//我本来就有,不是继承的
this.userName = "Cee";
}
最终结果翻译结果如下:
function Aee(){
this.userName = "Aee";
this.userAge = "18";
this.userPhone = "15699999999";
this.getUserName = function(){
return this.userName;
}
this.getUserAge = function(){
return this.userAge;
}
this.getUserPhone = function(){
return this.userPhone;
}
}
function Bee(){
this.userName = "Aee";
this.userAge = "18";
this.userPhone = "15699999999";
this.getUserName = function(){
return this.userName;
}
this.getUserAge = function(){
return this.userAge;
}
this.getUserPhone = function(){
return this.userPhone;
}
this.userAge = "Bee19";
}
function Cee(){
this.userName = "Aee";
this.userAge = "18";
this.userPhone = "15699999999";
this.getUserName = function(){
return this.userName;
}
this.getUserAge = function(){
return this.userAge;
}
this.getUserPhone = function(){
return this.userPhone;
}
this.userAge = "Bee19";
this.userName = "Cee";
}
var cec = new Cee();
console.log(cec.userName); //Cee
console.log(cec.userAge); //Bee19
console.log(cec.userPhone); //15699999999
用白话再翻译一遍
Aee.call(this);
1:立即运行Aee函数
2:建立新的指针指向Aee构造函数(实现继承的关键)
3:开始获取相关属性或调用相关函数,如果当前作用域里面没有找到,则去查找call函数第一个参数对象,当前也就是this,如果还没有找到,则去Aee里去查找
Bee.call(obj);
1:立即运行Bee函数
2:建立新的指针指向Bee构造函数(实现继承的关键)
3:开始获取相关属性或调用相关函数,如果当前作用域里面没有找到,则去查找call函数第一个参数对象,当前也就是obj,如果还没有找到,则去Bee里去查找
var num = [1,3,5,7,2,-10,11];
Math.max.apply(Math, num);
1:立即运行Math.max函数
2:建立新的指针指向Math.max构造函数(实现继承的关键)
3:开始获取相关属性或调用相关函数,如果当前作用域里面没有找到,则去Math里面去查找max函数,如果还没有找到,则去Math.max里去查找(实际不会走到这一步,上一步已经结束查找了)
var fakeArr = {0:'a',1:'b',length:2};
Array.prototype.slice.call(fakeArr);
1:立即运行Array.prototype.slice函数
2:建立新的指针指向Array.prototype.slice构造函数(实现继承的关键)
3:开始获取相关属性或调用相关函数,如果当前作用域里面没有找到,则去fakeArr里面去查找Array.prototype.slice函数,如果还没有找到,则去Array.prototype.slice里去查找,实际它查找的是Array对象下是否有slice函数
总结:
1:call和apply的使用本质是作用域链的动态添加,且遵循作用域链的查找规则,不管call和apply嵌套层级多深(先查找自身,然后根据嵌套逻辑逐级往上查找)
2:javascript 继承的本质不是复制,是新增指针指向