Cuộc gọi Javascript () & áp dụng () so với ràng buộc ()?


794

Tôi đã biết điều đó applycall là các chức năng tương tự được thiết lập this(bối cảnh của một chức năng).

Sự khác biệt là với cách chúng tôi gửi các đối số (thủ công so với mảng)

Câu hỏi:

Nhưng khi nào nên sử dụng bind()phương pháp này?

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
Đó không phải là lỗi của bạn nếu có người dùng nhìn vào điểm danh tiếng của OP trước khi đăng câu trả lời hoặc nâng cấp :)
Gabriel Llamas

54
gọi áp dụng gọi một chức năng trong khi liên kết tạo ra một chức năng. Mặc dù vớicall()bạn vượt qua các đối số riêng lẻ vàapply()như là một mảng đối số. Để biết thêm chi tiết, hãy kiểm tra tài liệu được liên kết để có thể trả lời hoàn toàn câu hỏi của bạn.
Không,

3
kind of weird there is not an existing question about this :Liên quan đến. Đó có lẽ là vì bind()đã được thêm vào sau khi hai cái kia đã tồn tại trong JavaScript 1.8.5 - ECMA-262, phiên bản thứ 5. Trong khi call()apply()đã xuất hiện kể từ JavaScript 1.3 - ECMA-262 Phiên bản thứ 3. SO có những câu hỏi về chúng như: cái gì là khác biệt giữa cuộc gọi và ứng dụng . Tôi chỉ đoán mặc dù tôi đã tự hỏi rằng.
Không

Bạn có cần các phương thức này (gọi, áp dụng, liên kết) ở đây không ?? không có cái này bạn cũng có thể gọi phương thức và nó sẽ chỉ vào đối tượng
Mahi

Câu trả lời:


131

Tôi đã tạo ra sự so sánh này giữa các đối tượng hàm, các hàm gọi call/applybindmột lúc trước:

nhập mô tả hình ảnh ở đây

.bindcho phép bạn đặt thisgiá trị ngay bây giờ trong khi cho phép bạn thực thi hàm trong tương lai , vì nó trả về một đối tượng hàm mới.


779

Sử dụng .bind()khi bạn muốn chức năng đó sau này được gọi với một ngữ cảnh nhất định, hữu ích trong các sự kiện. Sử dụng .call()hoặc .apply()khi bạn muốn gọi hàm ngay lập tức và sửa đổi bối cảnh.

Gọi / áp dụng gọi hàm ngay lập tức, trong khi bindtrả về một hàm, khi được thực hiện sau đó, sẽ có bối cảnh chính xác để gọi hàm gốc. Bằng cách này, bạn có thể duy trì ngữ cảnh trong các cuộc gọi lại và sự kiện không đồng bộ.

Tôi làm điều này rất nhiều:

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

Tôi sử dụng nó rộng rãi trong Node.js cho các cuộc gọi lại async mà tôi muốn truyền một phương thức thành viên cho, nhưng vẫn muốn bối cảnh là ví dụ bắt đầu hành động async.

Việc thực hiện ràng buộc đơn giản, ngây thơ sẽ như sau:

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

Có nhiều thứ hơn (như vượt qua các đối số khác), nhưng bạn có thể đọc thêm về nó và xem triển khai thực sự trên MDN .

Hi vọng điêu nay co ich.


2
@RoyiNamir là chính xác, bạn có thể sử dụng chức năng "ràng buộc" được trả lại sau và bối cảnh sẽ được duy trì.
Chad

5
Đó là chính xác những gì bindtrở lại.
Chad

@RoyiNamir Chỉnh sửa câu trả lời của tôi
Chad

4
Bạn cũng có thể sử dụng liên kết cho các phần, chuyển qua các đối số trước khi hàm được gọi.
Andrew Kirkegaard 16/03/13

1
Bạn chỉ đang thực hiện lại ràng buộc, thực sự không có sự khác biệt. Dù bằng cách nào, bạn chỉ gói nó trong một bao đóng có quyền truy cập vào một biến phạm vi chứa bối cảnh. Mã của bạn về cơ bản là polyfill tôi đã đăng.
Chad

