3

假设我们有以下示例 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作为provider1.

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

4

3 回答 3

4

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

不。

“有没有办法provider1使用consumeras this?”

不。

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

由于您似乎想要绑定一个参数而不是this值,因此我会创建一个参数绑定方法,Function.prototype该方法返回一个仅绑定参数的函数,而不是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,但modeller将绑定为第一个参数。

于 2012-11-06T20:04:19.630 回答
1

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

于 2017-07-28T14:47:54.193 回答
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() 。如果这不包括它在原始源中所做的唯一字符串,那么您就知道它是一个绑定。最好一如既往地测试您想要支持的浏览器。

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

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

于 2021-04-17T17:31:32.937 回答