2011-05-09 16 views
12

Al mirar el código fuente de Rafael o g.raphael u otras bibliotecas que he notado el desarrollador hace algo como esto:¿Por qué invocar "aplicar" en lugar de llamar a la función directamente?

var val = Math.max.apply(Math, data_array); 

¿Por qué no invocar la función directamente, tales como:

var val = Math.max(data_array); 

Gracias.

+0

Ok por lo que veo que Math.max toma dos argumentos por lo mi ejemplo de solo llamar, Math.max (matriz) no funcionaría. Entonces, supongo que la pregunta es ¿cómo es la primera línea de código en mi pregunta invocando "max" en cada elemento del data_array? – codecraig

+2

Javascript '.apply' y' .call' ftw !! – Rudie

Respuesta

11

creo que la explicación de la Mozilla Docs lo describe así:

puede asignar un este objeto diferente cuando se llama a una función existente. este se refiere al objeto actual, el objeto de llamada . Con apply, puede escribir un método una vez y luego heredar en otro objeto, sin tener para reescribir el método para el nuevo objeto .

aplicar es muy similar a llamar, excepto para el tipo de argumentos que admite. Puede usar una matriz de argumentos en su lugar de un conjunto de parámetros con nombre. Con aplicar, puede usar una matriz literal, por ejemplo, fun.apply (esto, [nombre, valor]), o un objeto Array, para ejemplo, fun.apply (esta, nueva Matriz (nombre, valor)).

En cuanto a los parámetros:

thisArg determina el valor de este dentro diversión. Si thisArg es nulo o undefined, este será el objeto global . De lo contrario, este será igual a objeto (thisArg) (que es thisArg si thisArg ya es un objeto, o una cadena , Boolean, o número si thisArg es un valor primitivo de la tipo correspondiente). Por lo tanto, es siempre cierto ese tipo de este == "objeto" cuando se ejecuta la función.

argsArray Una matriz argumento para el objeto, especificando los argumentos con los que diversión debe ser llamado, o nulos o indefinido si no hay argumentos deben ser proporcionado a la función.

Los documentos dan un buen ejemplo de un caso de uso para aplicar.En el ejemplo siguiente, se aplican se utiliza para la cadena de un constructor:

function product(name, value) 
{ 
    this.name = name; 
    if (value >= 1000) 
    this.value = 999; 
    else 
    this.value = value; 
} 

function prod_dept(name, value, dept) 
{ 
    this.dept = dept; 
    product.apply(this, arguments); 
} 
prod_dept.prototype = new product(); 

// since 5 is less than 1000 value is set 
var cheese = new prod_dept("feta", 5, "food"); 

// since 5000 is above 1000, value will be 999 
var car = new prod_dept("honda", 5000, "auto"); 

en cuenta que en el prod_dept constructor, el this suministrado se refiere al objeto prod_dept, y arguments es una matriz de argumentos pasados ​​a la product constructor.

12

Math.max no aceptará una lista por defecto. "aplicar" le permite descomprimir la lista en argumentos para que max funcione correctamente.

2

¿Por qué invocar "aplicar" en lugar de llamar a la función directamente? Vamos a echar un fragmento:

var obj = {a: "apply"}; 
func.call(obj, "parameter"); 
function func(para) { 
    if(this.a === "apply"){ 
     console.log('apply'); 
    } 
} 

Aquí podemos ver que estamos utilizando 'this' (contexto) dentro de una función, Si llamar directamente a un func que no tenemos ningún contexto, de lo que se llevará a window contexto, que Está Mal. Por lo tanto, si usa el contexto dentro de su función, use el método apply.

0

.apply se usa a menudo cuando la intención es invocar una función variadic con una lista de valores de argumento, p.

La función Math.max([value1[,value2, ...]]) devuelve el mayor número de cero o más.

Math.max(10, 20); // 20 
Math.max(-10, -20); // -10 
Math.max(-10, 20); // 20 

El método Math.max() no le permite pasar en una matriz. Si tiene una lista de valores de los cuales necesita obtener la más grande, normalmente debería llamar a esta función usando Function.prototype.apply(), p.

Math.max.apply(null, [10, 20]); // 20 
Math.max.apply(null, [-10, -20]); // -10 
Math.max.apply(null, [-10, 20]); // 20 

Sin embargo, a partir de la especificación de ECMAScript 6 puede utilizar el spread operator:

El operador diferencial permite una expresión que se expandió en lugares en los múltiples argumentos (para llamadas de función) o múltiples elementos (por literales de matriz).

Math.max(...[10, 20]); // 20 
Math.max(...[-10, -20]); // -10 
Math.max(...[-10, 20]); // 20 

Cuando se llama a una función utilizando el operador variadic, incluso se puede añadir valores adicionales, por ejemplo,

Math.max(...[10, 20], 50); // 50 
Math.max(...[-10, -20], 50); // 50 
0

general que usaría apply() y call() ser capaz de establecer el contexto o el objeto al que la función de llamada pertenece. La función se convierte efectivamente en un método de ese objeto/contexto que es útil si necesita acceder a los campos del contexto.

Esta es la forma en Javascript invoca de forma nativa funciones:

  1. hacer una lista de argumentos (argList) fuera de los parámetros 1 hasta el final
  2. El primer parámetro es EsteValor
  3. invocar la función con este conjunto de EsteValor y la argList como su lista de argumentos

Referencia: Understanding JavaScript Function Invocation and "this" por Yehuda Katz

Por lo tanto, cuando se llama a una función directamente, en realidad está pasando implícitamente en un contexto predeterminado a la función.Javascript pasa 'window' o 'undefined' como contexto cuando no se especifica usando call() o apply()

Este answer también da un ejemplo que podría ayudar a comprender el uso de

Cuestiones relacionadas