Я постараюсь объяснить как можно лучше. В первом примере ваше определение bind
— это function
, которое получает два аргумента, в идеале — функцию в качестве первого аргумента (давайте назовем ее THE_FUNC) и object в качестве второго аргумента (назовем его THE_THIS_ARG), который будет использоваться как thisArgs
для этой функции.
Теперь это определение bind
возвращает function
, которое явно не принимает аргументов (но неявно может принимать любые аргументы), и когда эта функция вызывается, она возвращает оценку вызова применить к THE_FUNC, используя THE_THIS_ARG в качестве значения this
для THE_FUNC и использования полученного 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
будет аргументом thing
, полученным методом person.hello()
, и именно поэтому определение функции печатается вместо аргумента 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"
person
Shidersz
schedule
20.02.2019
uncaught TypeError: boundHello is not a function
- это то, что я ожидал (но все равно проверял его на случай, если я что-то пропустил). Разница в том, что первая (правильная) версияbind
возвращает функцию — версиюfunc
, которая всегда связана сthisValue
в качестве ссылки наthis
. Вторая (неправильная) версия просто сразу возвращает (нефункциональное) значение (в данном случае этоundefined
, но в целом это будет то, чтоfunc
возвращает для аргументов, которые вы предоставили), поэтому вы не можете вызвать это. - person Robin Zigmond   schedule 21.02.2019