ECMAScript【js基础】javascript中的apply() call() bind() 方法是javascript专业人员的功底[译]


— Understand JavaScript’s “this” With Ease, and Master It.
— JavaScript Objects
— Understand JavaScript Closures
(This is an intermediate to advanced topic)


  1. 轻松理解javascript的this,并会见使他;
  2. javascript的对象;
  3. 亮javascript中之闭包(closures)

Functions are objects in JavaScript, as you should know by now, if you
have read any of the prerequisite articles. And as objects, functions
have methods, including the powerful Apply, Call, and Bind methods. On
the one hand, Apply and Call are nearly identical and are frequently
used in JavaScript for borrowing methods and for setting the this value
explicitly. We also use Apply for variable-arity functions; you will
learn more about this in a bit.

call()、 以及 bind() 方法。一方面,apply() 和 call()
几乎同样,而且每当javascript中借调方法时和展示的装置 this
的值时是频繁的使用。我们尚用apply()在 variable-arity

On the other hand, we use Bind for setting the this value in methods and
for currying functions.

一边,我们采用bind() 来安 方法里之this 的值 来操作方法。

We will discuss every scenario in which we use these three methods in
JavaScript. While Apply and Call come with ECMAScript 3 (available on IE
6, 7, 8, and modern browsers), ECMAScript 5 (available on only modern
browsers) added the Bind method. These 3 Function methods are workhorses
and sometimes you absolutely need one of them. Let’s begin with the Bind

