JavaScript面向对象 (call()方法)

版权声明:刘家军 https://blog.csdn.net/qq_42911663/article/details/85484484

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

猜你喜欢

转载自blog.csdn.net/qq_42911663/article/details/85484484