(контекст функции). apply и call Вопрос: this Но когда я должен использовать метод

Прототип

?

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

некоторое время назад:

позволяет вам установить значение call/apply и bind какое-то время ago:

enter image description here

.bind сейчас this, в то же время позволяя вам выполнить function , когда вы хотите, чтобы эта функция позже вызывалась с определенным контекстом, полезно в событиях. Используйте , если вы хотите немедленно вызвать функцию и изменить контекст. передаст эти значения исходной функции. Любые дополнительные параметры, которые вы позже передадите в связанную функцию, будут переданы после связанных параметров: , потому что он возвращает новый объект функции.

Использование .bind() Call / apply вызывает функцию немедленно, тогда как .call() или .apply() возвращает функцию, которая при последующем выполнении будет иметь правильный контекст, установленный для вызова исходной функции. Таким образом, вы можете поддерживать контекст в асинхронных обратных вызовах и событиях.

Call / apply немедленно вызывает функцию, тогда как bind возвращает функцию, для которой при последующем выполнении будет задан правильный контекст для вызова исходной функции. Таким образом, вы можете поддерживать контекст в асинхронных обратных вызовах и событиях.

Я часто это делаю:

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.
};

Я широко использую его в Node.js для асинхронных обратных вызовов, для которых я хочу передать метод member, но все же хочу, чтобы контекст был экземпляром, который запустил асинхронное действие.

Простая, наивная реализация bind будет выглядеть так:

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

Это еще кое-что (например, передача других аргументов), но вы можете прочитать об этом больше и увидеть реальную реализацию в MDN Глядя на вывод

Надеюсь, это поможет.

Все они присоединяют this В функцию (или объект), и разница заключается в вызове функции (см. Ниже).

вызов , присоединяет this к функции и немедленно выполняет функцию:

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 , присоединяет this в функции, и ее необходимо вызывать отдельно, например:

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"

или следующим образом:

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

, использование похож на вызов , за исключением того, что он принимает объект, похожий на массив, вместо перечисления аргументов по одному:

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"                                     

Ответ в форме SIMPLEST

  • Вызов вызывает функцию и позволяет вам передать аргументы один на один.
  • , использование вызывает функцию и позволяет передавать аргументы в виде массива.
  • bind возвращает новую функцию, позволяющую передать массив athis и любое количество аргументов.

Примеры «Применить против звонка против привязки»

Вы можете передать его, используя внедрение зависимостей Angulars:

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

, использование

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

bind

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

Когда использовать Каждый

вызов и применить довольно взаимозаменяемы. Просто решите, проще ли отправить массив или список аргументов через запятую.

Я всегда помню, какой из них, помня, что Call для запятой (разделенный список) и Apply для Array.

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

Bind отлично подходит для многих вещей. Мы можем использовать его для карри функций, как в примере выше. Мы можем взять простую функцию hello и превратить ее в helloJon или helloKelly. Мы также можем использовать его для таких событий, как onClick, когда мы не знаем, когда они будут запущены, но мы знаем, какой контекст мы хотим, чтобы они имели.

Ссылка: codeplanet.io

Позволяет установить значение для this независимо от того, как вызывается функция. Это очень полезно при работе с обратными вызовами:

  function sayHello(){
    alert(this.message);
  }

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

Чтобы достичь того же результата с call, это будет выглядеть так:

  function sayHello(){
    alert(this.message);
  }

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

Предположим, у нас есть multiplication функция

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

. Давайте создадим некоторые стандартные функции, используя bind

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

Теперь multiby2 (b) равно умножению (2, b) ;

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

Что если я передам оба параметра в bind

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

Теперь getSixAlways () равно умножению (3,2) ;

getSixAlways();//6

даже передаваемый параметр возвращает 6 ; getSixAlways(12); //6

var magicMultiplication = multiplication.bind(this);

Это создает новую функцию умножения и присваивает ее magicMultiplication.

О нет, мы скрываем функциональность умножения в magicMultiplication.