咱们拿会讨论就三个方式以javascript用到的诸一样种植方案情景。 apply()
、call() 方法从es3虽因故了(在IE 6 7 8


We use the Bind () method primarily to call a function with the this
value set explicitly. It other words, bind () allows us to easily set
which specific object will be bound to this when a function or method is

咱俩以bind()方法要是显现的设置调用函数的this 值,换句话说,

This might seem relatively trivial, but often the this value in methods
and functions must be set explicitly when you need a specific object
bound to the function’s this value.


The need for bind usually occurs when we use the this keyword in a
method and we call that method from a receiver object; in such cases,
sometimes this is not bound to the object that we expect it to be bound
to, resulting in errors in our applications. Don’t worry if you don’t
fully comprehend the preceding sentence. It will become clear like
teardrop in a moment.


Before we look at the code for this section, we should understand the
this keyword in JavaScript. If you don’t already understand this in
JavaScript, read my article, Understand JavaScript’s “this” With
Clarity, and Master It. If you don’t understand this well, you will have
trouble understanding some of the concepts discussed below. In fact,
many of the concepts regarding setting the “this” value that I discuss
in this article I also discussed in the Understand JavaScript’s “this”

于咱们看就无异有的的代码时,我们该清楚 this
你将格外为难了解下面讨论的概念,事实上,这首文章我只要讨论的有关设置 this
值的定义,我就于《Understand JavaScript’s “this”

JavaScript’s Bind Allows Us to Set the this Value on Methods


When the button below is clicked, the text field is populated with a
random name.


//            <button>Get Random Person</button>​
​//        <input type="text">​
​var user = {
        {name:"T. Woods", age:37},
        {name:"P. Mickelson", age:43}
    clickHandler:function (event) {
        var randomNum = ((Math.random () * 2 | 0) + 1) - 1; // random number between 0 and 1​
        // This line is adding a random person from the data array to the text field​
        $ ("input").val ([randomNum].name + " " +[randomNum].age);
​// Assign an eventHandler to the button's click event​
$ ("button").click (user.clickHandler);

When you click the button, you get an error because this in the
clickHandler () method is bound to the button HTML element, since that
is the object that the clickHandler method is executed on.

当你点击按钮时,你会拿走一个左,因为this 在 clickHandler()
方中绑定的是 button 对象 ,button 对象是 clickHandler

This particular problem is quite common in JavaScript, and JavaScript
frameworks like Backbone.js and libraries like jQuery automatically do
the bindings for us, so that this is always bound to the object we
expect it to be bound to.

和 库 像 Jquery 自动吗我们举行绑定,因此 this 总是

To fix the problem in the preceding example, we can use the bind method
Instead of this line:

为化解前例子中之问题,我们得以动用 bind 方法 如下 代替脚这同一尽

 $ ("button").click (user.clickHandler);

We simply have to bind the clickHandler method to the user object like
咱俩无非待 把 clickHandler 方法 绑定到 user 对象及 像这样:

 $ ("button").click (user.clickHandler.bind (user));

Consider this other way to fix the this value: You can pass an anonymous
callback function to the click () method and jQuery will bind this
inside the anonymous function to the button object.
考虑这问题外的方式去化解 this

Because ECMAScript 5 introduced the Bind method, it (Bind) is
unavailable in IE < 9 and Firefox 3.x. Include this Bind
implementation in your code, if you are targeting older browsers:

坐bind() 方法时凡在es5 才提出的,他于IE 9一下与 火狐 3.x

立马段代码挺复杂,是javascript大牛 Douglas写的

       // Credit to Douglas Crockford for this bind method​
            if (!Function.prototype.bind) {
                Function.prototype.bind = function (oThis) {
                    if (typeof this !== "function") {
                        // closest thing possible to the ECMAScript 5 internal IsCallable function​
                        throw new TypeError ("Function.prototype.bind - what is trying to be bound is not callable");
                    var aArgs = (arguments, 1),
                            fToBind = this,
                            fNOP = function () {
                            fBound = function () {
                                return fToBind.apply (this instanceof fNOP && oThis
                                        ? this​
                                        : oThis,
                                        aArgs.concat ( (arguments)));
                    fNOP.prototype = this.prototype;
                    fBound.prototype = new fNOP ();
                    return fBound;

Let’s continue with the same example we used above. The this value is
also bound to another object if we assign the method (where this is
defined) to a variable. This demonstrates:

   // 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 ([randomNum].name + " " +[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)​

When we execute the showDataVar () function, the values printed to the
console are from the global data array, not the data array in the user
object. 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.

showDataVar() 是作为一个大局函数执行之,use对象的函数showDataVar()
里面的this 被绑定到全局作用域上,在浏览器里虽为window 对象。

Again, we can fix this problem by specifically setting the“this” value
with the bind method:


  // 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 () Allows us to Borrow Methods


In JavaScript, we can pass functions around, return them, borrow them,
and the like. And the bind () method makes it super easy to borrow
Here is an example using bind () to borrow a method:
当javascript 中,我们好传递函数,返回函数,借用函数等等。bind()

     // Here we have a cars object that does not have a method to print its data to the console​
            var cars = {
                    {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​

(其实本质上或者显得设置 user 对象里 this 值)

One problem with this example is that we are adding a new method
(showData) on the cars object and we might not want to do that just to
borrow a method because the cars object might already have a property or
method name showData. We don’t want to overwrite it accidentally. As we
will see in our discussion of Apply and Call below, it is best to borrow
a method using either the Apply or Call method.



       var data = [
                {name:"Samantha", age:12},
                {name:"Alexis", age:14}

            var user = {
                    {name:"T. Woods", age:37},
                    {name:"P. Mickelson", age:43}
                showData:function (event) {
                    var randomNum = ((Math.random () * 2 | 0) + 1) - 1; 
                    console.log ([randomNum].name + " " +[randomNum].age);
            // var showDataVar = user.showData;

            // showDataVar (); // Samantha 12 (from the global data array, not from the local data array)​

            var cars = {
                    {name:"Honda Accord", age:14},
                    {name:"Tesla Model S", age:2}

                    console.log("hello guy");


           cars.showData = user.showData.bind(cars);
           cars.showData (); // Honda Accord 14​/Tesla Model S 2

JavaScript’s Bind Allows Us to Curry a Function

企图三:柯里化函数(MDN上称Partial Functions[偏函数])

Function Currying, also known as partial function application, is the
use of a function (that accept one or more arguments) that returns a new
function with some of the arguments already set. The function that is
returned has access to the stored arguments and variables of the outer
function. This sounds way more complex than it actually is, so let’s
函数柯里化,也叫做(partial function

Let’s use the bind () method for currying. First we have a simple greet
() function that accepts 3 parameters:


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

And we use the bind () method to curry (preset one or more of the
parameters) our greet () function. The first argument of the bind ()
method sets the this value, as we discussed earlier:

  // 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."

When we use the bind () method for currying, all the parameters of the
greet () function, except the last (rightmost) argument, are preset. So
it is the rightmost argument that we are changing when we call the new
functions that were curried from the greet () function. Again, I discuss
currying at length in a separate blog post, and you will see how we can
easily create very powerful functions with Currying and Compose, two
Functional JavaScript concepts.


So, with the bind () method, we can explicitly set the this value for
invoking methods on objects, we can borrow
and copy methods, and assign methods to variable to be executed as
functions. And as outlined in the Currying Tip
you can use bind for currying.

JavaScript’s Apply and Call Methods

apply() 和 call()

The Apply and Call methods are two of the most often used Function
methods in JavaScript, and for good reason: they allow us to borrow
functions and set the this value in function invocation. In addition,
the apply function in particular allows us to execute a function with an
array of parameters, such that each parameter is passed to the function
individually when the function executes—great for variadic functions; a
variadic function takes varying number of arguments, not a set number of
arguments as most functions do.

apply() 和call()

  • 于可变换参数函数是生好的;

Set the this value with Apply or Call

作用一:设置this 值

Just as in the bind () example, we can also set the this value when
invoking functions by using the Apply or Call methods. The first
parameter in the call and apply methods set the this value to the object
that the function is invoked upon.

call()方法调用函数时,我们呢足以装 函数惨遭 this 值。调用apply()

Here is a very quick, illustrative example for starters before we get
into more complex usages of Apply and Call:
于我们进去复杂的应用apply 和call之前,这里来一个初步的例证:

// global variable for demonstration
        var avgScore = "global avgScore";

        //global function
        function avg (arrayOfScores) {
            // Add all the scores and return the total
            var sumOfScores = arrayOfScores.reduce (function (prev, cur, index, array) {
                return prev + cur;

            // The "this" keyword here will be bound to the global object, unless we set the "this" with Call or Apply
            this.avgScore = sumOfScores / arrayOfScores.length;

        var gameController = {
            scores  :[20, 34, 55, 46, 77],

        // If we execute the avg function thus, "this" inside the function is bound to the global window object:
        avg (gameController.scores);
        // Proof that the avgScore was set on the global window object
        console.log (window.avgScore); // 46.4
        console.log (gameController.avgScore); // null

        // reset the global avgScore
        avgScore = "global avgScore";
   // To set the "this" value explicitly, so that "this" is bound to the gameController,
        // We use the call () method: (gameController, gameController.scores);

        console.log (window.avgScore); //global avgScore
        console.log (gameController.avgScore); // 46.4

Note that the first argument to call () sets the this value. In the
preceding example, it is set to
the gameController object. The other arguments after the first argument
are passed as parameters to the
avg () function.

注意, (gameController, gameController.scores);
call()的第一单参数是设置 函数 this 值,在上述的例子,this

The apply and call methods are almost identical when setting the this
value except that you pass the function parameters to apply () as an
array, while you have to list the parameters individually to pass them
to the call () method. More on this follows. Meanwhile, the apply ()
method also has another feature that the call () method doesn’t have, as
we will soon see.
apply() 和call() 方法以安 this

Use Call or Apply To Set this in Callback Functions


  // 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 Apply method sets the this value to callbackObj. This allows us to
execute the callback function with the this value set explicitly, so the
parameters passed to the callback function will be set on the clientData

apply()方法设置this 值为callbackObj.这允许我们于调用回调函数时白纸黑字的装置
object对象及。(如果非这样做只话,this 会指向window)

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

The Apply, Call, and Bind methods are all used to set the this value
when invoking a method, and they do it in slightly different ways to
allow use direct control and versatility in our JavaScript code. The
this value in JavaScript is as important as any other part of the
language, and we have the 3 aforementioned methods are the essential
tools to setting and using this effectively and properly.
当调用一个方时,apply() call() bind() 方法都让用来安装 this
this 的中坚工具。

Borrowing Functions with Apply and Call (A Must Know)

意三:用apply()和call() 来借用函数(必须了解)

The most common use for the Apply and Call methods in JavaScript is
probably to borrow functions. We can borrow functions with the Apply and
Call methods just as we did with the bind method, but in a more
versatile manner.
每当javascript中,apply() 和call()
Consider these examples:

Borrowing Array Methods


Arrays come with a number of useful methods for iterating and modifying
arrays, but unfortunately, Objects do not have as many native methods.
Nonetheless, since an Object can be expressed in a manner similar to an
Array (known as an array-like object), and most important, because all
of the Array methods are generic (except toString and toLocaleString),
we can borrow Array methods and use them on objects that are

An array-like object is an object that has its keys defined as
non-negative integers. It is best to specifically add a length property
on the object that has the length of the object, since the a length
property does not exist on objects it does on Arrays.

I should note (for clarity, especially for new JavaScript developers)
that in the following examples, when we call Array.prototype, we are
reaching into the Array object and on its prototype (where all its
methods are defined for inheritance). And it is from there—the
source—that we are borrowing the Array methods. Hence the use of code
like Array.prototype.slice—the slice method that is defined on the Array

  • 源码- 我们借了Array方法。因此用如Array.prototype.slice这样的代码-

Let’s create an array-like object and borrow some array methods to
operate on the our array-like object. Keep in mind the array-like object
is a real object, it is not an array at all:

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

Now, if wish to use any of the common Array methods on our object, we


  // Make a quick copy and save the results in a real array:​
                // First parameter sets the "this" value​
                var newArray = (anArrayLikeObj, 0);
                console.log (newArray); // ["Martin", 78, 67, Array[3]]​
                // Search for "Martin" in the array-like object​
                console.log ( (anArrayLikeObj, "Martin") === -1 ? false : true); // true​
                // Try using an Array method without the call () or apply ()​
                console.log (anArrayLikeObj.indexOf ("Martin") === -1 ? false : true); // Error: Object has no method 'indexOf'​
                // Reverse the object:​
                console.log ( (anArrayLikeObj));
                // {0: Array[3], 1: 67, 2: 78, 3: "Martin", length: 4}​
                // Sweet. We can pop too:​
                console.log ( (anArrayLikeObj));
                console.log (anArrayLikeObj); // {0: Array[3], 1: 67, 2: 78, length: 3}​
                // What about push?​
                console.log ( (anArrayLikeObj, "Jackie"));
                console.log (anArrayLikeObj); // {0: Array[3], 1: 67, 2: 78, 3: "Jackie", length: 4}​

We get all the great benefits of an object and we are still able to use
Array methods on our object, when we setup our object as an array-like
object and borrow the Array methods. All of this is made possible by the
virtue of the call or apply method.

The arguments object that is a property of all JavaScript functions is
an array-like object, and for this reason, one of the most popular uses
of the call () and apply () methods is to extract the parameters passed
into a function from the arguments object.

Here is an example I took from the Ember.js source, with comments I

   function transitionTo (name) {
                    // Because the arguments object is an array-like object​
                    // We can use the slice () Array method on it​
                    // The number "1" parameter means: return a copy of the array from index 1 to the end. Or simply: skip the first item​
                    var args = (arguments, 1);
                    // I added this bit so we can see the args value​
                    console.log (args);
                    // I commented out this last line because it is beyond this example​
                    //doTransition(this, name, this.updateURL, args);​
                // Because the slice method copied from index 1 to the end, the first item "contact" was not returned​
                transitionTo ("contact", "Today", "20"); // ["Today", "20"]​

The args variable is a real array. It has a copy of all the parameters
passed to the transitionTo function.

From this example, we learn that a quick way to get all the arguments
(as an array) passed to a function is to do:

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

We will discuss how to use the apply method with the arguments
array-like object again for variadic functions. More on this later.

Borrowing String Methods with Apply and Call


Like the preceding example, we can also use apply () and call () to
borrow String methods. Since Strings are immutable, only the
non-manipulative arrays work on them, so you cannot use reverse, pop and
the like.
例如上述的事例一样,我们也得以利用apply() 和 call() 方法去借String

Borrow Other Methods and Functions


Since we are borrowing, lets go all in and borrow from our own custom
methods and functions, not just from Array and String:

 var gameController = {
                    scores  :[20, 34, 55, 46, 77],
                    players :[
                        {name:"Tommy", playerID:987, age:23},
                        {name:"Pau", playerID:87, age:33}
                var appController = {
                    scores  :[900, 845, 809, 950],
                    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​

Sure, it is just as easy, even recommended, to borrow our own custom
methods and functions. The gameController object borrows the
appController object’s avg () method. The “this” value defined in the
avg () method will be set to the first parameter—the gameController

You might be wondering what will happen if the original definition of
the method we are borrowing changes. Will the borrowed (copied) method
change as well, or is the copied method a full copy that does not refer
back to the original method? Let’s answer these questions with a quick,
illustrative example:


    appController.maxNum = function () {
            this.avgScore = Math.max.apply (null, this.scores);
        appController.maxNum.apply (gameController, gameController.scores);
        console.log (gameController.avgScore); // 77​

As expected, if we change the original method, the changes are reflected
in the borrowed instances of that method. This is expected for good
reason: we never made a full copy of the method, we simply borrowed it
(referred directly to its current implementation).

Use Apply () to Execute Variable-Arity Functions


To wrap up our discussion on the versatility and usefulness of the
Apply, Call, and Bind methods, we will discuss a neat, little feature of
the Apply method: execute functions with an array of arguments.
为形成我们的有关apply() call() bind() 方法的通用性和实用性

We can pass an array with of arguments to a function and, by virtue of
using the apply () method, the function will execute the
items in the array as if we called the function like this:

createAccount (arrayOfItems[0], arrayOfItems[1], arrayOfItems[2], arrayOfItems[3]);

This technique is especially used for creating variable-arity, also
known as variadic functions.
These are functions that accept any number of arguments instead of a
fixed number of arguments. The arity of a function specifies the number
of arguments the function was defined to accept.

The Math.max() method is an example of a common variable-arity function
in JavaScript:

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

But what if we have an array of numbers to pass to Math.max? We cannot
do this:

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

This is where the apply () method helps us execute variadic functions.
Instead of the above, we have to pass the array of numbers using apply
() thus:

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

As we have learned earlier, the fist argument to apply () sets the
“this” value, but “this” is not used in the Math.max () method, so we
pass null.

Here is an example of our own variadic function to further illustrate
the concept of using the apply () method in
this capacity:



    var students = ["Peter Alexander", "Michael Woodruff", "Judy Archer", "Malcolm Khan"];
    // No specific parameters defined, because ANY number of parameters are accepted​
    function welcomeStudents () {
        var args = (arguments);
        var lastItem = args.pop ();
        console.log ("Welcome " + args.join (", ") + ", and " + lastItem + ".");
    welcomeStudents.apply (null, students);
    // Welcome Peter Alexander, Michael Woodruff, Judy Archer, and Malcolm Khan.

Final Words


The Call, Apply, and Bind methods are indeed workhorses and should be
part of your JavaScript repertoire for setting the this value in
functions, for creating and executing variadic functions, and for
borrowing methods and functions. As a JavaScript developer, you will
likely encounter and use these functions time and again. So be sure you
understand them well.

Be Good. Imagine. Create.