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_FUNC 的 this
的值,并使用收到的 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"
我有以下部分代码:
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_FUNC 的 this
的值,并使用收到的 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"