вызов magicMultiplication возвращает пробел function b()

при выполнении он работает нормально magicMultiplication(6,5); //30

Как насчет вызова и подачи заявки?

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

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

Простыми словами, bind создает функцию, call и apply выполняет функцию, тогда как apply ожидает, что параметры в массиве

обоих Function.prototype.call() и Function.prototype.apply() вызывают функцию с данным значением this и возвращают возвращаемое значение этого функция.

Function.prototype.bind(), с другой стороны, создает новую функцию с заданным значением this и возвращает эту функцию без ее выполнения.

Итак, давайте возьмем функцию, которая выглядит следующим образом:

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

Теперь давайте возьмем объект, который выглядит следующим образом:

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

Мы можем привязать нашу функцию к нашему объекту следующим образом:

Obj.log = logProp.bind(Obj);

Теперь мы можем запустить Obj.log где-нибудь в нашем коде:

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

, где это действительно становится интересным, это когда вы не только привязываете значение для this, но также для его аргумента prop, тогда нам нужно привязать контекст к внутренней функции.

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

Теперь мы можем сделать это:

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

bind : он связывает функцию с предоставленным значением и контекстом, но не выполняет функцию. Для выполнения функции необходимо вызвать функцию.

call : выполняет функцию с предоставленным контекстом и параметром.

, использование: Выполняет функцию с предоставленным контекстом и параметром как массив Глядя на вывод

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

  • bind() позволяет нам легко установить, к какому конкретному объекту будет привязан this при вызове функции или метода.

    // 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() Позвольте мне еще раз процитировать проблему, как описано by @Steg

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

    Одна из проблем этого примера в том, что мы добавляем новый метод showData. Если вы хотите, чтобы экземпляры имели свои собственные массивы, создайте их в функции, а не в прототипе. cars Таким образом, приведенный выше пример теперь будет showData. Мы не хотим перезаписывать его случайно. Как мы увидим в нашем обсуждении Apply и Call ниже, лучше всего заимствовать метод, используя либо метод Apply или Call.

  • bind() позволяют нам каррировать функцию

    Функция Curry , также известная как частичное применение функции , представляет собой использование функции (принимающей один или несколько аргументов), которая возвращает новую функцию с некоторые аргументы уже установлены.

    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   ".";
        }
     }
    

    Мы можем использовать bind() для каррирования этой 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() или call() для установки this значения. Все методы

    Переменная apply, call и bind используются для установки значения this при вызове метода, и они делают это слегка различными способами. позволяют использовать прямой контроль и универсальность в нашем коде JavaScript. Методы

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

    Вот один пример использования call или apply для установки this в функции обратного вызова.

    // 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
    
  • функций заимствования с apply или call

    • методами заимствования массива

      Давайте создадим объект array-like и заимствуем некоторые методы массива для работы с нашим массивоподобным объектом.

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

      Еще один распространенный случай — преобразование arguments в массив следующим образом

        // 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"]
      
    • Заимствование других методов

      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​
      
  • Использование apply() для выполнения функции переменной-арности function { *} Разница между вызовом и применением

Переменная Math.max — один из примеров функции переменной-арности, { *} Но что, если у нас есть массив чисел для передачи

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

? Мы не можем сделать это: Math.max Здесь метод

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

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

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

немедленно выполняет функцию: не выполняет функцию немедленно, но возвращает упакованную функцию

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

bind (для последующего выполнения): , использование Call вызывает функцию и позволяет передавать аргументы один за другим.

function bind(func, context) {
    return function() {
        return func.apply(context, arguments);
    };
}
  • Apply вызывает функцию и позволяет передавать аргументы в виде массива.
  • Bind возвращает новую функцию, позволяющую передавать массив this и любое количество аргументов.
  • Звоните, применяйте и связывайте. и как они отличаются.

Позволяет учиться звонить и применять, используя любую ежедневную терминологию.

У вас есть три автомобиля

