Javascript 函数调用和绑定

Javascript function invocation & binding

我有以下部分代码:

var person = {
  name: "Brendan Eich",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

var bind = function(func, thisValue) {
  return function() {
    return func.apply(thisValue, arguments);
  }
}

var boundHello = bind(person.hello, person);
boundHello("world") // "Brendan Eich says hello world"

这里,代码会在控制台打印出文本

Brendan Eich says hello world

如果我采用绑定变量赋值并将其更改为:

var person = {
  name: "Brendan Eich",
  hello: function(thing) {
    console.log(this.name + " says hello " + thing);
  }
}

var bind = function(func, thisValue) {
  return func.apply(thisValue, arguments);
}

var boundHello = bind(person.hello, person);
boundHello("world") // "Brendan Eich says hello world"

那么结果就是

Brendan Eich says hello function(thing) { console.log(this.name + " says hello " + thing); }

谁能解释一下为什么会这样,以及 return 中的两个嵌套 return 函数到底是什么? ?

它们究竟是如何工作的?

在您的第二个版本中,您在调用 bind() 时调用了 func,并且 return 调用了函数调用的值。

它正在打印 hello 函数的源代码,因为 arguments 是类数组对象 [person.hello, person],所以您实际上是在调用 person.hello(person.hello, person),并将 thing 设置为 person.hello,并将函数转换为字符串以连接 return 其源代码。

要绑定函数,您必须 return 一个可以稍后调用的闭包。这是在您的第一个版本中通过 return 匿名函数完成的。

我会尽力解释。在第一个例子中,你的 bind 定义是一个有两个参数的 function,理想情况下是 function 作为 first argument (让我们称之为 THE_FUNC) 和一个 object 作为 第二个参数 (让我们称之为 THE_THIS_ARG) 将用作该函数的 thisArgs

现在,这个 bind 定义 return 是一个 function 明确地不接受任何参数(但隐含地可以接受 任何参数 )并且当调用此函数它将 return 使用 THE_THIS_ARG[=94 在 THE_FUNC 上调用 apply 的评估=] 作为 THE_FUNCthis 的值,并使用收到的 arguments (我们称之为 THE_ARGS ) 作为传递给 THE_FUNC.

的参数

对于您的特定示例,设置将是这个:

THE_FUNC => person.hello

THE_THIS_ARG => person

THE_ARGS => ["world"](类数组对象)

最后 boundHello("word") 被翻译成(不完全是)这样的东西:

person.hello.apply(person, ["world"]);

也许,下一个带有一些调试的示例可以帮助您比我的解释更好地理解:

var person = {
    name: "Brendan Eich",
    hello: function(thing)
    {
        console.log(this.name + " says hello " + thing);
    }
}

var bind = function(func, thisValue)
{
    console.log("func is: ", func);
    console.log("thisValue is: ", thisValue);
    return function()
    {
        console.log("Arguments are:", arguments);
        return func.apply(thisValue, arguments);
    }
}

var boundHello = bind(person.hello, person);
boundHello("world") // "Brendan Eich says hello world"

同样的解释在某种程度上也适用于第二个例子。但在这种情况下 bind 不会像前面的示例那样 return 函数,而是使用此设置调用 apply

THE_FUNC => person.hello

THE_THIS_ARG => person

THE_ARGS => [person.hello, person](类数组对象)

所以,当你调用 bind(person.hello, person) 时,它会被转换成类似这样的内容:

person.hello.apply(person, [person.hello, person]);

如您所见,person.hello 将是 person.hello() 方法接收的 thing 参数,这就是在 [=32 的位置打印函数定义的原因=] 参数。

var person = {
    name: "Brendan Eich",
    hello: function(thing)
    {
        console.log(this.name + " says hello " + thing);
    }
}
    
var bind = function(func, thisValue)
{
    console.log("Arguments are:", arguments);
    return func.apply(thisValue, arguments);
}

var boundHello = bind(person.hello, person);
//boundHello("world") // "Uncaught TypeError: boundHello is not a function"