446

Tất cả đều gắn cái này vào hàm (hoặc đối tượng) và sự khác biệt nằm ở lời gọi hàm (xem bên dưới).

cuộc gọi gắn cái này vào chức năng và thực thi chức năng ngay lập tức:

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"

liên kết gắn cái này vào chức năng và nó cần được gọi riêng như thế này:

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"

hoặc như thế này:

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

áp dụng tương tự như gọi ngoại trừ việc nó lấy một đối tượng giống như mảng thay vì liệt kê từng đối số một:

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
Điều này có nghĩa là sự khác biệt là Bind là một đóng cửa?
Gregory R.

Bạn vừa dạy tôi về tính năng đối số được sử dụng bên trong một hàm thông qua đoạn mã của bạn. Đó là khuyến khích để đề cập "use strict"để tránh ghi đè các từ khóa dành riêng như vậy. +1.
RBT

@Max đồng ý; Tôi đã gửi một bản chỉnh sửa trong đó "điều này" là sai hoặc không có ý nghĩa gì cho đến khi chúng tôi sử dụng liên kết / cuộc gọi / áp dụng
iono

1
Cảm ơn các đề xuất cải tiến. Tôi chỉnh sửa câu trả lời của tôi một chút. @iono Đề xuất của bạn có một số điểm không chính xác vì vậy không thể chấp nhận nó, nhưng đã thực hiện các chỉnh sửa của riêng tôi trong câu trả lời. Hy vọng nó bây giờ toàn diện hơn.
CuriousSuperhero

200

Trả lời dưới dạng SIMPLEST

  • Gọi gọi hàm và cho phép bạn chuyển từng đối số một.
  • Áp dụng gọi hàm và cho phép bạn truyền vào các đối số dưới dạng một mảng.
  • Bind trả về một hàm mới, cho phép bạn truyền vào một mảng này và bất kỳ số lượng đối số nào.

Ví dụ áp dụng so với cuộc gọi so với Bind

Gọi

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

Ứng dụng

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

Trói buộc

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

Khi nào nên sử dụng mỗi

Gọi và áp dụng là khá hoán đổi cho nhau. Chỉ cần quyết định xem việc gửi một mảng hoặc danh sách các đối số được phân tách bằng dấu phẩy sẽ dễ dàng hơn.

Tôi luôn nhớ cái nào là bằng cách nhớ rằng Cuộc gọi dành cho dấu phẩy (danh sách được tách riêng) và Áp dụng là cho Mảng.

Bind là một chút khác nhau. Nó trả về một chức năng mới. Gọi và Áp dụng thực hiện chức năng hiện tại ngay lập tức.

Bind là tuyệt vời cho rất nhiều thứ. Chúng ta có thể sử dụng nó để các hàm cà ri như trong ví dụ trên. Chúng ta có thể thực hiện một chức năng hello đơn giản và biến nó thành helloJon hoặc helloKelly. Chúng tôi cũng có thể sử dụng nó cho các sự kiện như onClick nơi chúng tôi không biết khi nào họ sẽ bị sa thải nhưng chúng tôi biết chúng tôi muốn họ có bối cảnh nào.

Tham khảo: codeplanet.io


8
Câu trả lời tuyệt vời, nếu đó là bài đăng câu hỏi của tôi, tôi cho BẠN đánh dấu.
AmerllicA

Trong callapply, liệu nó có tuân theo rằng nếu bạn không có thisphương thức bên trong, thì bạn sẽ gán đối số đầu tiên là một null?
Daryll Santos

1
@DaryllSantos, Theo MDN: thisArg Tùy chọn. Giá trị này được cung cấp cho lệnh gọi hàm. Lưu ý rằng đây có thể không phải là giá trị thực mà phương thức nhìn thấy: nếu phương thức là một hàm trong chế độ không nghiêm ngặt, null và không xác định sẽ được thay thế bằng đối tượng toàn cục và các giá trị nguyên thủy sẽ được chuyển đổi thành các đối tượng. Vì vậy, nếu bạn không sử dụng chức năng này trong chức năng thì nó không thành vấn đề.
Amit Shah

4
gọi = = dấu phẩy, áp dụng == mảng là một mẹo ghi nhớ nhỏ rất hay
drlff

var person1 = {firstName: 'Jon', lastName: 'Kuperman'}; function say(greeting) { console.log(greeting + ' ' + this.firstName + ' ' + this.lastName); } say.apply(person1, ['Hello']); // Hello Jon KupermanHoạt động hoàn toàn tốt và xuất ra VM128: 4 Xin chào Jon Kuperman
Pratik

53

Nó cho phép đặt giá trị thisđộc lập với cách gọi hàm. Điều này rất hữu ích khi làm việc với các cuộc gọi lại:

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

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

Để đạt được kết quả tương tự với callsẽ như thế này:

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

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

5
Cách sử dụng .bind()như bạn đã trình bày trước đây là không chính xác. Khi bạn sử dụng fn.bind(obj)chức năng khác sẽ được trả lại (không phải là bạn đã tạo trước đó). Và không có khả năng thay đổi giá trị thisbên trong của bindedchức năng. Chủ yếu là điều này được sử dụng cho thisbảo hiểm gọi lại . Nhưng trong ví dụ của bạn - không có sự khác biệt trong kết quả. Nhưng hãy fn !== fn.bind(obj);chú ý rằng.
ValeriiVasin

@InviS Tôi không hiểu bình luận của bạn - tại sao không có gì khác biệt?
jantimon

2
Sự khác biệt trong cuộc gọi và áp dụng là. trong cuộc gọi, bạn truyền các đối số dưới dạng các chuỗi được phân tách bằng dấu phẩy, trong khi áp dụng, bạn có thể truyền các đối số dưới dạng mảng. phần còn lại là như nhau.
Ashish Yadav

dấu phẩy tách chuỗi ?? chỉ cần vượt qua các đối số như dấu phẩy được phân tách !!
Sudhansu Choudhary

46

Giả sử chúng ta có multiplicationchức năng

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

Cho phép tạo một số chức năng tiêu chuẩn bằng cách sử dụng bind

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

Bây giờ multiby2 (b) bằng phép nhân (2, b);

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

Điều gì xảy ra nếu tôi vượt qua cả hai tham số trong liên kết

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

Bây giờ getSixAlways () bằng phép nhân (3,2);

getSixAlways();//6

thậm chí truyền tham số trả về 6; getSixAlways(12); //6

var magicMultiplication = multiplication.bind(this);

Điều này tạo ra một hàm nhân mới và gán nó cho magicMultiplication.

Ồ không, chúng tôi đang ẩn chức năng nhân lên thành MagicMultiplication.

gọi magicMultiplicationtrả lại một khoảng trốngfunction b()

khi thực hiện nó hoạt động tốt magicMultiplication(6,5); //30

Làm thế nào về cuộc gọi và áp dụng?

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

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

Nói một cách đơn giản, bindtạo hàm callapplythực thi hàm trong khi applymong đợi các tham số trong mảng


Giải thích rất tốt!
CatalinBerta

3
+1 cho "Nói một cách đơn giản, bindtạo hàm callapplythực thi hàm trong khi applymong đợi các tham số trong mảng"
Josh Buchea

32

Cả hai Function.prototype.call()Function.prototype.apply()gọi một hàm với một thisgiá trị đã cho và trả về giá trị trả về của hàm đó.

Function.prototype.bind()mặt khác, tạo ra một hàm mới với một thisgiá trị nhất định và trả về hàm đó mà không thực hiện nó.

Vì vậy, hãy thực hiện một chức năng trông như thế này:

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

Bây giờ, hãy lấy một đối tượng trông như thế này:

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

Chúng ta có thể liên kết chức năng của mình với đối tượng như thế này:

Obj.log = logProp.bind(Obj);

Bây giờ, chúng tôi có thể chạy Obj.logbất cứ nơi nào trong mã của chúng tôi:

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

