简体   繁体   English

有关prototype.js函数绑定代码的说明

[英]explanation about prototype.js function binding code

From: http://ejohn.org/apps/learn/#2 来自: http : //ejohn.org/apps/learn/#2

Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

Can anyone tell me why the second return is necessary (before fn.apply)? 谁能告诉我为什么必须第二次返回(在fn.apply之前)?

Also, can anyone explain why args.concat is necessary? 另外,谁能解释为什么args.concat是必需的? Why wouldn't it be re-written as: 为什么不将其重写为:

fn.apply(object, args)

instead of 代替

return fn.apply(object,
          args.concat(Array.prototype.slice.call(arguments)));

The second return is necessary because otherwise we will lose any return value from the bound function. 第二次返回是必要的,因为否则我们将失去绑定函数的任何返回值。

You may already know this, but doesn't hurt to mention. 您可能已经知道这一点,但是不必提。 If we don't wrap fn.apply inside another function, then we are directly calling the function fn which is sub-optimal, as bind is only supposed to set the execution context (what should this refer to inside the function), and not invoke it. 如果我们不裹fn.apply另一个函数里面,然后我们直接调用该函数fn这是次优的,因为bind只应该设置执行上下文(又该this是指在函数内部),而不是调用它。

Javascript methods can be invoked by calling the call or apply method on them. 可以通过调用call或对它们apply方法来调用Javascript方法。 Here's a small example: 这是一个小例子:

function example() {
    alert("useless example");
}

example.apply() // or example.call(), alerts "useless example";

The outer function in Prototype's bind() is supposed to work like an invisible wrapper around the bound function. Prototype的bind()中的外部函数应该像绑定函数周围的不可见包装器一样工作。 Thus any arguments that are passed to the wrapper should be passed to the bound function as well, and it must return any value that the bound function returns, which is why the return statement is there. 因此,传递给包装器的所有参数也应传递给绑定函数,并且它必须返回绑定函数返回的任何值,这就是为什么return语句在那里的原因。

The reason for doing args.concat inside fn.apply is different and it's not optional. 在fn.apply中执行args.concat的原因是不同的,并且不是可选的。 bind in Prototype allows you to prepend arguments to the bound function. 原型中的bind允许您在绑定函数之前添加参数。

args represents the arguments that were passed when we called bind on the function. args表示在函数上调用bind时传递的参数。 arguments represents the arguments that were passed when we called the bound function. arguments表示调用绑定函数时传递的参数。 We're basically concatenating two arrays there. 我们基本上是在这里串联两个数组。

From the above example: 从上面的示例:

var obj = { x: 'prop x' };
var boundExample = example.bind(obj, 12, 23); // args => 12, 23
boundExample(36, 49); // arguments => 36, 49

// arguments that our example() function receives => 12, 23, 36, 49

Old post but a newer approach ;) 旧职位,但更新的方法;)

Function.prototype.bind = function(){
    var fn = this, 
    context = arguments[0], 
    args = Array.prototype.slice.call(arguments, 1);
    return function(){
        return fn.apply(context, args.concat([].slice.call(arguments)));
    }
}

obj = {'abc':'x'};
var func = function() {
  console.log(arguments);
  alert(this.abc);
}
var x = func.bind(obj);

console.log(x(1,2,3));

This is a very good example to explain. 这是一个很好的例子。 Run it and check the console log. 运行它并检查控制台日志。 Then modify the code to leave out 然后修改代码以省去

[].slice.call(arguments)

You will see that the console.log of the execution of x(1,2,3) is not showing up the arguments anymore. 您将看到执行x(1,2,3)的console.log不再显示参数了。 This is because the arguments objects is a local variable within all functions. 这是因为arguments对象是所有函数中的局部变量。 That might sound a bit confusing, but what it means is basically: 这听起来可能有点令人困惑,但是这实际上意味着:

var x = func.bind(obj,1,2,3);

Returns this function internally: 内部返回此函数:

function() {
    return fn.apply(obj, [1,2,3].concat([].slice.call(arguments)));
}

So it is more of a template for the function. 因此,它更多是该功能的模板。

When you do now run it like: 现在,请按以下方式运行它:

x(4,5,6)

This will be ran: 这将运行:

fn.apply(obj, [1,2,3].concat([].slice.call(arguments)))

with a special arguments object = {0:4,1:5,2:6} , which can be converted into an array using [].slice.call where arguments is a local object, that is automatically beeing assigned during the invokation of the function. 带有特殊参数object = {0:4,1:5,2:6},可以使用[] .slice.call将其转换为数组,其中arguments是本地对象,在调用时会自动分配给bee功能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM