javascript usar Qual é a diferença entre ligar e aplicar?




script type= text/javascript src= (16)

Aqui está um pequeno post, escrevi sobre isso:

http://sizeableidea.com/call-versus-apply-javascript/

var obj1 = { which : "obj1" },
obj2 = { which : "obj2" };

function execute(arg1, arg2){
    console.log(this.which, arg1, arg2);
}

//using call
execute.call(obj1, "dan", "stanhope");
//output: obj1 dan stanhope

//using apply
execute.apply(obj2, ["dan", "stanhope"]);
//output: obj2 dan stanhope

//using old school
execute("dan", "stanhope");
//output: undefined "dan" "stanhope"

Qual é a diferença entre usar call e apply para invocar uma função?

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

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

Existem diferenças de desempenho entre os dois métodos acima mencionados? Quando é melhor usar o apply call over e vice-versa?


Gostaria de mostrar um exemplo, onde o argumento 'valueForThis' é usado:

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] 

** detalhes: http://es5.github.io/#x15.4.4.7 *


Outro exemplo com Call, Apply e Bind. A diferença entre Call e Apply é evidente, mas Bind funciona assim:

  1. Vincular retorna uma instância de uma função que pode ser executada
  2. Primeiro Parâmetro é ' this '
  3. Segundo parâmetro é uma lista de argumentos separados por vírgulas (como Chamada )

}

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
*/

Resumo:

Ambos call() e apply() são métodos que estão localizados em Function.prototype . Portanto, eles estão disponíveis em todos os objetos de função através da cadeia de protótipos. Ambos call() e apply() podem executar uma função com um valor especificado do this .

A principal diferença entre call() e apply() é a maneira que você tem que passar argumentos nele. Em ambos, call() e apply() você passa como primeiro argumento o objeto que você quer que seja o valor como this . Os outros argumentos diferem da seguinte maneira:

  • Com call() você tem que colocar os argumentos normalmente (a partir do segundo argumento)
  • Com apply() você tem que passar em array de argumentos.

Exemplo:

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

Por que eu precisaria usar essas funções?

this valor pode ser complicado, por vezes, em javascript. O valor this determinado quando uma função é executada não quando uma função é definida. Se nossa função depender de um direito this ligação, podemos usar call() e apply() para reforçar esse comportamento. Por exemplo:

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


Aqui está um bom mnemônico. Um pply usa A rrays e A lways leva um ou dois argumentos. Quando você usa C, tudo o que você precisa para calcular o número de argumentos.


Chamar e aplicar ambos são usados ​​para forçar this valor quando uma função é executada. A única diferença é que a call recebe n+1 argumentos em que 1 é this e 'n' arguments . apply leva apenas dois argumentos, um é o outro array de argumentos.

A vantagem que vejo em apply over call é que podemos facilmente delegar uma chamada de função para outra função sem muito esforço;

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

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

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

Observe a facilidade com que delegamos o hello para sayHello hello usando " apply , mas com a call isso é muito difícil de conseguir.


A diferença é que call() pega os argumentos da função separadamente e apply() pega os argumentos da função em uma matriz.


Podemos diferenciar chamada e aplicar métodos como abaixo

CALL: Uma função com argumento fornece individualmente. Se você conhece os argumentos a serem passados ​​ou não há argumentos para passar, você pode usar a chamada.

APLICAR: Chame uma função com argumento fornecido como uma matriz. Você pode usar apply se não souber quantos argumentos vão passar para a função.

Há uma vantagem de usar o comando over call, não precisamos alterar o número de argumentos apenas podemos alterar um array que é passado.

Não há grande diferença no desempenho. Mas podemos dizer que a chamada é um pouco mais rápida, como comparar para aplicar porque uma matriz precisa avaliar no método apply.


A principal diferença é que, usando a chamada, podemos alterar o escopo e passar os argumentos como normais, mas aplicar permite chamá-lo usando argumentos como uma matriz (passá-los como matriz). Mas em termos do que eles fazem em seu código, eles são bem parecidos.

Embora a sintaxe dessa função seja quase idêntica à de apply (), a diferença fundamental é que call () aceita uma lista de argumentos, enquanto apply () aceita uma única matriz de argumentos.

Então, como você vê, não há uma grande diferença, mas ainda há casos em que preferimos usar call () ou apply (). Por exemplo, observe o código abaixo, que encontra o menor e maior número em uma matriz do MDN, usando o método 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)

Então a principal diferença é a maneira como passamos os argumentos:

Ligar:

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

Aplique:

function.apply(thisArg, [argsArray]);

Diferença entre estes para métodos são, como você deseja passar os parâmetros.

"A para matriz e C para vírgula" é um mnemônico útil.


Para responder a parte sobre quando usar cada função, use apply se você não souber o número de argumentos que você estará passando, ou se eles já estiverem em um array ou objeto do tipo array (como o objeto arguments para encaminhar seu próprio Use a call outra forma, pois não há necessidade de agrupar os argumentos em uma matriz.

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

Quando não estou passando nenhum argumento (como o seu exemplo), prefiro call já que estou chamando a função. apply implicaria que você está aplicando a função aos argumentos (inexistentes).

Não deve haver nenhuma diferença de desempenho, exceto talvez se você usar apply e encapsular os argumentos em uma matriz (por exemplo, f.apply(thisObject, [a, b, c]) vez de f.call(thisObject, a, b, c) ). Eu não testei, então poderia haver diferenças, mas seria muito específico do navegador. É provável que a call seja mais rápida se você ainda não tiver os argumentos em uma matriz e apply é mais rápido se você fizer isso.


Embora este seja um tópico antigo, eu só queria ressaltar que o .call é um pouco mais rápido que o .apply. Eu não posso te dizer exatamente por quê.

Veja jsPerf, http://jsperf.com/test-call-vs-apply/3

[ UPDATE! ]

Douglas Crockford menciona brevemente a diferença entre os dois, o que pode ajudar a explicar a diferença de desempenho ... http://youtu.be/ya4UHuXNygM?t=15m52s

Aplicar leva uma matriz de argumentos, enquanto a chamada leva zero ou mais parâmetros individuais! Ah hah!

.apply(this, [...])

.call(this, param1, param2, param3, param4...)


K. Scott Allen escreveu um bom artigo sobre o assunto.

Basicamente, eles diferem em como eles lidam com argumentos de função.

O método apply () é idêntico a call (), exceto que apply () requer uma matriz como o segundo parâmetro. A matriz representa os argumentos para o método de destino. "

Assim:

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

A diferença fundamental é que call() aceita uma lista de argumentos , enquanto apply() aceita uma única matriz de argumentos .


Dos documentos do MDN em Function.prototype.apply () :

O método apply () chama uma função com um determinado valor e argumentos fornecidos como uma matriz (ou um objeto do tipo array).

Sintaxe

fun.apply(thisArg, [argsArray])

Dos documentos do MDN em Function.prototype.call () :

O método call () chama uma função com um determinado valor e argumentos fornecidos individualmente.

Sintaxe

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

De Function.apply e Function.call em JavaScript :

O método apply () é idêntico a call (), exceto que apply () requer uma matriz como o segundo parâmetro. A matriz representa os argumentos para o método de destino.

Exemplo de código:

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'
));

Veja também este violino .






dynamic