首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Function.prototype.bind

Function.prototype.bind
EN

Stack Overflow用户
提问于 2011-09-02 18:27:04
回答 2查看 13.8K关注 0票数 22

我有一个关于EcmaScript-5 Function.prototype.bind实现的非常有趣的问题。通常,当您使用bind时,您可以这样做:

代码语言:javascript
复制
var myFunction = function() {
    alert(this);
}.bind(123);

// will alert 123
myFunction();

好的,这很酷,但是当我们这样做的时候会发生什么呢?

代码语言:javascript
复制
// rebind binded function
myFunction = myFunction.bind('foobar');
// will alert... 123!
myFunction();

我知道,就Function.prototype.bind的实现方式(https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind)而言,这是完全符合逻辑的行为。但在现实生活中,这完全是无用的行为,不是吗?问题是:它是bug还是特性?如果它是一个bug,为什么它没有被提及?如果它是一个功能,那么为什么Google Chrome与原生“绑定”实现的行为完全相同?

为了让它更清楚,在我看来更有意义的是,下面的代码片段实现了稍微不同的Function.prototype.bind:

代码语言:javascript
复制
if (!Function.prototype.bind) {
    Function.prototype.bind = function() {
        var funcObj = this;
        var original = funcObj;
        var extraArgs = Array.prototype.slice.call(arguments);
        var thisObj = extraArgs.shift();
        var func = function() {
            var thatObj = thisObj;
            return original.apply(thatObj, extraArgs.concat(
                Array.prototype.slice.call(
                    arguments, extraArgs.length
                )
            ));
        };
        func.bind = function() {
            var args = Array.prototype.slice.call(arguments);
            return Function.prototype.bind.apply(funcObj, args);
        }
        return func;
    };
}

所以现在试试这个:

代码语言:javascript
复制
// rebind binded function
myFunction = myFunction.bind('foobar');
// will alert... "foobar"
myFunction();

在我看来,替换"this“更有意义...

你们是怎么想的?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-09-06 09:30:13

Function.prototype.bind的先例是该思想在各种JS框架中的实现。据我所知,它们都不允许通过后续绑定更改this-binding。您可能会问为什么它们都不允许这种绑定更改,就像问为什么ES5不允许这样做一样。

你不是我听过的唯一一个觉得奇怪的人。Chris Leary在Mozilla的JS引擎上工作(和我一样),他认为这有点奇怪,几个月前在Twitter上提出了这个问题。在另一种不同的形式中,我记得Mozilla实验室的一名黑客质疑是否有某种方法可以“解除”函数的绑定,从函数中提取目标函数。(如果可以这样做,您当然可以将它绑定到不同的this,至少如果您还可以提取绑定的参数列表来传递它。)

我不记得在指定bind时讨论过的问题。然而,在这件事被讨论出来的时候,我并没有特别密切地关注es-讨论邮件列表。话虽如此,我不认为ES5希望在这一领域进行太多创新,借用一句话来说,就是“铺平一条平坦的路”。

如果你写了一个足够详细的提案,你可能会提出一些内省的方法来解决这些问题并进行讨论。另一方面,绑定是信息隐藏机制的一种形式,这将阻碍其被采用。如果你有时间,可能值得尝试提出一些建议。我的猜测是,信息隐藏的担忧会阻止提案被采用。但这只是一个猜测,很可能是错误的。只有一种方法能找到答案。

票数 14
EN

Stack Overflow用户

发布于 2013-07-26 00:24:03

当您绑定一个函数时,您请求一个新函数,该函数忽略它自己的this伪参数,并使用一个固定值调用原始函数。

另一次绑定此函数具有完全相同的行为。如果bind以某种方式将一个新的this补丁到其中,那么它将不得不为已经绑定的函数提供特殊情况。

换句话说,bind对“普通”函数的作用与对bind返回的函数的作用完全相同,在没有覆盖因素的情况下,保持函数的语义复杂性是一个很好的工程-如果以完全相同的方式对待所有输入函数,则更容易记住bind对函数做了什么,而不是特殊地对待某些输入函数。

我认为您的困惑在于,您将bind视为修改现有的函数,因此,如果您再次修改它,您会期望原始函数再次被修改。然而,bind并没有修改任何东西,它创建了一个具有特定行为的新函数。新函数本身就是一个函数,它不是原始函数的魔法补丁版本。

因此,为什么它被标准化或发明成原来的方式并不神秘: bind返回一个函数,该函数提供新的this和前置参数,并且在所有函数上都是相同的。最简单的语义。

只有这样才能真正安全地使用--如果绑定会在已经绑定的函数和“正常”函数之间产生差异,那么就必须在绑定之前进行测试。一个很好的例子是jQuery.each,它传递一个新的this。如果bind指定绑定函数,则没有安全的方法将绑定函数传递到jQuery.each中,因为这将在每次调用时被覆盖。要解决这个问题,jQuery.each必须以某种方式指定绑定函数。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7282158

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档