javascript arrays function

JavaScript de llamada() y apply() vs bind()?



javascript this (16)

Ya sé que apply y call son funciones similares que configuran this (contexto de una función).

La diferencia está en la forma en que enviamos los argumentos (manual vs array)

Pregunta:

Pero, ¿cuándo debo usar el método bind() ?

var obj = { x: 81, getX: function() { return this.x; } }; alert(obj.getX.bind(obj)()); alert(obj.getX.call(obj)); alert(obj.getX.apply(obj));

jsbin


Responda en la forma más simple

  • La llamada invoca la función y le permite pasar los argumentos uno por uno.
  • Aplicar invoca la función y le permite pasar argumentos como una matriz.
  • Bind devuelve una nueva función, lo que le permite pasar a esta matriz y cualquier número de argumentos.

Ejemplos de aplicación frente a llamada frente a enlace

Llamada

var person1 = {firstName: ''Jon'', lastName: ''Kuperman''}; var person2 = {firstName: ''Kelly'', lastName: ''King''}; function say(greeting) { console.log(greeting + '' '' + this.firstName + '' '' + this.lastName); } say.call(person1, ''Hello''); // Hello Jon Kuperman say.call(person2, ''Hello''); // Hello Kelly King

Aplicar

var person1 = {firstName: ''Jon'', lastName: ''Kuperman''}; var person2 = {firstName: ''Kelly'', lastName: ''King''}; function say(greeting) { console.log(greeting + '' '' + this.firstName + '' '' + this.lastName); } say.apply(person1, [''Hello'']); // Hello Jon Kuperman say.apply(person2, [''Hello'']); // Hello Kelly King

Enlazar

var person1 = {firstName: ''Jon'', lastName: ''Kuperman''}; var person2 = {firstName: ''Kelly'', lastName: ''King''}; function say() { console.log(''Hello '' + this.firstName + '' '' + this.lastName); } var sayHelloJon = say.bind(person1); var sayHelloKelly = say.bind(person2); sayHelloJon(); // Hello Jon Kuperman sayHelloKelly(); // Hello Kelly King

Cuándo usar cada

Llamar y solicitar son bastante intercambiables. Simplemente decida si es más fácil enviar una matriz o una lista de argumentos separados por comas.

Siempre recuerdo cuál es cuál al recordar que Llamada es para coma (lista separada) y Aplicar es para Array.

Bind es un poco diferente. Devuelve una nueva función. Llamar y aplicar ejecutan la función actual inmediatamente.

Bind es genial para muchas cosas. Podemos usarlo para curry funciones como en el ejemplo anterior. Podemos tomar una función de saludo simple y convertirla en un saludo o un saludo. También podemos usarlo para eventos como onClick donde no sabemos cuándo serán despedidos, pero sabemos qué contexto queremos que tengan.

codeplanet.io : codeplanet.io


