Function.bind.bind(Function.call)如何解决?

dje*_*lin 13 javascript functional-programming this function-binding

我的代码库中有这一行:

var uncurryThis = Function.bind.bind(Function.call);
Run Code Online (Sandbox Code Playgroud)

我正在努力解决这个问题.据推测,它是不可靠的.我该如何解决这个问题?

我想这是一个版本Function.bind,其自身this必然Function.call.对我没有帮助.而且我没有找到任何用途,所以我甚至不确定你是单独称它还是需要"作为一种方法"来调用它,只是,你知道,首先绑定它.

Poi*_*nty 15

它将call函数传递给bind函数,bind函数本身就是函数的值this.因此,您可以获得一个bind函数的包装器,thiscall函数在您调用它时可以安排为函数.,又是一个功能,可以让你创建一个围绕在一个包装call必将给您传递一些参数的功能.

如果您今天早上醒来时没有连续喝咖啡,请一步一步:

  • Function.bind.bind是对bind函数的引用.引用是从 - 混淆点1 - 属性bind本身的属性生成的.请记住,bind当使用某个函数作为对象调用时,该函数用于创建围绕该函数的包装器,并this绑定到传入的第一个参数.
  • 因此,该函数调用为您提供了一个函数.该功能就像你打电话一样Function.call.bind(something).
  • 如果你将一些随机函数作为参数传递给那个函数,那么,你会得到一个围绕随机函数的包装器,当被调用时,它将起作用randomFunction.call(whatever).

所以:

function random() {
  alert(this.foo);
}

var bb = Function.bind.bind(Function.call);

var randomcall = bb(random);

randomcall({ foo: "hello world" }); // alerts "hello world"
Run Code Online (Sandbox Code Playgroud)

最终的一点是:你有一个函数,在函数内部有代码,它们希望this有一些属性,并且它this以某种方式使用.你真的希望能够在这里使用某个对象的那个函数,那里有一些对象.你显然可以这样做

random.call(someObject);
Run Code Online (Sandbox Code Playgroud)

但是这个神奇的"绑定绑定调用"技巧为您提供了一种廉价的方法来创建函数的变体,使您可以避免显式编码的调用.call().它还允许您延长您的高级前端开发人员位置一段时间.

编辑 - 我要破坏上面的妙语,因为我只是想到了一个很好的理由使用bind + call技巧来获得一个函数来安排调用某些期望的函数,该函数期望通过this某些"所有者" 进行操作"对象.假设您有一个字符串数组,并且您希望以小写字母获得这些字符串的版本.你可以这样写:

var uc = ["Hello", "World"];
var lc = uc.map(function(s) { return s.toLowerCase(); });
Run Code Online (Sandbox Code Playgroud)

但是使用神奇的"bb"函数我们也可以写:

var uc = ["Hello", "World"];    
var tlc = bb(String.prototype.toLowerCase);
var lc = uc.map(tlc);
Run Code Online (Sandbox Code Playgroud)

用这种方式编写的改进并不多,但如果要bb()编写所有方便的String原型方法的一组包装,它可能更有意义.当然,一切都有价格,而且这种包装可能会对性能产生一些影响.(如果这样的做法很常见,那么运行时可能会得到改善.)


Ber*_*rgi 6

好.你知道bind吗?它是一个函数来修复它们的this参数,并返回一个新函数.它可以简化为:

function bind(context) {
    var fn = this;
    return function() {
        return fn.apply(context, arguments);
    };
}
Run Code Online (Sandbox Code Playgroud)

我将使用具有大量部分应用程序的更多功能样式缩写具有上下文的函数调用:bind fn(context) - > fn context.带参数:( bind fn(context))(...)等于fn context(...).

同样,call确实需要一个this值,而不是返回的功能,它现在应用它:调用FN(背景下,...) - > FN 上下文(...).

现在让我们来看看你的代码:bind.call(bind, call).在这里,你将bindbindcall作为该值:绑定绑定(通话).让我们扩展这个(使用上面的规则)来绑定调用.如果我们现在提供一些参数怎么办?

bind bind(call)(fn)(context,...)

bind call (fn)(context,...)

call fn(context,...)

fn context(...)

一步一步,我们可以做到

uncurryThis = bind bind(call)//bind call

func = uncurryThis(方法)//调用方法

result = func(context,...)//方法上下文(...)

一个实际的用例是任何应该转换为静态函数的"类"方法,将对象(将在其上调用该方法)作为第一个参数:

var uncurryThis = Function.bind.bind(Function.call);
var uc = uncurryThis(String.prototype.toUpperCase);
uc("hello") // in contrast to "hello".toUpperCase()
Run Code Online (Sandbox Code Playgroud)

如果您不能进行方法调用但需要静态函数,这可能会有所帮助; 例如,如

["hello", "world"].map(uc) // imagine the necessary function expression
Run Code Online (Sandbox Code Playgroud)

此外,您要调用的方法可能不是对象本身的方法,如

var slice = uncurryThis(Array.prototype.slice);
slice(arguments) // instead of `Array.prototype.slice.call(arguments)` everywhere
Run Code Online (Sandbox Code Playgroud)

如果它有帮助,这里也是一个显式实现,没有任何绑定:

function uncurryThis(method) {
    return function(context/*, ...*/)
        return method.apply(context, Array.prototype.slice.call(arguments, 1));
    };
}
Run Code Online (Sandbox Code Playgroud)