Nơi nó thực sự trở nên thú vị, là khi bạn không chỉ ràng buộc một giá trị cho this, mà còn cho đối số của nó prop:

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

Bây giờ chúng ta có thể làm điều này:

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

23

bind : Nó liên kết hàm với giá trị được cung cấp và bối cảnh nhưng nó không thực thi hàm. Để thực thi chức năng bạn cần gọi hàm.

gọi : Nó thực thi chức năng với bối cảnh và tham số được cung cấp.

áp dụng : Nó thực thi hàm với bối cảnh và tham số được cung cấp dưới dạng mảng .


đơn giản và khiêm tốn!
Habeeb Perwad

18

Đây là một bài viết hay để minh họa sự khác biệt giữa bind(), apply()call(), tóm tắt nó như dưới đây.

  • bind()cho phép chúng ta dễ dàng thiết lập đối tượng cụ thể nào sẽ bị ràng buộc với điều này khi một hàm hoặc phương thức được gọi.

    // 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() cho phép chúng tôi mượn phương thức

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

    Một vấn đề với ví dụ này là chúng tôi đang thêm một phương thức mới showDatavào carsđối tượng và chúng tôi có thể không muốn làm điều đó chỉ để mượn một phương thức vì đối tượng ô tô có thể đã có tên thuộc tính hoặc phương thức showData. Chúng tôi không muốn ghi đè lên nó một cách tình cờ. Như chúng ta sẽ thấy trong cuộc thảo luận của chúng tôi về ApplyCallbên dưới, tốt nhất là mượn một phương thức bằng cách sử dụng Applyhoặc Callphương thức.

  • bind() cho phép chúng ta cà ri một chức năng

    Hàm Currying , còn được gọi là ứng dụng hàm một phần , là việc sử dụng hàm (chấp nhận một hoặc nhiều đối số) trả về một hàm mới với một số đối số đã được đặt.

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

    Chúng ta có thể sử dụng bind()để cà ri greetchức năng này

    // 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()hoặc call()để đặt giá trị này

    Các apply, callbind các phương thức đều được sử dụng để đặt giá trị này khi gọi một phương thức và chúng thực hiện theo các cách hơi khác nhau để cho phép sử dụng kiểm soát trực tiếp và tính linh hoạt trong mã JavaScript của chúng tôi.

    Các phương thức applycallgần như giống hệt nhau khi đặt giá trị này ngoại trừ việc bạn chuyển các tham số hàm apply ()thành một mảng , trong khi bạn phải liệt kê các tham số riêng lẻ để truyền chúng cho call ()phương thức.

    Dưới đây là một ví dụ để sử dụng callhoặc applyđặt điều này trong chức năng gọi lại.

    // 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
  • Hàm mượn với applyhoặccall

    • Phương thức vay mượn

      Hãy tạo một array-likeđối tượng và mượn một số phương thức mảng để hoạt động trên đối tượng giống như mảng của chúng ta.

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

      Một trường hợp phổ biến khác là chuyển đổi argumentssang mảng như sau

        // 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"]
    • Mượn phương thức khác

      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​
  • Sử dụng apply()để thực thi chức năng biến thiên

Đây Math.maxlà một ví dụ về hàm arity biến,

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

Nhưng nếu chúng ta có một dãy số để chuyển đến Math.maxthì sao? Chúng ta không thể làm điều này:

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

Đây là nơi apply ()phương thức giúp chúng ta thực thi các hàm matrixdic . Thay vì ở trên, chúng ta phải truyền mảng số bằng cách sử dụng apply (), do đó:

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

gọi / áp dụng chức năng thực thi ngay lập tức:

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

liên kết không thực thi chức năng ngay lập tức, nhưng trả về hàm áp dụng được bao bọc (để thực hiện sau):

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

7

Cú pháp

  • gọi (thisArg, arg1, arg2, ...)
  • áp dụng (thisArg, argsArray)
  • liên kết (thisArg [, arg1 [, arg2 [, ...]]])

