Почему Function.bind ("foo"). Call ("bar") всегда называет это "foo" - PullRequest
4 голосов
/ 27 августа 2011

Я только что испытал поведение в JS, которое не смог понять: я хотел создать метод, который вызывает String.prototype.replace с некоторыми заданными аргументами, поэтому я придумал это:

String.prototype.replace.bind("foo", /bar/g, function(){}).call

Я догадался, что получу функцию, в которую мне нужно будет просто добавить строку, чтобы получить замену. Вместо этого я всегда получаю начальное this -значение (в данном случае foo).

Теперь мои вопросы:

  • Почему JS ведет себя так? Что на самом деле возвращает связывание и как я могу получить this -параметр .call()?
  • Есть ли другой способ сделать то, что я хочу, без создания функции-оболочки?

Ответы [ 3 ]

2 голосов
/ 27 августа 2011

Почему это происходит

Вы передаете некоторое значение this из call в функцию, возвращаемую bind.Однако bind игнорирует это значение и вызывает исходную функцию со значением this (например, foo).Фактически, bind - это , означающее для привязки значения this.arguments, который вы можете связать, - это скорее нечто дополнительное.

Решение этого вопроса

Без функции-обертки я не думаю, что вы можете делать то, что хотите.Однако с помощью функции-обертки вы можете делать то, что вам нужно:

Function.prototype.bindArgs = function() {
    var args = arguments,
        func = this;

    return function(context) {
        return func.apply(context, args);
    }
};

Например

var func = function(a, b, c) {
    console.log(this, a, b, c);
};

var bound = func.bindArgs(1, 2, 3);
bound([1]); // [1] 1 2 3
bound({a: 1}); // {a: 1} 1 2 3
2 голосов
/ 27 августа 2011

Function.bind возвращает новую функцию, которая при вызове всегда будет вызывать исходную функцию с привязанным контекстом.

Можно реализовать Function.bind так:

Function.prototype.bind = function(context) {
    var origFunction = this;
    return function() {
        return origFunction.apply(context, arguments);
    };
};

Вы можете попробовать это здесь: http://jsfiddle.net/HeRU6/

Так что, когда вы делаете somefunction.bind("foo"), он возвращает новую функцию.Вызов этой новой функции всегда вызовет somefunction с "foo" в качестве контекста.

Вы можете написать функцию, которая будет связывать только аргументы, а не контекст:

Function.prototype.curry = function() {
    var origFunction = this, args = Array.prototype.slice.call(arguments);
    return function() {
        console.log(args, arguments);
        return origFunction.apply(this, Array.prototype.concat.apply(args, arguments));
    };
};

a = function() { console.log(this, arguments); };

b = a.curry(1, 2);
b(); // Window [1, 2]
b(3); // Window [1, 2, 3]
b.call("foo", 4); // "foo" [1, 2, 4]
1 голос
/ 27 августа 2011

Почему JS ведет себя так?

Так как это определено в стандарте .

Что связываетдействительно вернуть и как я могу получить этот-параметр .call ()?

g = f.bind(foo, bar, ...) точно так же, как function g() { return f.call(foo, bar, ...); } Так как * g в *1016* нет, выне могу получить его обратно из вызова.

Есть ли другой способ сделать то, что я хочу сделать без создания функции-оболочки?

Возможно, нет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...