Aquí hay un buen artículo para ilustrar la diferencia entre bind() , apply() y call() , resúmalo de la siguiente manera.

  • bind() nos permite establecer fácilmente qué objeto específico estará vinculado a esto cuando se invoca una función o método.

    // This data variable is a global variable​ var data = [ {name:"Samantha", age:12}, {name:"Alexis", age:14} ] var user = { // local data variable​ data :[ {name:"T. Woods", age:37}, {name:"P. Mickelson", age:43} ], showData:function (event) { var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1​ console.log (this.data[randomNum].name + " " + this.data[randomNum].age); } } // Assign the showData method of the user object to a variable​ var showDataVar = user.showData; showDataVar (); // Samantha 12 (from the global data array, not from the local data array)​ /* This happens because showDataVar () is executed as a global function and use of this inside showDataVar () is bound to the global scope, which is the window object in browsers. */ // Bind the showData method to the user object​ var showDataVar = user.showData.bind (user); // Now the we get the value from the user object because the this keyword is bound to the user object​ showDataVar (); // P. Mickelson 43​

  • bind() nos permite tomar prestados métodos

    // Here we have a cars object that does not have a method to print its data to the console​ var cars = { data:[ {name:"Honda Accord", age:14}, {name:"Tesla Model S", age:2} ] } // We can borrow the showData () method from the user object we defined in the last example.​ // Here we bind the user.showData method to the cars object we just created.​ cars.showData = user.showData.bind (cars); cars.showData (); // Honda Accord 14​

    Un problema con este ejemplo es que estamos agregando un nuevo método showData en el objeto cars y es posible que no queramos hacerlo solo para tomar prestado un método porque el objeto cars ya podría tener una propiedad o nombre de método showData . No queremos sobrescribirlo accidentalmente. Como veremos en nuestra discusión de Apply y Call continuación, es mejor pedir prestado un método utilizando el método Apply o Call .

  • bind() nos permite curry una función

    La función Currying , también conocida como aplicación de función parcial , es el uso de una función (que acepta uno o más argumentos) que devuelve una nueva función con algunos de los argumentos ya establecidos.

    function greet (gender, age, name) { // if a male, use Mr., else use Ms.​ var salutation = gender === "male" ? "Mr. " : "Ms. "; if (age > 25) { return "Hello, " + salutation + name + "."; }else { return "Hey, " + name + "."; } }

    Podemos usar bind() para curry esta función de greet .

    // So we are passing null because we are not using the "this" keyword in our greet function. var greetAnAdultMale = greet.bind (null, "male", 45); greetAnAdultMale ("John Hartlove"); // "Hello, Mr. John Hartlove." var greetAYoungster = greet.bind (null, "", 16); greetAYoungster ("Alex"); // "Hey, Alex."​ greetAYoungster ("Emma Waterloo"); // "Hey, Emma Waterloo."

  • apply() o call() para establecer este valor.

    Los métodos de apply , call y bind se utilizan para establecer este valor cuando se invoca un método, y lo hacen de formas ligeramente diferentes para permitir el control directo y la versatilidad en nuestro código JavaScript.

    Los métodos de apply y call son casi idénticos al configurar este valor, excepto que pasa los parámetros de la función a apply () como una matriz , mientras que tiene que enumerar los parámetros individualmente para pasarlos al método call () .

    Aquí hay un ejemplo para usar call o apply para configurar esto en la función de devolución de llamada.

    // Define an object with some properties and a method​ // We will later pass the method as a callback function to another function​ var clientData = { id: 094545, fullName: "Not Set", // setUserName is a method on the clientData object​ setUserName: function (firstName, lastName) { // this refers to the fullName property in this object​ this.fullName = firstName + " " + lastName; } }; function getUserInput (firstName, lastName, callback, callbackObj) { // The use of the Apply method below will set the "this" value to callbackObj​ callback.apply (callbackObj, [firstName, lastName]); } // The clientData object will be used by the Apply method to set the "this" value​ getUserInput ("Barack", "Obama", clientData.setUserName, clientData); // the fullName property on the clientData was correctly set​ console.log (clientData.fullName); // Barack Obama

  • Funciones de préstamo con apply o call

    • Métodos de la matriz de préstamo

      Vamos a crear un objeto array-like una array-like y tomar prestados algunos métodos de matriz para operar en nuestro objeto similar a una matriz.

      // An array-like object: note the non-negative integers used as keys​ var anArrayLikeObj = {0:"Martin", 1:78, 2:67, 3:["Letta", "Marieta", "Pauline"], length:4 }; // Make a quick copy and save the results in a real array: // First parameter sets the "this" value​ var newArray = Array.prototype.slice.call (anArrayLikeObj, 0); console.log (newArray); // ["Martin", 78, 67, Array[3]]​ // Search for "Martin" in the array-like object​ console.log (Array.prototype.indexOf.call (anArrayLikeObj, "Martin") === -1 ? false : true); // true​

      Otro caso común es que los arguments conversión a la matriz de la siguiente manera

      // We do not define the function with any parameters, yet we can get all the arguments passed to it​ function doSomething () { var args = Array.prototype.slice.call (arguments); console.log (args); } doSomething ("Water", "Salt", "Glue"); // ["Water", "Salt", "Glue"]

    • Pedir prestado otros metodos

      var gameController = { scores :[20, 34, 55, 46, 77], avgScore:null, players :[ {name:"Tommy", playerID:987, age:23}, {name:"Pau", playerID:87, age:33} ] } var appController = { scores :[900, 845, 809, 950], avgScore:null, avg :function () { var sumOfScores = this.scores.reduce (function (prev, cur, index, array) { return prev + cur; }); this.avgScore = sumOfScores / this.scores.length; } } // Note that we are using the apply () method, so the 2nd argument has to be an array​ appController.avg.apply (gameController); console.log (gameController.avgScore); // 46.4​ // appController.avgScore is still null; it was not updated, only gameController.avgScore was updated​ console.log (appController.avgScore); // null​

  • Use apply() para ejecutar la función de aridad variable

El Math.max es un ejemplo de función de variable-aridad,

// We can pass any number of arguments to the Math.max () method​ console.log (Math.max (23, 11, 34, 56)); // 56

¿Pero qué pasa si tenemos una serie de números para pasar a Math.max ? No podemos hacer esto:

var allNumbers = [23, 11, 34, 56]; // We cannot pass an array of numbers to the the Math.max method like this​ console.log (Math.max (allNumbers)); // NaN

Aquí es donde el método apply () nos ayuda a ejecutar funciones variadic . En lugar de lo anterior, tenemos que pasar la matriz de números usando apply ( ), por lo tanto:

var allNumbers = [23, 11, 34, 56]; // Using the apply () method, we can pass the array of numbers: console.log (Math.max.apply (null, allNumbers)); // 56


Creo que los mismos lugares de ellos son: todos ellos pueden cambiar el valor de esta función. Las diferencias entre ellos son: la función de vinculación devolverá una nueva función como resultado; los métodos de llamada y aplicación ejecutarán la función inmediatamente, pero la aplicación puede aceptar una matriz como parámetros, y analizará la matriz separada. Además, la función de vinculación puede ser Currying.


Imagina, el enlace no está disponible. Se puede construir fácilmente de la siguiente manera:

var someFunction=... var objToBind=.... var bindHelper = function (someFunction, objToBind) { return function() { someFunction.apply( objToBind, arguments ); }; } bindHelper(arguments);


Permite establecer el valor para this independientemente de cómo se llame la función. Esto es muy útil cuando se trabaja con devoluciones de llamada:

function sayHello(){ alert(this.message); } var obj = { message : "hello" }; setTimeout(sayHello.bind(obj), 1000);

Para lograr el mismo resultado con call se vería así:

function sayHello(){ alert(this.message); } var obj = { message : "hello" }; setTimeout(function(){sayHello.call(obj)}, 1000);


Supongamos que tenemos función de multiplication

function multiplication(a,b){ console.log(a*b); }

Permite crear algunas funciones estándar usando bind

var multiby2 = multiplication.bind(this,2);

Ahora multiby2 (b) es igual a la multiplicación (2, b);

multiby2(3); //6 multiby2(4); //8

¿Qué pasa si paso ambos parámetros en enlace

var getSixAlways = multiplication.bind(this,3,2);

Ahora getSixAlways () es igual a la multiplicación (3,2);

getSixAlways();//6

incluso pasando el parámetro devuelve 6; getSixAlways(12); //6

var magicMultiplication = multiplication.bind(this);

Esto crea una nueva función de multiplicación y la asigna a magicMultiplication.

Oh no, estamos ocultando la funcionalidad de multiplicación en magicMultiplication.

llamando a magicMultiplication devuelve una function b() blanco function b()

en ejecución funciona bien magicMultiplication(6,5); //30 magicMultiplication(6,5); //30

¿Qué hay de llamar y aplicar?

magicMultiplication.call(this,3,2); //6

magicMultiplication.apply(this,[5,2]); //10

En palabras simples, bind crea la función, call y apply ejecuta la función mientras que apply espera los parámetros en la matriz


Tanto Function.prototype.call() como Function.prototype.apply() llaman a una función con un valor dado y devuelven el valor de retorno de esa función.

Function.prototype.bind() , por otro lado, crea una nueva función con un valor dado y devuelve esa función sin ejecutarla.

Por lo tanto, vamos a tomar una función que se parece a esto:

var logProp = function(prop) { console.log(this[prop]); };

Ahora, tomemos un objeto que se ve así:

var Obj = { x : 5, y : 10 };

Podemos unir nuestra función a nuestro objeto de esta manera:

Obj.log = logProp.bind(Obj);

Ahora, podemos ejecutar Obj.log en cualquier lugar de nuestro código:

Obj.log(''x''); // Output : 5 Obj.log(''y''); // Output : 10

Donde realmente se pone interesante, es cuando no solo vincula un valor para this , sino también para su argumento prop :

Obj.logX = logProp.bind(Obj, ''x''); Obj.logY = logProp.bind(Obj, ''y'');

Ahora podemos hacer esto:

Obj.logX(); // Output : 5 Obj.logY(); // Output : 10


Todos adjuntan esto a la función (u objeto) y la diferencia está en la invocación de la función (ver más abajo).

la llamada adjunta esto a la función y ejecuta la función inmediatamente:

var person = { name: "James Smith", hello: function(thing) { console.log(this.name + " says hello " + thing); } } person.hello("world"); // output: "James Smith says hello world" person.hello.call({ name: "Jim Smith" }, "world"); // output: "Jim Smith says hello world"

bind adjunta esto a la función y debe invocarse por separado de esta manera:

var person = { name: "James Smith", hello: function(thing) { console.log(this.name + " says hello " + thing); } } person.hello("world"); // output: "James Smith says hello world" var helloFunc = person.hello.bind({ name: "Jim Smith" }); helloFunc("world"); // output: Jim Smith says hello world"

o así:

... var helloFunc = person.hello.bind({ name: "Jim Smith" }, "world"); helloFunc(); // output: Jim Smith says hello world"

La aplicación es similar a la llamada, excepto que toma un objeto similar a una matriz en lugar de enumerar los argumentos uno por uno:

function personContainer() { var person = { name: "James Smith", hello: function() { console.log(this.name + " says hello " + arguments[1]); } } person.hello.apply(person, arguments); } personContainer("world", "mars"); // output: "James Smith says hello mars", note: arguments[0] = "world" , arguments[1] = "mars"


Use .bind() cuando desee que esa función se llame más tarde con un contexto determinado, útil en eventos. Utilice .call() o .apply() cuando desee invocar la función inmediatamente, y modifique el contexto.

Llamar / aplicar llamar a la función inmediatamente, mientras que bind devuelve una función que, una vez ejecutada posteriormente, tendrá el contexto correcto configurado para llamar a la función original. De esta manera puede mantener el contexto en devoluciones de llamada asíncronas y eventos.

Lo hago mucho:

function MyObject(element) { this.elm = element; element.addEventListener(''click'', this.onClick.bind(this), false); }; MyObject.prototype.onClick = function(e) { var t=this; //do something with [t]... //without bind the context of this function wouldn''t be a MyObject //instance as you would normally expect. };

Lo uso ampliamente en Node.js para las devoluciones de llamadas asíncronas para las que deseo pasar un método miembro, pero aún quiero que el contexto sea la instancia que inició la acción asíncrona.

Una implementación simple e ingenua de bind sería como:

Function.prototype.bind = function(ctx) { var fn = this; return function() { fn.apply(ctx, arguments); }; };

Hay más en esto (como pasar otros argumentos), pero puede leer más sobre él y ver la implementación real bind .

Espero que esto ayude.


la función de vinculación debe usarse cuando queremos asignar una función con un contexto particular para, por ejemplo,

var demo = { getValue : function(){ console.log(''demo object get value function'') } setValue : function(){ setTimeout(this.getValue.bind(this),1000) } }

en el ejemplo anterior, si llamamos a la función demo.setValue () y pasamos directamente a esta función.getValue, entonces no llamamos directamente a la función demo.setValue porque esto en setTimeout se refiere al objeto de la ventana, por lo que necesitamos pasar el contexto del objeto de demostración a este.getValue función mediante enlace. Significa que solo pasamos la función con el contexto del objeto de demostración que no llama a la función de manera actully.

Espero que entiendas .

para obtener más información, consulte la función de enlace de javascript saber en detalle


La función call / apply ejecuta inmediatamente:

func.call(context, arguments); func.apply(context, [argument1,argument2,..]);

bind no ejecuta la función de forma inmediata, pero devuelve la función de aplicación de reinicio (para una ejecución posterior):

function bind(func, context) { return function() { return func.apply(context, arguments); }; }


Llame a aplicar y enlazar. Y como son diferentes.

Permite aprender llamar y aplicar utilizando cualquier terminología diaria.

Tiene tres automóviles: your_scooter , your_car and your_jet que comienzan con el mismo mecanismo (método). Creamos un objeto automobile con un método push_button_engineStart .

var your_scooter, your_car, your_jet; var automobile = { push_button_engineStart: function (runtime){ console.log(this.name + "''s" + '' engine_started, buckle up for the ride for '' + runtime + " minutes"); } }

Vamos a entender cuándo se usa y se llama. Supongamos que usted es un ingeniero y tiene your_scooter , your_car y your_jet que no vino con un push_button_engine_start y desea utilizar un tercero push_button_engineStart .

Si ejecuta las siguientes líneas de código, darán un error. ¿POR QUÉ?

//your_scooter.push_button_engineStart(); //your_car.push_button_engineStart(); //your_jet.push_button_engineStart(); automobile.push_button_engineStart.apply(your_scooter,[20]); automobile.push_button_engineStart.call(your_jet,10); automobile.push_button_engineStart.call(your_car,40);

Así que el ejemplo anterior es exitoso y le da a su_scooter, su_car, su_jeto una característica del objeto del automóvil.

Vamos a profundizar aquí Aquí dividiremos la línea de código anterior. automobile.push_button_engineStart nos está ayudando a obtener el método que se está utilizando.

Además utilizamos aplicar o llamar usando la notación de puntos. automobile.push_button_engineStart.apply()

Ahora aplique y llame a aceptar dos parámetros.

  1. contexto
  2. argumentos

Así que aquí establecemos el contexto en la última línea de código.

automobile.push_button_engineStart.apply(your_scooter,[20])

La diferencia entre call y apply es que solo se aplican los parámetros aceptables en forma de una matriz, mientras que call simplemente puede aceptar una lista de argumentos separados por comas.

¿Qué es la función JS Bind?

Una función de enlace es básicamente la que enlaza el contexto de algo y luego lo almacena en una variable para su ejecución en una etapa posterior.

Hagamos nuestro ejemplo anterior aún mejor. Anteriormente, utilizamos un método que pertenece al objeto del automóvil y lo usamos para equipar your_car, your_jet and your_scooter . Ahora imaginemos que queremos dar un push_button_engineStart separado para arrancar nuestros automóviles individualmente en cualquier etapa posterior de la ejecución que deseemos.

var scooty_engineStart = automobile.push_button_engineStart.bind(your_scooter); var car_engineStart = automobile.push_button_engineStart.bind(your_car); var jet_engineStart = automobile.push_button_engineStart.bind(your_jet); setTimeout(scooty_engineStart,5000,30); setTimeout(car_engineStart,10000,40); setTimeout(jet_engineStart,15000,5);

todavia no esta satisfecho?

Vamos a dejarlo claro como lágrima. Tiempo para experimentar. Volveremos a llamar y aplicar la aplicación de función e intentaremos almacenar el valor de la función como referencia.

El siguiente experimento falla porque la llamada y la aplicación se invocan de inmediato, por lo tanto, nunca llegamos a la etapa de almacenar una referencia en una variable que es donde la función de vinculación roba el espectáculo.

var test_function = automobile.push_button_engineStart.apply(your_scooter);


bind : Enlaza la función con el valor y el contexto proporcionados, pero no ejecuta la función. Para ejecutar la función necesitas llamar a la función.

llamada : Ejecuta la función con el contexto y parámetro provistos.

apply : Ejecuta la función con el contexto proporcionado y el parámetro como matriz .


function sayHello() { //alert(this.message); return this.message; } var obj = { message: "Hello" }; function x(country) { var z = sayHello.bind(obj); setTimeout(y = function(w) { //''this'' reference not lost return z() + '' '' + country + '' '' + w; }, 1000); return y; } var t = x(''India'')(''World''); document.getElementById("demo").innerHTML = t;


function printBye(message1, message2){ console.log(message1 + " " + this.name + " "+ message2); } var par01 = { name:"John" }; var msgArray = ["Bye", "Never come again..."]; printBye.call(par01, "Bye", "Never come again...");//Bye John Never come again... printBye.call(par01, msgArray);//Bye,Never come again... John undefined //so call() doesn''t work with array and better with comma seperated parameters //printBye.apply(par01, "Bye", "Never come again...");//Error printBye.apply(par01, msgArray);//Bye John Never come again... var func1 = printBye.bind(par01, "Bye", "Never come again..."); func1();//Bye John Never come again... var func2 = printBye.bind(par01, msgArray); func2();//Bye,Never come again... John undefined //so bind() doesn''t work with array and better with comma seperated parameters


  • La llamada invoca la función y le permite pasar los argumentos uno por uno.
  • Aplicar invoca la función y le permite pasar argumentos como una matriz.
  • Bind devuelve una nueva función, lo que le permite pasar a esta matriz y cualquier número de argumentos.