Đây

  • thisArg là đối tượng
  • argArray là một đối tượng mảng
  • arg1, arg2, arg3, ... là các đối số bổ sung

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

Sự khác biệt cơ bản giữa Gọi, Áp dụng và Ràng buộc là:

Bind sẽ được sử dụng nếu bạn muốn bối cảnh thực hiện của bạn đến sau trong hình.

Ví dụ:

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

Giả sử tôi muốn sử dụng phương pháp này trong một số biến khác

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

Để sử dụng tham chiếu của xe trong một số biến khác, bạn nên sử dụng

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

Hãy nói về việc sử dụng rộng rãi hơn của chức năng liên kết

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

func();
// Number: 1

Tại sao? Bởi vì bây giờ func được liên kết với Số 1, nếu chúng ta không sử dụng liên kết trong trường hợp đó, nó sẽ trỏ đến Đối tượng Toàn cầu.

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

func();
// Object

Gọi, Áp dụng được sử dụng khi bạn muốn thực thi câu lệnh cùng một lúc.

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

Gọi áp dụng và ràng buộc. và chúng khác nhau như thế nào

Hãy học gọi và áp dụng bất kỳ thuật ngữ hàng ngày.

Bạn có ba chiếc ô tô your_scooter , your_car and your_jetbắt đầu với cùng một cơ chế (phương pháp). Chúng tôi tạo ra một đối tượng automobilevới một phương thức 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");
    }
}

Hãy hiểu khi nào cuộc gọi và áp dụng được sử dụng. Giả sử rằng bạn là một kỹ sư và bạn có your_scooter, your_caryour_jetđiều đó không đi kèm với Push_button_engine_start và bạn muốn sử dụng bên thứ ba push_button_engineStart.

Nếu bạn chạy các dòng mã sau, chúng sẽ báo lỗi. TẠI SAO?

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

Vì vậy, ví dụ trên là thành công mang lại cho your_scooter, your_car, your_jet một tính năng từ đối tượng ô tô.

Chúng ta hãy đi sâu hơn Ở đây chúng ta sẽ phân chia dòng mã trên. automobile.push_button_engineStartđang giúp chúng tôi có được phương pháp đang được sử dụng.

Hơn nữa chúng tôi sử dụng áp dụng hoặc gọi bằng cách sử dụng ký hiệu chấm. automobile.push_button_engineStart.apply()

Bây giờ áp dụng và gọi chấp nhận hai tham số.

  1. bối cảnh
  2. tranh luận

Vì vậy, ở đây chúng tôi đặt bối cảnh trong dòng mã cuối cùng.

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

Sự khác biệt giữa cuộc gọi và ứng dụng chỉ là việc áp dụng chấp nhận các tham số ở dạng mảng trong khi cuộc gọi đơn giản có thể chấp nhận một danh sách các đối số được phân tách bằng dấu phẩy.

Hàm Bind của JS là gì?

Một hàm liên kết về cơ bản là liên kết bối cảnh của một cái gì đó và sau đó lưu nó vào một biến để thực hiện ở giai đoạn sau.

Hãy làm cho ví dụ trước của chúng tôi thậm chí tốt hơn. Trước đó chúng tôi đã sử dụng một phương pháp thuộc về đối tượng ô tô và sử dụng nó để trang bị your_car, your_jet and your_scooter. Bây giờ hãy tưởng tượng chúng tôi muốn cung cấp một cách riêng push_button_engineStartbiệt để khởi động ô tô riêng của chúng tôi ở bất kỳ giai đoạn nào sau này của việc thực hiện mà chúng tôi muốn.

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

vẫn chưa hài lòng?

Hãy làm cho nó rõ ràng như giọt nước mắt. Thời gian để thử nghiệm. Chúng tôi sẽ quay lại để gọi và áp dụng ứng dụng chức năng và thử lưu trữ giá trị của hàm làm tham chiếu.

Thử nghiệm bên dưới thất bại vì cuộc gọi và ứng dụng được gọi ngay lập tức, do đó, chúng tôi không bao giờ đến giai đoạn lưu trữ một tham chiếu trong một biến trong đó chức năng liên kết ăn cắp chương trình

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


