【问题标题】:Javascript function invocation & bindingJavascript函数调用和绑定
【发布时间】:2019-07-14 16:22:41
【问题描述】:

我有以下部分代码:

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 向世界问好

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

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 说你好 function(thing) { console.log(this.name + "打招呼" + thing); }

谁能解释一下为什么会发生这种情况以及 bind 中的 2 个嵌套 return 函数到底是什么?

它们究竟是如何工作的?

【问题讨论】:

  • 当我运行你的第二个例子时,我得到了uncaught TypeError: boundHello is not a function - 这是我所期望的(但无论如何我都会检查它以防我错过了什么)。不同之处在于bind 的第一个(正确)版本返回一个函数——func 的一个版本,它始终绑定到thisValue 作为其this 引用。第二个(不正确的)版本只是立即返回一个(非函数)值(在这种情况下它是undefined,但它通常是func 为您提供的参数返回的任何值) - 所以你可以'不叫它。
  • 我想我有点明白你所说的无功能是什么意思了。

标签: javascript function binding method-invocation


【解决方案1】:

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

现在,这个bind 定义返回一个function,它显式不带参数(但隐式可以带任何参数),当调用此函数时,它将返回调用@987654321 的评估@ on THE_FUNC 使用 THE_THIS_ARG 作为 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 不会像上一个示例那样返回函数,而是使用此设置调用 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 参数,这就是打印函数定义来代替thing 参数的原因。

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"

【讨论】:

  • 谢谢!控制台日志记录似乎成功了,帮助我理解了!
【解决方案2】:

在您的第二个版本中,当您调用 bind() 时,您将调用 func,并返回函数调用的值。

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

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

【讨论】:

  • 对我来说,一个令人困惑的部分是返回的函数应该有一个参数,现在它不需要任何参数。正确的?我也猜想我应该阅读有关 Javascript 闭包的信息...?
  • 返回的函数使用特殊变量arguments,它会自动设置为一个包含给函数的所有参数的数组。所以它可以使用任意数量的参数。
猜你喜欢
  • 1970-01-01
  • 2019-01-30
  • 2021-05-08
  • 1970-01-01
  • 2018-11-10
  • 2015-09-25
  • 1970-01-01
  • 1970-01-01
  • 2015-11-11
相关资源
最近更新 更多