type - объект function javascript




В чем разница между призывом и подачей заявки? (14)

Резюме:

Оба метода call() и apply() - это методы, которые расположены на Function.prototype . Поэтому они доступны для каждого функционального объекта через цепочку прототипов. И call() и apply() могут выполнять функцию с указанным значением this .

Основное различие между call() и apply() заключается в том, как вы должны передавать в него аргументы. В обоих call() и apply() вы передаете в качестве первого аргумента объект, которым вы хотите быть значением как this . Другие аргументы различаются следующим образом:

  • С call() вы должны нормально вводить аргументы (начиная со второго аргумента)
  • С apply() вы должны передать массив аргументов.

Пример:

let obj = {
  val1: 5,
  val2: 10
}

const summation = function (val3, val4) {
  return  this.val1 + this.val2 + val3 + val4;
}

console.log(summation.apply(obj, [2 ,3]));
// first we assign we value of this in the first arg
// with apply we have to pass in an array


console.log(summation.call(obj, 2, 3));
// with call we can pass in each arg individually

Зачем мне нужно использовать эти функции?

Это значение может быть сложным иногда в javascript. Значение this определяется, когда функция выполняется не при определении функции. Если наша функция зависит от права this привязки, мы можем использовать функции call() и apply() для обеспечения соблюдения этого поведения. Например:

var name = 'unwantedGlobalName';

const obj =  {
  name: 'Willem',
  sayName () { console.log(this.name);}
}


let copiedMethod = obj.sayName;
// we store the function in the copiedmethod variable



copiedMethod();
// this is now window, unwantedGlobalName gets logged

copiedMethod.call(obj);
// we enforce this to be obj, Willem gets logged

В чем разница между использованием call и apply для вызова функции?

var func = function() {
  alert('hello!');
};

func.apply(); vs func.call();

Существуют ли различия в производительности между двумя вышеупомянутыми методами? Когда лучше использовать call over apply и наоборот?


Call () принимает разделенные запятыми аргументы, например:

.call(scope, arg1, arg2, arg3)

и apply () принимает массив аргументов, например:

.apply(scope, [arg1, arg2, arg3])

вот несколько примеров использования: http://blog.i-evaluation.com/2012/08/15/javascript-call-and-apply/


Вот хорошая мнемоника. Pply использует A rrays и A lways принимает один или два аргумента. Когда вы используете C, вы должны указать количество аргументов.


Вызов и применение обоих используются для принудительного использования this значения при выполнении функции. Единственное различие заключается в том, что call принимает n+1 аргументов, где 1 - this и 'n' arguments . apply принимает только два аргумента, один - this другой массив аргументов.

Преимущество, которое я вижу в apply над call состоит в том, что мы можем легко делегировать вызов функции другой функции без особых усилий;

function sayHello() {
  console.log(this, arguments);
}

function hello() {
  sayHello.apply(this, arguments);
}

var obj = {name: 'my name'}
hello.call(obj, 'some', 'arguments');

Обратите внимание, как легко мы делегировали hello чтобы sayHello использование hello apply , но с call этого очень трудно достичь.


Другой пример с Call, Apply и Bind. Разница между Call и Apply очевидна, но Bind работает следующим образом:

  1. Bind возвращает экземпляр функции, которая может быть выполнена
  2. Первый параметр - это « это »
  3. Второй параметр - список аргументов, разделенных запятыми (например, Call )

}

function Person(name) {
    this.name = name; 
}
Person.prototype.getName = function(a,b) { 
     return this.name + " " + a + " " + b; 
}

var reader = new Person('John Smith');

reader.getName = function() {
   // Apply and Call executes the function and returns value

   // Also notice the different ways of extracting 'getName' prototype
   var baseName = Object.getPrototypeOf(this).getName.apply(this,["is a", "boy"]);
   console.log("Apply: " + baseName);

   var baseName = Object.getPrototypeOf(reader).getName.call(this, "is a", "boy"); 
   console.log("Call: " + baseName);

   // Bind returns function which can be invoked
   var baseName = Person.prototype.getName.bind(this, "is a", "boy"); 
   console.log("Bind: " + baseName());
}

