call()的基本用法
语法
fun.call(thisArg, arg1, arg2, …)
参数
thisArg
在fun函数运行时指定的this值。需要注意的是,指定的this值并不一定是该函数执行时真正的this值,如果这个函数处于non-strict mode,则指定为null和undefined的this值会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的this会指向该原始值的自动包装对象。
arg1, arg2, …
指定的参数列表。
返回值
使用调用者提供的this值和参数调用该函数的返回值。若该方法没有返回值,则返回undefined。
描述
call()允许为不同的对象分配和调用属于一个对象的函数/方法。
call()提供新的 this 值给当前调用的函数/方法。你可以使用call来实现继承:写一个方法,然后让另外一个新的对象来继承它(而不是在新对象中再写一次这个方法)。
示例
window.name = "window-name"
document.name = "document-name"
const obj = {
name: "obj-name"
};
function handleName() {
console.log(this.name);
}
handleName.call() // window-name(如果没有参数,默认指向是window)
handleName.call(window) // window-name
handleName.call(document) // document-name
handleName.call(this) // window-name
handleName.call(obj) // obj-name
我们重点看下这个 handleName.call(obj) // obj-name
call(obj)使handleName的this指向发生了变化,从原来的window变到了obj
我们可以在函数handleName打印this,已观察this的变化
const obj = {
name: "obj-name"
};
function handleName() {
console.log(this);
}
handleName.call()
handleName.call(obj)
输出:
上面的例子中,函数handleName有一个方法call,call不是函数handleName通过原型继承得到的,
function handleName() {
console.log(this.name);
}
console.log(handleName.prototype.call)
输出:
call方法在handleName的原型对象中输出undefined,所以call不是函数handleName通过原型继承得到的
如果了解继续往下看
const LJJ = {
name: "刘家军",
doSth(dear) {
console.log(`${this.name}陪${dear}`);
}
};
const YH = {
name: "袁姮"
};
LJJ.doSth.call(YH, "小仙女");
输出:
调用了LJJ下doSth的call方法,并传入YH,改变了doSth下this的指向,最终输出 “袁姮陪小仙女”
我们稍微扩展一下,上面的代码做一下改动
function Ljj(name) {
this.name = name
this.doSth = function (dear) {
console.log(`${this.name}陪${dear}`);
}
}
function Yh(name) {
this.name = name
}
const LJJ = new Ljj("刘家军")
const YH = new Yh("袁姮")
LJJ.doSth("小仙女") // 刘家军陪小仙女
LJJ.doSth.call(YH, "小仙女") // 袁姮陪小仙女
Ljj和Yh这两个是自定义的构造函数,
通过Ljj实例化一个函数LJJ
通过Yh实例化一个函数YH
调用函数LJJ的doSth方法,
我们打印一下LJJ函数
function Ljj(name) {
this.name = name
this.doSth = function (dear) {
console.log(this.name);
}
}
function Yh(name) {
this.name = name
}
const LJJ = new Ljj("刘家军")
const YH = new Yh("袁姮")
LJJ.doSth()
LJJ.doSth.call(YH)
输出:
可以看出LJJ.doSth中this.name指向 “刘家军”,即this指向LJJ,
而当LJJ.doSth.call(YH)时,this.name指向"袁姮",即this发生了改变指向了YH
一个call的经典案例
function add(a, b) {
console.log('add',this)
console.log('a+b:',a+b)
}
function sub(a, b) {
console.log('sub',this)
console.log('a-b:',a-b)
}
add.call(sub, 1, 2) // 3
输出:
对上面的输出和结果是不是感到很意外?
分析一下
首先是调用的add的call方法,并传入了第一个参数sub,
执行的还是add方法,但是add方法内this的指向变了,this指向了sub,所以会出现上面的输出
为什么结果是3?
调用的是add方法,add方法中的this指向的是sub,然而add.call,还传入了第二个和第三个参数(3,1)
他们分别是add方法中的a和b,a+b就是1+2 = 3