Причина использования метода JS.call()?

Мне интересно, в чем причина использования метода call() в JS. Кажется, он дублирует обычный метод вызова this.

Например, у меня есть код с вызовом().

var obj = {
    objType: "Dog"
}

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

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

Результат - "Собаки съели пищу". Но тот же результат я могу получить назначение функции объекту.

var obj = {
    objType: "Dog"
}

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

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

Результат тот же. Но этот способ более понятен и удобен в использовании. Зачем нужен вызов()?

Ответ 1

call используется, когда вы хотите управлять областью, которая будет использоваться в вызываемой функции. Возможно, вам нужно, чтобы ключевое слово this было чем-то иным, чем область, к которой вы назначили эту функцию, в этих случаях вы можете использовать call или apply для вызова функции с вашей собственной областью.

F.ex, он также позволяет вызывать методы утилиты вне области видимости, например, при использовании функций "private":

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

obj.publicFn();

В приведенном выше примере privateFn не отображается в obj, но он все равно может быть сконструирован так, как если бы он был частью общедоступной области (используя this таким же образом).

Ответ 2

Обновление 2017

Все функции в функции Function.prototype имеют метод .call. Причиной использования .call() является указание того, к чему относится переменная "this".

MDN указывает:

Метод call() вызывает функцию с заданным значением и аргументы, предоставленные индивидуально.

Рассмотрим следующее:

function x() {
    return this;
}

x()

В строгом режиме x() возвращает undefined в нестандартном режиме, он возвращает объект Global, Window в контексте браузера.

Пример с .call() мы расскажем, что означает "this":

function x() {
    return this;
}

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

x.call(obj);

Результат: {myName: "Robert", myLocation: "Earth"}. В приведенном выше примере мы указываем объект obj как значение this внутри функции x()

Его можно использовать для эмуляции наследования в ООП.

Пример:

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

Ответ 3

Вероятно, вы использовали бы второй способ в своем примере, но иногда вы хотите использовать одну функцию объекта на другом объекте. Примером может быть использование методов Array для объектов типа Array, таких как NodeList s

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

Ответ 4

Это связано с концепцией функции первого класса. В основном языки, такие как Javascript, позволяют вам рассматривать функции как свои вещи. Функции могут храниться в переменных или передаваться другим функциям.

call() обеспечивает способ выполнения функции свободного стояния, не привязанной к какому-либо другому объекту.