reader.getName();
/* Output
Apply: John Smith is a boy
Call: John Smith is a boy
Bind: John Smith is a boy
*/

Из документов MDN на Function.prototype.apply () :

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

Синтаксис

fun.apply(thisArg, [argsArray])

Из документов MDN на Function.prototype.call () :

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

Синтаксис

fun.call(thisArg[, arg1[, arg2[, ...]]])

From Function.apply и Function.call в JavaScript :

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

Пример кода:

var doSomething = function() {
    var arr = [];
    for(i in arguments) {
        if(typeof this[arguments[i]] !== 'undefined') {
            arr.push(this[arguments[i]]);
        }
    }
    return arr;
}

var output = function(position, obj) {
    document.body.innerHTML += '<h3>output ' + position + '</h3>' + JSON.stringify(obj) + '\n<br>\n<br><hr>';
}

output(1, doSomething(
    'one',
    'two',
    'two',
    'one'
));

output(2, doSomething.apply({one : 'Steven', two : 'Jane'}, [
    'one',
    'two',
    'two',
    'one'
]));

output(3, doSomething.call({one : 'Steven', two : 'Jane'},
    'one',
    'two',
    'two',
    'one'
));

См. Также этот скрипт .


Мы можем дифференцировать методы вызова и применения, как показано ниже

CALL: функция с аргументом предоставляется индивидуально. Если вы знаете переданные аргументы или нет аргументов, вы можете использовать вызов.

APPLY: вызов функции с аргументом, представленным в виде массива. Вы можете использовать apply, если вы не знаете, сколько аргументов будет передано функции.

Существует преимущество использования метода over over call, нам не нужно изменять количество аргументов, только мы можем изменить передаваемый массив.

В производительности нет большой разницы. Но мы можем сказать, что вызов бит быстрее, чем сравнение, потому что массив должен оцениваться в методе apply.


Несмотря на то, что call и apply достигают одинакового результата, я думаю, что по крайней мере одно место, где вы не можете использовать call но можете использовать его. Это то, когда вы хотите поддерживать наследование и хотите вызвать конструктор.

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

function makeClass( properties ) {
    var ctor = properties['constructor'] || function(){}
    var Super = properties['extends'];
    var Class = function () {
                 // Here 'call' cannot work, only 'apply' can!!!
                 if(Super)
                    Super.apply(this,arguments);  
                 ctor.apply(this,arguments);
                }
     if(Super){
        Class.prototype = Object.create( Super.prototype );
        Class.prototype.constructor = Class;
     }
     Object.keys(properties).forEach( function(prop) {
           if(prop!=='constructor' && prop!=='extends')
            Class.prototype[prop] = properties[prop];
     });
   return Class; 
}

//Usage
var Car = makeClass({
             constructor: function(name){
                         this.name=name;
                        },
             yourName: function() {
                     return this.name;
                   }
          });
//We have a Car class now
 var carInstance=new Car('Fiat');
carInstance.youName();// ReturnsFiat

var SuperCar = makeClass({
               constructor: function(ignore,power){
                     this.power=power;
                  },
               extends:Car,
               yourPower: function() {
                    return this.power;
                  }
              });
//We have a SuperCar class now, which is subclass of Car
var superCar=new SuperCar('BMW xy',2.6);
superCar.yourName();//Returns BMW xy
superCar.yourPower();// Returns 2.6

Основное различие заключается в том, что с помощью вызова мы можем изменить область действия и передать аргументы как обычно, но применить это позволяет вызывать ее с использованием аргументов в виде массива (передать их как массив). Но с точки зрения того, что они делают в вашем коде, они довольно похожи.

Хотя синтаксис этой функции почти идентичен силе apply (), основное отличие состоит в том, что call () принимает список аргументов, а apply () принимает один массив аргументов.

