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

原文:javascriptissexy.com/javascript-apply-call-and-bind-methods-are-essential-for-javascript-professionals/#

Prerequisite:
— 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.

(在javascript中,函数也是目标的平栽,如果您念了部分关于javascript的基本功文章,现在公应有懂得,作为靶子,函数有许多法,包括精的apply()、
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
method.

咱们拿会讨论就三个方式以javascript用到的诸一样种植方案情景。 apply()
、call() 方法从es3虽因故了(在IE 6 7 8
和当代浏览器中还灵验),bind()方法是以es5才投入的不二法门(仅仅以现世浏览器中有效),这三独函数方法都是工作马(重要的),有时你必会得(用到)他们之中的他俩一个,让咱们初步攻读bind()
方法吧。

bind()

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
invoked.

咱俩以bind()方法要是显现的设置调用函数的this 值,换句话说,
在一个函数或者措施被调用时,bind()方法允许我们格外轻之
将某个具体的对象绑定到这函数或者措施齐;

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.

这或许看上去比较繁琐,但是若常索要把一个实际的目标绑定到有(调用)函数的this值上,那么这个函数方法中的this
值就不能不显性的装。

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.

当我们在术被行使this关键字时而且我们打一个奉的目标调用方法时,通常会有bind
的要求(应用场景);在这种气象下,有时,我们意在方法中之this绑定到这个目标只是可没有绑定,从而致使我们应用程序的不当。如果您不能够全掌握前面的语句,也不要顾虑。一会儿,他以诸如泪水一样清晰。

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”
article.

于咱们看就无异有的的代码时,我们该清楚 this
关键字,如果你还从未掌握javascript中的this,
请读立刻篇稿子,如果你知道好this,
你将格外为难了解下面讨论的概念,事实上,这首文章我只要讨论的有关设置 this
值的定义,我就于《Understand JavaScript’s “this”
article》这首文章被讨论了了。

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

作用一样:设置方式的this值

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 = {
    data:[
        {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 (this.data[randomNum].name + " " + this.data[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.

这特别的问题在javascript中凡是相当普遍的,在javascript的框架如Backbone.js
和 库 像 Jquery 自动吗我们举行绑定,因此 this 总是
绑定到我们期望绑定的靶子上。

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

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

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

We simply have to bind the clickHandler method to the user object like
this:
咱俩无非待 把 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
值:你可以以一个匿名回调函数传递给click()方法,并且jQuery将这个匿名函数绑定到拖欠按钮对象。

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
版本中凡是未可用之。如果你的靶子是镇的浏览求,在你的代码实现着引入了bind()
方法(你用举行有兼容性处理):

立马段代码挺复杂,是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 = Array.prototype.slice.call (arguments, 1),
                            fToBind = this,
                            fNOP = function () {
                            },
                            fBound = function () {
                                return fToBind.apply (this instanceof fNOP && oThis
                                        ? this​
                                        : oThis,
                                        aArgs.concat (Array.prototype.slice.call (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
值也会见绑定到另外一个目标及。如下所示:

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

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对象中的data数组。这个(现象)之所以有,是盖
showDataVar() 是作为一个大局函数执行之,use对象的函数showDataVar()
里面的this 被绑定到全局作用域上,在浏览器里虽为window 对象。

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

又,我们得以经过动bind()方法专门设置“this”值来解决之题目:

  // 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
methods.
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 = {
                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​

(这里吧应用了闭包。。。)
(其实本质上或者显得设置 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.

以此事例有一个题目:当我们以汽车对象上补偿加一个初的计(showData),我们或未思量竟地遮盖其,因为汽车对象或曾经出一个性或措施名称showData。但是我们用bind()方法就曾盖了cars对象中之showData方法。其实我们一味想借一个艺术无思挂。正而我们在下面的apply()、call()的座谈中以会晤看出,最好使用Apply或Call方法借用一栽办法。

推选个例:

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

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

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


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

                showData:function(){//注意这里,他会被覆盖
                    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
code.
函数柯里化,也叫做(partial function
application)是故一个函数(接受一个或者多独参数),该函数返回一个早就设置的参数的一个初函数。返回的函数可以拜存储的表面函数的参数和变量。这任起比实际更复杂,所以于咱们看代码吧。

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

咱来行使bind()方法进行调用。首先我们出一个简便的greet()函数,它承受3只参数:

  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:
俺们采取bind()方法来柯里化(预设一个要多独参数)我们的greet()函数。bind()方法的首先单参数设置了
this值,如前所述:

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

当我们使用bind()方法开展柯里化时,greet()函数的具有参数除了最后一个(最右边边的)参数之外都于预设。当我们调用一个早已从greet()函数柯里化的新函数时,最右侧边的函数就会见吃安装。再次,我于一个独门的博客文章中长篇大论柯里化,您将看到什么样通过Currying和Compose两单jsvascript函数功能,非常轻松创建强大的函数。

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
earlier,
you can use bind for currying.
汇总,用bind()方法,我们得显式地安装这this值来调用对象的道,我们可以借
暨复制方法,并函数执行时之参数为得以是道。而且只要
前提到的柯里化部分被所陈述,
而可使用bind进行柯里化。

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()
方法以javascript中函数中的使是特别广阔的。有异常好的说辞:他们许我们借函数,并安装函调用数之this值。此外,特别地,apply函数允许我们实行一个参数是多次组的函数,使得当函数执行时,每个参数为单独传递让函数

  • 于可变换参数函数是生好的;
    一个可换函数需要不同数量的参数,而非是比如说大多数函数一样装好参数数量。

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.

尽管如bind()中之例证一样,当我们透过apply()
call()方法调用函数时,我们呢足以装 函数惨遭 this 值。调用apply()
和call()方法被的率先个参数将this值设置为调用该函数的目标。

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],
            avgScore:null
        }

        // 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:
        avg.call (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.

注意, avg.call (gameController, gameController.scores);
call()的第一单参数是设置 函数 this 值,在上述的例子,this
指向gameComtroller对象,另一个参数作为avg()函数的参数。

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
值时几一致。在传递参数方面是不同之,你传递函数的参数为apply()
必须要是数组(后者类数组对象),然而传递参数为call()必须要分头逐个污染。(可以参见js高级程序设计第三版本117p),更多关于这一点。同时,apply()方法还有另外一个特性,即call()方法无,我们迅速就会见见到。

Use Call or Apply To Set this in Callback Functions

意二:在回调函数中安装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 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
object:

apply()方法设置this 值为callbackObj.这允许我们于调用回调函数时白纸黑字的装置
this值。所以传递给回调函数的参数为安装以clientData
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
值应用,并因为略不同之主意允许我们在JavaScript代码直接控制与多用。JavaScript中的
this
值与语言的别任何部分雷同重要,我们发出上述3种办法是立竿见影和科学地设置以及运用
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()
方法极其广大的用处可能是借用函数。我们借函数用apply()
和call()方法就是如我们下bind()
方法一致。但是他们更常用。(透过测试自己意识bind()方法无能够借数组方法
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
array-like.
于迭代和修改数组方面,数组有好多实惠之法。但是不幸的凡,对象没这么多之原生方法。虽然如此,因为对象在得水平上可像数组一样表达。(称为类数组对象),最紧要的是,由于所有数组的办法是通用的(除了toString()
和tlLocaleString()),我们我们可借用数组的章程,用在这些近似数组对象及。

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.
一个类数组对象是一个键定义为非负整数的靶子,他无限好于生长对象及醒目的加以一个length
属性,因为length
属性不存在在Object(原型)对象上,却在以Array(原型)对象上。(留意我们团结一心在结构一个类数组对象时,一定要加length属性,不然会失效

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
prototype.
我们当小心到(为了清晰起见,特别是一个js新手)在下面的例子。当我们调用Array.prototype,我们在触及数组对象和他的原型((其具有术还于定义也继承)。而且是由那里

  • 源码- 我们借了Array方法。因此用如Array.prototype.slice这样的代码-
    其实是以动Array原型上定义的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
can:

现在设我们期待用一个广阔的数组方法在我们的对象及,我好这么做:

  // 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​
​
                // 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 (Array.prototype.reverse.call (anArrayLikeObj));
                // {0: Array[3], 1: 67, 2: 78, 3: "Martin", length: 4}​
​
                // Sweet. We can pop too:​
                console.log (Array.prototype.pop.call (anArrayLikeObj));
                console.log (anArrayLikeObj); // {0: Array[3], 1: 67, 2: 78, length: 3}​
​
                // What about push?​
                console.log (Array.prototype.push.call (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.
咱得到一个靶的保有好处,而且当我们以对象设置为类数组的靶子并借Array方法时,我们照样可以目标及以Array方法。所有这整个都得由此call()或apply()方法的助益来兑现。

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.
arguments
对象是具有javascript函数中之一个性质,他是一个类数组对象,因为这由,call()
和apaly()一个绝受欢迎之用途就是从arguments类数组对象吃领取参数传递给函数。

Here is an example I took from the Ember.js source, with comments I
added:
此出一个例证,我是打Ember.js找来之源码,我加加了诠释:

   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 = Array.prototype.slice.call (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.
args变量是一个真正的数组。它兼具传递给transitionTo函数的保有参数的副本。

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 = Array.prototype.slice.call (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.
稍后,我们将讨论哪些通过arguments类数组对象来利用apply()方法还用于可更换参数函数。

Borrowing String Methods with Apply and Call

用apply()和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
对象的方。因为字符串对象是不足更改的,所以只有非操作数组在它们上行事,所以若无可知应用reverse(),pop()等艺术。

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],
                    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​

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
object.
本,借用我们团结之自定义方法与函数也是死爱的,甚至是引进的。
gameController对象借用appContoller对象的avg()方法,avg()函数里的this值即受定义成调用avg()方法里的首先独参数——gameControlller
对象.

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

用apply()去实践可更换参数函数

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() 方法的通用性和实用性
,我们拿讨论一下apply()方法的一个好简短的利用:执行函数参数是一个数组。

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:
咱得以以一个带有参数为数组的款型传递让一个函数,通过利用apply()方法,该函数将实行数组中之各级一样件,就比如下这样调用函数一样:

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.
这种技术是第一用于创造变量的多寡,也吃喻为可转移参数函数。
只是变换参数函数:接受任何参数个数而无是受一定的参数只数。函数的artity指定函数在概念是承受之参数个数。

The Math.max() method is an example of a common variable-arity function
in JavaScript:
Math.max()方法是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:
只是若我们来一个数组来传递让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

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:
当时是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

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:

如前所述,apply()的率先独参数设置了“this”值,但是以Math.max()方法被无使“this”,所以我们传递null。

这里是咱团结一心之可变函数的一个事例,以更印证在
是容量中采取apply()方法的定义:

    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 = Array.prototype.slice.call (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.

“call()”,“apply()”和“bind()”方法广为使用,并且该是公的JavaScript技能的一致局部,用于在函数中装置this值,用于创造与履可转移参数函数和假方法和函数。作为JavaScript开发人员,您可能会见一如既往赖以同样赖地碰到并以这些函数。所以自然要是好好掌握她们。

另一些参考资料:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind