Javascript - 使用apply来调用绑定函数

时间:2012-11-06 19:54:06

标签: javascript

假设我们有以下示例Javascript代码:

var modeller = "foo";
var provider1 = function (modeller, content, optionalArg) {
    alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg);
}.bind(null, modeller);

var provider2 = function (content, optionalArg) {
    alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg);
};

var createConsumer = function () {
    // some arbitrary private vars
    var content = 1; 
    var option = 2; 

    var doConsume = function(provider) {
        provider.apply(this, [content, option])
    };
    return {consume: doConsume};
};

// Now use them
var consumer = createConsumer();

consumer.consume(provider1);
consumer.consume(provider2);

为了演示目的,这简化了很多,但要点是provider1已经绑定,而provider2不是 - 消费者不能将自己作为this参数传递给{ {1}}。

问题:有没有办法检测已绑定函数的情况?有没有办法让provider1将消费者用作provider1?假设答案是否定的,那么解决这种情况的最佳方法是什么?

3 个答案:

答案 0 :(得分:4)

  

“有没有办法检测这种函数已被绑定的情况?”

没有

  

“有没有办法让provider1consumer用作this?”

没有

  

“......解决这种情况的最佳方法是什么?”

因为看起来你想要绑定一个参数而不是this值,我会在Function.prototype上创建一个参数binder方法,它返回一个只绑定了参数的函数,而不是{{ 1}}。

this

然后你会像这样使用它:

Function.prototype.argBind = function() {
    var _slicer = [].slice,
        orig_args = _slicer.call(arguments),
        orig_func = this;
    return function() {
        return orig_func.apply(this, orig_args.concat(_slicer.call(arguments)));
    };
};

现在,var modeller = "foo"; var provider1 = function (modeller, content, optionalArg) { alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg); }.argBind(modeller); 函数将被调用,但是给出了正常的provider1值,但this将被绑定为第一个参数。

答案 1 :(得分:0)

有一种方法可以检测某个函数是否已经绑定但是它不是很优雅: /\[native code]/.test(foo.toString()); 绑定函数具有toString()的本机代码。这适用于Chrome(NodeJS)。我不了解其他浏览器。

答案 2 :(得分:0)

以下是一些示例代码,它演示了 apply() 和 call() 的第一个参数不会改变绑定函数中“this”的值:

let bf = f .bind  (123);
let n  = bf.call  (234);
let n2 = bf.apply (234);
ok (n  === 123);
ok (n2 === 123);

function f ()
{ return this;
}

(上面的 ok() 是一个函数,如果调用的参数不真实,则会抛出错误)。

你能检测一个函数是否被绑定了吗?

以上 Mihai Voicescu 的回答在我看来是正确的。一种变体是:

将一些唯一的字符串(例如说您的名字作为函数的作者)放入您稍后要测试“绑定”的函数源代码中的注释中。取被测函数的 toString() 。如果这不包括它在原始来源中的唯一字符串,那么您就知道它是一个界限。最好像往常一样测试您想要支持的浏览器。

解决这种情况的最佳方法是什么?

使用普通的可选参数传入您要用作“substitute-this”的对象。例如,称其为“自我”。 'self' 参数可以将其默认值声明为 'this'。然后在函数内部到处使用“self”而不是“this”。默认情况下,它的值将与绑定的“this”相同,但您可以通过为可选参数“self”传入一个不同的显式值来更改它。如果您确实想使用绑定的“this”,则根本不需要传入可选的自参数。