Итак, как вы видите, нет большой разницы, но все же есть случаи, когда мы предпочитаем использовать call () или apply (). Например, просмотрите приведенный ниже код, который находит наименьшее и наибольшее число в массиве из MDN, используя метод apply:

// min/max number in an array
var numbers = [5, 6, 2, 3, 7];

// using Math.min/Math.max apply
var max = Math.max.apply(null, numbers); 
// This about equal to Math.max(numbers[0], ...)
// or Math.max(5, 6, ...)

var min = Math.min.apply(null, numbers)

Поэтому основное отличие заключается в том, как мы передаем аргументы:

Вызов:

function.call(thisArg, arg1, arg2, ...);

Применять:

function.apply(thisArg, [argsArray]);

Разница в том, что apply позволяет вызывать функцию с arguments как массив; call требует, чтобы параметры были указаны явно. Полезной мнемонической является « A для рва и C для c omma».

См. Документацию MDN по apply и call .

Псевдо-синтаксис:

theFunction.apply(valueForThis, arrayOfArgs)

theFunction.call(valueForThis, arg1, arg2, ...)

Существует также, с ES6, возможность spread массива для использования с функцией call , вы можете увидеть совместимость here .

Образец кода:

function theFunction(name, profession) {
    console.log("My name is " + name + " and I am a " + profession +".");
}
theFunction("John", "fireman");
theFunction.apply(undefined, ["Susan", "school teacher"]);
theFunction.call(undefined, "Claude", "mathematician");
theFunction.call(undefined, ...["Matthew", "physicist"]); // used with the spread operator


Разница между этими методами заключается в том, как вы хотите передать параметры.

«A для массива и C для запятой» - это полезная мнемоника.


У К. Скотта Аллена хорошая запись по этому вопросу.

В основном, они отличаются тем, как они обрабатывают аргументы функции.

Метод apply () идентичен вызову (), за исключением того, что apply () требует, чтобы в качестве второго параметра был выбран массив. Массив представляет аргументы для целевого метода. "

Так:

// assuming you have f
function f(message) { ... }
f.call(receiver, "test");
f.apply(receiver, ["test"]);

Чтобы ответить на вопрос о том, когда использовать каждую функцию, используйте apply если вы не знаете количество аргументов, которые вы передадите, или если они уже находятся в массиве или подобном массиву объекте (например, объект arguments для перенаправления собственных аргументы. Используйте call иначе, так как нет необходимости обертывать аргументы в массиве.

f.call(thisObject, a, b, c); // Fixed number of arguments

f.apply(thisObject, arguments); // Forward this function's arguments

var args = [];
while (...) {
    args.push(some_value());
}
f.apply(thisObject, args); // Unknown number of arguments

Когда я не передаю какие-либо аргументы (например, ваш пример), я предпочитаю call так как я call функцию. apply будет означать, что вы применяете эту функцию к (несуществующим) аргументам.

Не должно быть никаких различий в производительности, за исключением, может быть, если вы используете apply и wrap аргументы в массиве (например, f.apply(thisObject, [a, b, c]) вместо f.call(thisObject, a, b, c) ). Я не тестировал его, поэтому могут быть различия, но это было бы очень специфично для браузера. Вероятно, call выполняется быстрее, если у вас еще нет аргументов в массиве, и apply выполняется быстрее, если вы это сделаете.


Я хотел бы показать пример, где используется аргумент valueForThis:

Array.prototype.push = function(element) {
   /*
   Native code*, that uses 'this'       
   this.put(element);
   */
}
var array = [];
array.push(1);
array.push.apply(array,[2,3]);
Array.prototype.push.apply(array,[4,5]);
array.push.call(array,6,7);
Array.prototype.push.call(array,8,9);
//[1, 2, 3, 4, 5, 6, 7, 8, 9] 

** подробнее: http://es5.github.io/#x15.4.4.7 *





dynamic