JavaScript call()和apply()与bind()?


794

我已经知道了,apply并且call是类似的函数集this(函数的上下文)。

区别在于我们发送参数的方式(手动vs数组)

题:

但是什么时候应该使用该 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


9
如果有用户在发布答案或投票之前先查看OP的信誉点,这不是您的错:)
Gabriel Llamas

54
调用应用调用函数,而绑定创建函数。虽然与call()您分别传递参数并apply()作为参数数组。有关更多详细信息,请查看链接的文档,该文档应该能够完全回答您的问题。
2013年

3
kind of weird there is not an existing question about this :关于这一点。那可能是因为bind()在JavaScript 1.8.5-ECMA-262,第5版中已经存在另外两个之后添加了。虽然call()apply()自JavaScript的1.3已经出现- ECMA-262第3版。SO对它们有一些疑问,例如:调用和应用之间的差异是什么。我只是在想自己,我只是在猜测。
Nope 2013年

您是否需要这些方法(调用,应用,绑定)在这里?没有这个,您也可以调用该方法,并且该方法将仅指向对象
Mahi 2016年

Answers:


131

我在函数对象,函数调用call/applybind前一阵子之间创建了这种比较:

在此处输入图片说明

.bind允许您现在设置this值,同时允许将来执行函数,因为它返回一个新的函数对象。


779

.bind()当您希望稍后在特定上下文中调用该函数时使用,该事件在事件中很有用。当您想立即调用该函数并修改上下文时,请使用.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中将它广泛用于异步回调,我想为其传递成员方法,但仍希望上下文成为启动异步操作的实例。

一个简单,简单的bind实现是:

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

它还有更多的功能(就像传递其他args一样),但是您可以阅读更多有关它的内容,并查看MDN上的实际实现。

希望这可以帮助。


2
@RoyiNamir是正确的,您可以稍后使用返回的“ bound”函数,并且上下文将得到维护。
乍得

5
这正是bind回报。
乍得

@RoyiNamir编辑了我的答案
乍得

4
您也可以对部分函数使用bind,在调用函数之前传递参数。
Andrew Kirkegaard

1
您只是在重新实现绑定,实际上没有什么区别。不管哪种方式,您都只是将其包装在可以访问保存上下文的范围变量的闭包中。您的代码基本上就是我发布的polyfill。
乍得

446

他们都重视为功能(或对象)不同的是在函数调用(见下文)。

呼叫重视为功能和立即执行的功能:

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"

结合入功能和它需要被这样分开调用:

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"

applycall类似,不同之处在于apply类似于数组,而不是一次列出一个参数:

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"                                     

1
这是否意味着区别是绑定是关闭?
格雷戈里R.16年

您刚刚通过代码片段教会了我有关函数内部使用的参数功能的信息。最好提一下"use strict"以避免覆盖此类保留关键字。+1。
RBT

@Max同意;我提交了一个编辑,其中“ this”是错误的或没有任何意义,直到我们使用bind / call / apply为止
iono 2015年

1
感谢您的改进建议。我编辑了一下答案。@iono您的建议有一些错误,因此无法批准,但在答案中做了我自己的编辑。希望它现在更加全面。
CuriousSuperhero

199

以SIMPLEST形式回答

  • 调用会调用该函数,并允许您一个一个地传递参数。
  • Apply调用该函数,并允许您将参数作为数组传递。
  • Bind返回一个新函数,使您可以传入this数组和任意数量的参数。

应用,调用,绑定示例

呼叫

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

绑定

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,我始终记得是哪个。

绑定有点不同。它返回一个新函数。Call and Apply立即执行当前功能。

绑定在很多方面都很有用。我们可以使用它来管理上面的示例中的函数。我们可以采用一个简单的hello函数并将其转换为helloJon或helloKelly。我们还可以将其用于诸如onClick之类的事件,这些事件我们不知道何时触发,但我们知道我们希望它们具有什么上下文。

参考:codeplanet.io


8
真棒的答案,如果这是我的问题,我给您打勾。
AmerllicA

call和中apply,是否遵循以下方法:如果this方法内部没有,则将第一个参数分配为null??
达里尔·桑托斯

1
@DaryllSantos,根据MDN:thisArg可选。此值提供给函数调用。请注意,这可能不是该方法看到的实际值:如果该方法是非严格模式下的函数,则将null和undefined替换为全局对象,并将原始值转换为对象。因此,如果您不在函数中使用此函数,则没关系。
阿米特·沙阿

4
调用= =逗号,应用==数组是一个不错的记忆技巧
drlff

var person1 = {firstName: 'Jon', lastName: 'Kuperman'}; function say(greeting) { console.log(greeting + ' ' + this.firstName + ' ' + this.lastName); } say.apply(person1, ['Hello']); // Hello Jon Kuperman可以正常工作并输出VM128:4您好Jon Kuperman
Pratik

53

它允许设置值,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);

5
.bind()您之前显示的用法的用法不正确。当您使用fn.bind(obj)其他函数时,将返回(不是您之前创建的)。并且不能更改函数this内部的binded值。通常,这用于回调this保险。但是在您的示例中-结果没有差异。但是fn !== fn.bind(obj);请注意。
ValeriiVasin

@InviS我不理解您的评论-为什么没有区别?
jantimon

2
通话和申请的区别在于。在调用中,您可以将参数作为逗号分隔的字符串传递,而在应用中,您可以以数组形式传递参数。其余的都一样。
Ashish Yadav'2

逗号分隔的字符串?只需 将参数传递为逗号分隔即可
Sudhansu Choudhary19年

46

假设我们有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

如果我在绑定中传递了两个参数怎么办

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创建函数callapply执行函数,而apply期望数组中的参数


很好解释!
CatalinBerta,2013年

3
+1代表“用简单的话说,bind创建函数,call然后apply执行函数,但apply需要数组中的参数”
Josh Buchea

32

双方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

23

bind:它将功能与提供的值和上下文绑定,但不执行该功能。要执行功能,您需要调用该功能。

call:使用提供的上下文和参数执行函数。

apply:以提供的上下文和参数作为数组执行函数 。


简单而谦虚!
Habeeb Perwad

18

这里是一个很好的文章来说明之间的差异bind()apply()并且call(),它总结如下。

  • bind()使我们能够轻松设置在调用函数或方法时将哪个特定对象绑定到此对象。

    // 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() 让我们借用方法

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

    这个示例的一个问题是,我们showDatacars对象上添加了一个新方法,而我们可能不想仅仅借用一个方法,因为cars对象可能已经具有属性或方法名称showData。我们不想意外地覆盖它。正如我们将在我们的讨论中看到ApplyCall下面,最好是借使用A方法ApplyCall方法。

  • bind() 让我们咖喱功能

    函数Currying,也称为部分函数应用程序,是对一个函数(接受一个或多个参数)的使用,该函数返回一个已经设置了一些参数的新函数。

    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()设置

    applycallbind方法都是使用调用方法时设置这个值,他们这样做稍微不同的方式,让我们的JavaScript代码中使用直接控制和多功能性。

    设置this值时,applycall方法几乎相同,除了将函数参数apply ()作为数组传递,而必须单独列出参数以将它们传递给call ()方法。

    下面是一个例子使用callapply设置这个回调函数。

    // 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()执行可变元数函数

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 ()方法帮助我们执行可变函数的地方。代替上面的方法,我们必须使用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

8

调用/应用立即执行功能:

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

绑定不会立即执行功能,而是返回包装的应用功能(以供以后执行):

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

7

句法

  • 调用(thisArg,arg1,arg2,...)
  • 适用(thisArg,argsArray)
  • 绑定(thisArg [,arg1 [,arg2 [,...]]])

这里

  • thisArg是对象
  • argArray是一个数组对象
  • arg1,arg2,arg3,...是附加参数

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


6

调用,应用和绑定之间的基本区别是:

如果您希望执行上下文出现在图片的后面,将使用Bind。

例如:

var car = { 
  registrationNumber: "007",
  brand: "Mercedes",

  displayDetails: function(ownerName){
    console.log(ownerName + ' this is your car ' + '' + this.registrationNumber + " " + this.brand);
  }
}
car.displayDetails('Nishant'); // **Nishant this is your car 007 Mercedes**

假设我想在其他变量中使用此方法

var car1 = car.displayDetails('Nishant');
car1(); // undefined

要在其他变量中使用car的引用,您应该使用

var car1 = car.displayDetails.bind(car, 'Nishant');
car1(); // Nishant this is your car 007 Mercedes

让我们谈谈绑定函数的更广泛使用

var func = function() {
 console.log(this)
}.bind(1);

func();
// Number: 1

为什么?因为现在func与数字1绑定,如果在这种情况下不使用绑定,它将指向全局对象。

var func = function() {
 console.log(this)
}.bind({});

func();
// Object

如果要同时执行该语句,则使用Call,Apply。

var Name = { 
    work: "SSE",
    age: "25"
}

function displayDetails(ownerName) {
    console.log(ownerName + ", this is your name: " + 'age' + this.age + " " + 'work' + this.work);
}
displayDetails.call(Name, 'Nishant')
// Nishant, this is your name: age25 workSSE

In apply we pass the array
displayDetails.call(Name, ['Nishant'])
// Nishant, this is your name: age25 workSSE

4

调用应用并绑定。以及它们有何不同。

让我们使用任何日常术语来学习电话并申请。

您有三辆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");
    }
}

让我们了解何时调用并申请使用。让我们假设您是一名工程师,并且已经拥有your_scooteryour_car并且your_jet没有push_button_engine_start,并且您希望使用第三方push_button_engineStart

如果您运行以下代码行,它们将给出错误。为什么?

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

因此,上面的示例成功地为your_scooter,your_car,your_jet提供了来自汽车对象的功能。

让我们更深入地研究 这里将拆分上面的代码行。 automobile.push_button_engineStart正在帮助我们获得正在使用的方法。

