2009-11-04 56 views
1

我从this post了解到,这是修改Object的JavaScript原型的反模式。不过,我很好奇,如果它被广泛认为是修改其他“内置”原型的反模式。例如:假设我们想为CanvasRenderingContext2D添加一个setPixel(x,y,color)函数 - 以抽象出获取上下文图像数据,设置像素为特定颜色,并将图像数据放回的责任。这是修改JavaScript内置原型的反模式吗?

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); 
};

我还没有测试过这段代码,但你明白了。是否这样反对'最佳实践'?

+1

这个评论与你的问题没有关系,但是如果你想在Safari 3(或者其他)中扩展CanvasRenderingContext2D的原型,你需要这样访问它: document.createElement('canvas')。getContext ('2d').__ proto__ – 2009-11-04 20:38:36

+0

@Fabien - 为什么Safari需要这样的篮球,而Safari 4是否需要这样的? – 2009-11-04 20:40:24

+0

@James Safari 4不需要这个,但是我没有意识到Safari 3需要这个奇怪的东西。伟大的提示法比安! – JasonWyatt 2009-11-04 20:45:22

回答

3

一般来说,如果您要在JavaScript中为其中一个基础对象添加原型,您应该有一个很好的理由,并且确实没有理由修改Object,因为您不知道如何预测结束结果将是该修改。

我倾向于将startsWith,trim和其他一些函数添加到String中,例如,因为这些是辅助函数,就像为Firefox添加一些函数但不包含IE只是有意义的(例如过滤函数)。

因此,添加到画布是好的,但是,如果有人正在使用您的库,并使用excanvas会怎么样。会造成问题吗?

你可能想要探索它,或记录它不适用于excanvas,如果你有一个小的测试来表明它,请包括它,以便如果以后有新版本,并且你的问题消失的人可以验证。

UPDATE: 你会想这样做:

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

这样一来,如果有人做了包括一个由名字,你不会覆盖它,但你必须优雅地处理它。

0

只要功能或命名不会覆盖已存在的内容,我不会看到任何问题。我知道一些修改了Trim功能的string原型。

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

有什么好笑的,C#现在有什么所谓的扩展方法,有效地做同样的事情。

4

我不会这样做,因为它很难追踪哪里实施。它还引入了两个人压倒相同行为的风险。

+1

但是,如果一个浏览器在其Canvas版本中具有某些功能,并且希望将其添加到不包含它的另一个浏览器,它可以帮助简化。 – 2009-11-04 20:37:23

+0

我同意,它很难追踪事物的实现,但它似乎是一个更优雅的解决方案,而不是用自定义对象来包装对象,只是添加一个或两个函数。 所以我想一个新的问题会是:这是“优雅”的谬误?有点像goto语句? – JasonWyatt 2009-11-04 20:39:56

+0

我不认为它与goto语句的公平比较,但我确实认为优雅是一种错觉。它可能会使代码看起来更好,但对于不熟悉代码的开发人员而言,我认为这会使代码更难理解。 – 2009-11-04 20:46:03

1

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

0

并非如此,但如果Ajax库制造商无法依赖内置类型及其属性,可能会遇到问题。所以你可以打破依赖于某些行为的代码。

1

所有这些“反模式”的建议不要盲目采用。无论他们说什么,有时候最好的答案就是咬紧牙关,违背惯例让事情顺利进行。这当然主要取决于你的情况。

我想起了一种情况,在这种情况下,重新组织代码的时间是“正确的方式”,当一个简单的GO TO工作得很好而且只需要几分钟时间来执行时。最后,创建了一堆错误,因为代码被改变了,不需要改变。我是GO TO陈述的粉丝吗?一定不行!但是,如果使用防止一个月的头痛,那么毫无疑问。