I have the following part of code:
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"
Here, the code will print out in the console the text
Brendan Eich says hello world
if I take the bind variable assignment and I change it to:
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"
then the results is
Brendan Eich says hello function(thing) { console.log(this.name + " says hello " + thing); }
Could someone explain me why is that happening and what exactly are the 2 nested return functions inside the bind one?
How exactly do they work?
I will try to explain as best as I can. On the first example your bind
definition is a function
that get two arguments, ideally a function as first argument (lets call it THE_FUNC) and an object as second argument (lets call it THE_THIS_ARG) that will use as the thisArgs
for that function.
Now, this bind
definition returns a function
that explicitly takes no arguments (but implicitly could take any arguments) and when this function is called it will return the evaluation of calling apply on THE_FUNC using THE_THIS_ARG as the value of this
for THE_FUNC and using the arguments
received (lets call it THE_ARGS) as the arguments passed to THE_FUNC.
For your particular example, the setup will be this one:
THE_FUNC => person.hello
THE_THIS_ARG => person
THE_ARGS => ["world"]
(array-like object)
Finally boundHello("word")
is then traduced in something like (not exactly) this:
person.hello.apply(person, ["world"]);
Maybe, next example with some debugs can help you to understand better than my explanation:
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"
The same explanation is some sort of valid for the second example too. But in this case bind
do not return a function like in the previous example, and instead call apply
with this setup:
THE_FUNC => person.hello
THE_THIS_ARG => person
THE_ARGS => [person.hello, person]
(array-like object)
So, when you call bind(person.hello, person)
is then traduced into something like:
person.hello.apply(person, [person.hello, person]);
And as you can see person.hello
will be the thing
argument received by person.hello()
method and that is the reason a function definition is printed in the place of the thing
argument.
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"