3

Call: call gọi hàm và cho phép bạn truyền từng đối số một

Áp dụng: Áp dụng gọi hàm và cho phép bạn truyền đối số dưới dạng một mảng

Bind: Bind trả về một hàm mới, cho phép bạn truyền vào một mảng này và bất kỳ số lượng đối số nào.

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

gọi (): - Ở đây chúng ta chuyển các đối số hàm riêng lẻ, không phải ở định dạng mảng

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

áp dụng (): - Ở đây chúng ta chuyển các đối số hàm theo định dạng mảng

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

trói buộc() :--

       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

Cuộc gọi JavaScript ()

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)

Áp dụng JavaScript ()

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

** chức năng gọi và áp dụng là cuộc gọi khác nhau, lấy đối số riêng biệt nhưng áp dụng mảng như: [1,2,3] **

Liên kết JavaScript ()

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

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

1

Hãy tưởng tượng, ràng buộc là không có sẵn. bạn có thể dễ dàng xây dựng nó như sau:

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

Khái niệm chính đằng sau tất cả các phương thức này là Hàm burrowing .

Chức năng mượn cho phép chúng ta sử dụng các phương thức của một đối tượng trên một đối tượng khác nhau mà không phải tạo một bản sao của phương thức đó và duy trì nó ở hai nơi riêng biệt. Nó được thực hiện thông qua việc sử dụng. gọi() , . áp dụng (), hoặc. bind (), tất cả đều tồn tại để đặt rõ ràng điều này trên phương thức chúng ta đang mượn

  1. Gọi gọi hàm ngay lập tức và cho phép bạn chuyển từng đối số một
  2. Áp dụng gọi hàm ngay lập tức và cho phép bạn truyền vào các đối số dưới dạng một mảng .
  3. Bind trả về một hàm mới và bạn có thể gọi / gọi nó bất cứ lúc nào bạn muốn bằng cách gọi một hàm.

Dưới đây là một ví dụ về tất cả các phương pháp này

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

GỌI

đối số đầu tiên, ví dụ như tên bên trong phương thức gọi luôn là tham chiếu đến biến (this) và sau này sẽ là biến hàm

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

ỨNG DỤNG

Phương thức áp dụng giống như phương thức gọi, khác biệt duy nhất là, các đối số hàm được truyền trong danh sách Mảng

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

TRÓI BUỘC

phương thức liên kết giống như cuộc gọi ngoại trừ điều đó, liên kết trả về một hàm có thể được sử dụng sau này bằng cách gọi nó (không gọi nó ngay lập tức)

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

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

printMyNAme () là hàm gọi hàm

dưới đây là liên kết cho jsfiddle

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


-1

Tôi nghĩ rằng cùng một vị trí của chúng là: tất cả chúng có thể thay đổi giá trị này của hàm. Sự khác biệt của chúng là: hàm liên kết sẽ trả về một hàm mới như là kết quả; các phương thức gọi và áp dụng sẽ thực thi chức năng ngay lập tức, nhưng áp dụng có thể chấp nhận một mảng dưới dạng params và nó sẽ phân tích mảng được phân tách. Ngoài ra, hàm liên kết có thể là Currying.


-3

chức năng liên kết nên được sử dụng khi chúng ta muốn gán một hàm với ngữ cảnh cụ thể, ví dụ.

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

trong ví dụ trên nếu chúng ta gọi hàm demo.setValue () và truyền trực tiếp hàm this.getValue thì nó không gọi hàm demo.setValue trực tiếp vì điều này trong setTimeout đề cập đến đối tượng cửa sổ nên chúng ta cần truyền ngữ cảnh đối tượng demo cho this.getValue chức năng sử dụng liên kết. nó có nghĩa là chúng ta chỉ truyền hàm với ngữ cảnh của đối tượng demo chứ không thực hiện chức năng gọi.

Hy vọng u hiểu .

để biết thêm thông tin xin vui lòng tham khảo chức năng liên kết javascript biết chi tiết

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.