使用 JS .call() 方法的原因?

IT技术 javascript function methods this
2021-02-17 10:20:48

我对在 JS 中使用 call() 方法的原因很感兴趣。它似乎重复了通常的调用方法this

例如,我有一个带有 call() 的代码。

var obj = {
    objType: "Dog"
}

f = function(did_what, what) {
    alert(this.objType + " " + did_what + " " + what);
}

f.call(obj, "ate", "food");

输出是“Dog ate food”。但是同样的结果我可以将函数分配给对象。

var obj = {
    objType: "Dog"
}

f = function(did_what, what) {
    alert(this.objType + " " + did_what + " " + what);
}

obj.a = f;
obj.a("ate", "food");

结果是一样的。但是这种方式更容易理解,使用起来也方便。为什么需要 call() ?

5个回答

call当您想要控制将在调用的函数中使用的范围时使用。您可能希望this关键字不是您为函数分配的范围,在这些情况下,您可以使用callapply使用您自己的范围调用函数。

F.ex,它还允许您在范围之外调用实用程序方法,例如使用“私有”函数时:

var obj = (function() {
    var privateFn = function() {
        alert(this.id);
    }
    return {
        id: 123,
        publicFn: function() {
            privateFn.call(this);
        }
    };
}());

obj.publicFn();

在上面的例子中,privateFn没有暴露在,obj但它仍然可以被构造为好像它是公共范围的一部分(this以相同的方式使用)。

@Curtis 在此示例中,您别无选择,请尝试publicFn: function() { ... }publicFn: privateFn.bind(this). 当您定义函数时,您返回的对象尚未创建,因此上下文只是window,因为此时没有其他上下文。
2021-04-23 10:20:48
但是控制范围是绑定的目的,因此您可以执行 privateFn.bind(this)(); 那么通话是必要的还是看起来更好?
2021-04-26 10:20:48
publicFn: function() { privateFn.bind(this)(); 好吧,您可以这样做,因此调用不需要存在于 javascript 中,因为您通常使用括号调用函数,并且永远不需要调用。
2021-04-26 10:20:48
@Curtisbind创建函数的新副本,而call不会创建此外,fn.bind(this)('foo')是一个不太可读的版本fn.call(this, 'foo')
2021-04-28 10:20:48

2017年更新

所有通过 Function.prototype 的函数都有.call方法。使用的原因.call()是指定变量“ this”指的是什么

MDN 规定:

call()方法使用给定的 this 值和单独提供的参数调用函数。

考虑以下:

function x() {
    return this;
}

x()

在严格模式下x()返回undefined在非严格模式下,它返回全局对象,Window在浏览器环境。

例如,.call()我们告诉它“ this”指的是什么

function x() {
    return this;
}

var obj = {
    myName      : 'Robert',
    myLocation  : 'Earth'
}

x.call(obj);

结果:{myName: "Robert", myLocation: "Earth"}在上面的例子中,我们将obj对象指定this函数内部的值x()

它可用于模拟 OOP 中的继承。

例子:

var Robert = {
    name: "Robert Rocha",
    age: 12,
    height: "5,1",
    sex: "male",
    describe: function() {
        return "This is me " + this.name + " " + this.age + " " + this.height + " " + this.sex;
    }
};

假设上面是一个主对象(原型),并且您想describe在另一个对象中继承该功能

var Richard = {
    name: "Richard Sash",
    age: 25,
    height: "6,4",
    sex: "male",
}

Richard对象没有描述功能,您只想继承,可以说,该功能。你会这样做:

console.log( Robert.describe.call( Richard ) );

输出: This is me Richard Sash 25 6,4 male

本示例中的@TomSawyerthis指的是当前对象,即调用对象。随着.call()你可以写一个方法一次,继承它在你选择的另一个目的,而不必再写一遍,走的DRY原则护理。
2021-04-17 10:20:48
很好的解释!谢谢!
2021-04-19 10:20:48
拥有一个Person带有原型函数对象,describe然后 Robert/Richard 可以基于这个对象(即var Robert = new Person(...);)...我猜你上面提到罗伯特是一个主对象,所以我猜我们会使用.call在我们需要将另一个对象的函数用于另一个对象的地方?
2021-04-24 10:20:48
谢谢。你的回答很容易理解。
2021-04-30 10:20:48
这个答案没有解释方法中是否有this参数,call如:Robert.describe.call(this,Richard)这里的作用是this什么?
2021-05-04 10:20:48

您可能会在示例中使用第二种方式,但有时您想在另一个对象上使用一个对象的函数。一个例子是Array在类似数组的对象上使用方法,比如NodeLists

var el = document.getElementById("foo");
[].forEach.call(el.children, function(child, index) {
    //Iterate over an element's children, performing an action on each one
});

这与一等函数的概念有关基本上,像 Javascript 这样的语言允许您将函数视为自己的权利。函数可以存储在变量中或传递给其他函数。

call() 提供了一种执行不附加到任何其他对象的独立功能的方法。

你能提供一个例子吗?(“一种执行独立功能的方法”)。我们可以不调用函数call()吗?
2021-04-27 10:20:48

读完后,我明白了为什么。

JavaScript 新手的一个常见错误是从一个对象中提取一个方法,然后调用该函数并期望它使用原始对象作为它的对象this(例如,通过在基于回调的代码中使用该方法)。

但是,如果没有特别注意,原始对象通常会丢失从函数创建绑定函数,使用原始对象,巧妙地解决了这个问题:

this.x = 9;    // 'this' refers to global 'window' object here in a browser
const module = {
  x: 81,
  getX: function() { return this.x; }
};

module.getX();
//  returns 81

const retrieveX = module.getX;
retrieveX();
//  returns 9; the function gets invoked at the global scope

//  Create a new function with 'this' bound to module
//  New programmers might confuse the
//  global variable 'x' with module's property 'x'
const boundGetX = retrieveX.bind(module);
boundGetX();
//  returns 81

原点在这里