此外,我们使用点符号使用Apply或call。 automobile.push_button_engineStart.apply()

现在应用并调用接受两个参数。

  1. 语境
  2. 论点

因此,这里我们在代码的最后一行中设置了上下文。

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

通话和申请之间的区别仅在于apply接受数组形式的参数,而call则可以接受逗号分隔的参数列表。

什么是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);

还是不满意?

让我们清楚地将其作为泪珠。该实验了。我们将返回调用并应用函数应用程序,并尝试将函数的值存储为引用。

下面的实验失败了,因为调用和应用立即被调用,因此,我们从没有进入将引用存储在变量中的阶段,在该变量中绑定函数会窃取表演

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


3

调用:调用会调用该函数,并允许您一个一个地传递参数

Apply: 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


2

call():- 这里我们单独传递函数参数,而不是以数组格式传递

var obj = {name: "Raushan"};

var greeting = function(a,b,c) {
    return "Welcome "+ this.name + " to "+ a + " " + b + " in " + c;
};

console.log(greeting.call(obj, "USA", "INDIA", "ASIA"));

apply():- 这里我们以数组格式传递函数参数

var obj = {name: "Raushan"};

var cal = function(a,b,c) {
    return this.name +" you got " + a+b+c;
};

var arr =[1,2,3];  // array format for function arguments
console.log(cal.apply(obj, arr)); 

bind():-

       var obj = {name: "Raushan"};

       var cal = function(a,b,c) {
            return this.name +" you got " + a+b+c;
       };

       var calc = cal.bind(obj);
       console.log(calc(2,3,4));

2

JavaScript Call()

const person = {
    name: "Lokamn",
    dob: 12,
    print: function (value,value2) {
        console.log(this.dob+value+value2)
    }
}
const anotherPerson= {
     name: "Pappu",
     dob: 12,
}
 person.print.call(anotherPerson,1,2)

JavaScript apply()

    name: "Lokamn",
    dob: 12,
    print: function (value,value2) {
        console.log(this.dob+value+value2)
    }
}
const anotherPerson= {
     name: "Pappu",
     dob: 12,
}
 person.print.apply(anotherPerson,[1,2])

** call和apply函数是差异调用,采用不同的参数,但应用诸如以下的数组:[1,2,3] **

JavaScript bind()

    name: "Lokamn",
    dob: 12,
    anotherPerson: {
        name: "Pappu",
        dob: 12,
        print2: function () {
            console.log(this)
        }
    }
}

var bindFunction = person.anotherPerson.print2.bind(person)
 bindFunction()

1

想象一下,绑定不可用。您可以轻松地将其构造如下:

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

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

bindHelper(arguments);

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

0

所有这些方法背后的主要概念是函数挖掘

函数借用使我们可以在不同对象上使用一个对象的方法,而不必复制该方法并将其维护在两个单独的位置。这是通过使用来完成的。call()。apply()或。bind(),所有这些都可以在我们借用的方法上显式设置此值

  1. 呼叫立即调用函数,并允许您在参数一一传
  2. Apply立即调用该函数,并允许您将参数作为数组传递。
  3. Bind返回一个新函数,您可以在任何时候通过调用一个函数来调用/调用它。

下面是所有这些方法的示例

let name =  {
    firstname : "Arham",
    lastname : "Chowdhury",
}
printFullName =  function(hometown,company){
    console.log(this.firstname + " " + this.lastname +", " + hometown + ", " + company)
}

呼叫

第一个参数,例如调用方法中的名称始终是(this)变量的引用,而后者将是函数变量

printFullName.call(name,"Mumbai","Taufa");     //Arham Chowdhury, Mumbai, Taufa

应用

apply方法与call方法相同,唯一的区别是,函数参数在Array列表中传递

printFullName.apply(name, ["Mumbai","Taufa"]);     //Arham Chowdhury, Mumbai, Taufa

绑定

bind方法与call相同,不同之处在于,bind返回一个函数,该函数稍后可以通过调用它来使用(不立即调用它)

let printMyNAme = printFullName.bind(name,"Mumbai","Taufa");

printMyNAme();      //Arham Chowdhury, Mumbai, Taufa

printMyNAme()是调用该函数的函数

以下是jsfiddle的链接

https://codepen.io/Arham11/pen/vYNqExp


-1

我认为它们的相同之处是:它们都可以更改函数的this值。它们的区别是:bind函数将返回一个新函数;call和apply方法将立即执行该函数,但是apply可以接受一个数组作为参数,并且将解析该数组分离。而且,bind函数可以是Currying。


-3

当我们想为一个函数分配特定上下文时,应该使用bind函数。

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

在上面的示例中,如果我们调用demo.setValue()函数并直接传递this.getValue函数,则它不会直接调用demo.setValue函数,因为setTimeout中的this引用窗口对象,因此我们需要将演示对象上下文传递给this.getValue使用绑定功能。这意味着我们仅在演示对象的上下文中传递函数,而不能强制调用函数。

希望你能理解。

有关更多信息,请参考 javascript绑定函数详细了解

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.