, которые запускаются с одним и тем же механизмом (методом). Мы создали объект your_scooter , your_car and your_jet с помощью метода automobile. Давайте разберемся, когда вызывается и применяется используется. Предположим, что вы инженер, и у вас есть 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");
    }
}

, который не поставлялся с push_button_engine_start, и вы хотите использовать стороннего разработчика your_scooter, your_car и your_jet Если вы запустите следующие строки кода, они выдадут ошибку. ЗАЧЕМ? push_button_engineStart Глядя на вывод

Таким образом, приведенный выше пример успешно предоставляет your_scooter, your_car, your_jet функцию из автомобильного объекта.

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

Давайте углубимся глубже

Здесь мы разделим вышеприведенную строку кода. помогает нам получить используемый метод. automobile.push_button_engineStart Далее мы используем apply или call, используя точечную запись.

Теперь примените и вызовите принять два параметра. automobile.push_button_engineStart.apply()

Итак, здесь мы устанавливаем контекст в последней строке кода.

  1. context
  2. читаются

Разница между вызовом и применением

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

, что такое функция JS Bind? Оператор

Функция связывания — это, в основном, функция, которая связывает контекст чего-либо, а затем сохраняет его в переменной для выполнения на более позднем этапе.

Давайте сделаем наш предыдущий пример еще лучше. Ранее мы использовали метод, принадлежащий автомобильному объекту, и использовали его для оснащения

. Теперь давайте представим, что мы хотим дать отдельное your_car, your_jet and your_scooter отдельно, чтобы запускать наши автомобили индивидуально на любой последующей стадии исполнения, которую мы желаем. push_button_engineStart все еще не удовлетворен?

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

Давайте проясним это как слезинки. Время экспериментировать. Мы вернемся к вызову и применим функцию application и попытаемся сохранить значение функции в качестве ссылки.

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

вызывает функцию и позволяет передать Аргументы один за другим

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

— это спасение, я подумал с помощью Apply вызывает функцию и позволяет передавать аргументы в виде массива

Применить: Bind:

Bind возвращает новую функцию, позволяющую передавать массив this и любое количество аргументов. Представь, привязка недоступна. Вы можете легко сконструировать его следующим образом:

var person1 = {firstName: 'Raju', lastName: 'king'};
var person2 = {firstName: 'chandu', lastName: 'shekar'};

function greet(greeting) {
    console.log(greeting   ' '   this.firstName   ' '   this.lastName);
}
function greet2(greeting) {
        console.log( 'Hello '   this.firstName   ' '   this.lastName);
    }


greet.call(person1, 'Hello'); // Hello Raju king
greet.call(person2, 'Hello'); // Hello chandu shekar



greet.apply(person1, ['Hello']); // Hello Raju king
greet.apply(person2, ['Hello']); // Hello chandu shekar

var greetRaju = greet2.bind(person1);
var greetChandu = greet2.bind(person2);

greetRaju(); // Hello Raju king
greetChandu(); // Hello chandu shekar
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

Я думаю, что они одинаковы: все они могут изменять значение функции this. Различия между ними: функция bind вернет новую функцию в результате { ***} методы call и apply сразу же выполнят функцию, но apply может принять массив в качестве параметров и проанализировать разделенный массив. А также, функция bind может быть Curry.

var someFunction=...
var objToBind=....

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

bindHelper(arguments);
    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;

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

в приведенном выше примере, если мы вызываем функцию demo.setValue () и передаем функцию this.getValue напрямую, то она не вызывает функцию demo.setValue напрямую, потому что это в setTimeout ссылается на объект окна, поэтому нам нужно передать контекст демо-объекта в Функция this.getValue, использующая связывание. это означает, что мы только передаем функцию с контекстом демонстрационного объекта, а не вызываем функцию.

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

Надеюсь, ты понимаешь.

для получения дополнительной информации, пожалуйста, обратитесь к

javascript bind function know подробно javascript — Какой самый эффективный способ создания HTML-элементов с использованием jQuery? — Переполнение стека