【问题标题】:Is it an anti-pattern to modify JavaScript's built-in prototypes?修改 JavaScript 的内置原型是一种反模式吗?
【发布时间】:2009-11-04 20:23:34
【问题描述】:

我从this post 了解到,在 JavaScript 中修改 Object 的原型是一种反模式。但是,我很好奇它是否被广泛认为是修改其他“内置”原型的反模式。

例如:假设我们想在CanvasRenderingContext2D 中添加一个setPixel(x,y,color) 函数 - 以抽象出获取上下文图像数据、将像素设置为某种颜色并将图像数据放回的职责。

CanvasRenderingContext2D.prototype.setPixel = function(x, y, color){
    var imgdata = this.createImageData(1,1);
    imgdata.data[0] = color.r;
    imgdata.data[1] = color.g;
    imgdata.data[2] = color.b;
    imgdata.data[3] = color.a;
    this.putImageData(imgdata,x,y);
};

我没有测试过这段代码,但你明白了。这样的事情是否违反“最佳实践”?

【问题讨论】:

  • 此评论与您的​​问题无关,但如果您想在 Safari 3(可能还有其他)中扩展 CanvasRenderingContext2D 的原型,您需要以这种方式访问​​它:document.createElement('canvas ').getContext('2d').__proto__
  • @Fabien - 为什么 Safari 需要这样的箍,Safari 4 是否需要这个?
  • @James Safari 4 不需要这个,但是我没有意识到 Safari 3 需要这个奇怪的东西。很棒的小费法比恩!
  • Safari 不会直接暴露 CanvasRenderingContext2D 对象,所以你需要这样做。这可能被解释为一个错误,我同意。 Safari 4 不需要这个。

标签: javascript canvas anti-patterns prototype


【解决方案1】:

我不会这样做,因为它很难跟踪在哪里实现了什么。它还引入了两个人覆盖相同行为的风险。

【讨论】:

  • 但如果一个浏览器在其 Canvas 版本中具有某些功能,并且您想将其添加到另一个不包含它的浏览器,它可以帮助简化。
  • 我同意这使得跟踪事物的实现位置变得很困难,但它似乎是一个比使用自定义对象包装对象只是添加一两个功能更优雅的解决方案。所以我想一个新的问题是:这种“优雅”是谬误吗?有点像 goto 语句?
  • 我认为它与 goto 语句的比较并不公平,但我确实觉得优雅是一种谬误。它可能会使代码看起来更好,但对于不熟悉代码的开发人员来说,我认为它会使代码更难理解。
【解决方案2】:

一般来说,如果你在 JavaScript 中向其中一个基础对象添加原型,你应该有充分的理由,而且真的没有理由修改 Object,因为你不知道如何预测最终结果将是那个修改。

我倾向于在S​​tring中添加startsWith、trim和其他一些函数,例如,因为这些是辅助函数,就像在Array中添加一些Firefox存在但IE不存在的函数才有意义(例如过滤器功能) .

所以,添加到 Canvas 很好,但是,如果有人在使用您的库并使用 excanvas 怎么办。会不会出问题?

您可能想要探索它,或者记录它不适用于 excanvas,如果您有一个小测试来证明这一点,请包含它,这样如果以后有新版本,以及您的问题消失的人可以验证这一点。

更新: 你会想要这样做:

if (!CanvasRenderingContext2D.setPixel) {
...
}

这样,如果有人确实包含了该名称的人,您不会覆盖它,但您需要优雅地处理它。

【讨论】:

    【解决方案3】:

    绝对不是;如果方法以这种方式与对象相关,那么它是一个优雅的解决方案。

    【讨论】:

      【解决方案4】:

      所有这些“反模式”建议都不能盲目采纳。不管他们说什么,有时最好的答案是咬紧牙关,打破常规,让事情顺利进行。当然,这在很大程度上取决于您的情况。

      我想起了这样一种情况,即花费数天时间重新组织代码以“以正确的方式”进行适当的修复,而一个简单的 GO TO 本来可以很好地工作,并且只需要几分钟就可以实现。最后,由于更改了不需要更改的代码,因此产生了一堆错误。我是 GO TO 语句的粉丝吗?一定不行!但是,如果使用一个可以避免几个月的头痛,那么毫无疑问。

      【讨论】:

        【解决方案5】:

        只要功能或命名不会覆盖已经存在的内容,我认为这没有任何问题。我知道一些修改string 原型的Trim 函数。

        http://www.somacon.com/p355.php

        有趣的是,C# 现在有了所谓的扩展方法,它可以有效地做同样的事情。

        【讨论】:

          【解决方案6】:

          与其本身不同,但如果 Ajax 库制造商不能依赖内置类型及其属性,他们可能会遇到问题。因此,您可以破坏依赖于某些行为的代码。

          【讨论】:

            猜你喜欢
            • 2022-07-14
            • 2015-12-08
            • 2015-10-11
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-07-31
            相关资源
            最近更新 更多