Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 是";猴子修补术;真的那么糟糕吗?_Javascript_Ruby_Oop_Language Design_Monkeypatching - Fatal编程技术网

Javascript 是";猴子修补术;真的那么糟糕吗?

Javascript 是";猴子修补术;真的那么糟糕吗?,javascript,ruby,oop,language-design,monkeypatching,Javascript,Ruby,Oop,Language Design,Monkeypatching,有些语言如Ruby和JavaScript具有开放类,允许您修改核心类(如数字、字符串、数组等)的接口。显然,这样做可能会让熟悉API的其他人感到困惑,但是否有充分的理由避免这样做,假设您正在添加到接口而不更改现有行为 例如,向不实现ECMAScript第5版(如果不需要所有jQuery)的web浏览器添加一个实现可能会更好。或者,您的Ruby阵列可能会受益于使用“注入”的“求和”便利方法。只要更改与您的系统隔离(例如,不属于您发布的软件包的一部分),是否有充分的理由不利用此语言功能?Wikipe

有些语言如Ruby和JavaScript具有开放类,允许您修改核心类(如数字、字符串、数组等)的接口。显然,这样做可能会让熟悉API的其他人感到困惑,但是否有充分的理由避免这样做,假设您正在添加到接口而不更改现有行为


例如,向不实现ECMAScript第5版(如果不需要所有jQuery)的web浏览器添加一个实现可能会更好。或者,您的Ruby阵列可能会受益于使用“注入”的“求和”便利方法。只要更改与您的系统隔离(例如,不属于您发布的软件包的一部分),是否有充分的理由不利用此语言功能?

Wikipedia简要总结了猴子补丁的缺陷:


每件事都有时间和地点,也有修补猴子的时间和地点。经验丰富的开发人员掌握了许多技术,并学会了何时使用这些技术。它本身很少是一种“邪恶”的技术,只是不加考虑地使用它

只要将更改隔离到 您的系统(例如,不属于 为您发布的软件包 分配)是否有充分的理由 不要利用这种语言 特征

作为独立问题的独立开发人员,扩展或更改本机对象没有任何问题。对于较大的项目,这也是团队应该做出的选择

就我个人而言,我不喜欢修改javascript中的本机对象,但这是一种常见的做法,也是一种有效的选择。如果你要写一个库或代码,是为了别人的使用,我会极力避免它

但是,允许用户设置一个配置标志是一种有效的设计选择,该标志表示请使用方便的方法覆盖本机对象,因为这样做非常方便

来说明特定于JavaScript的陷阱

Array.protoype.map = function map() { ... };

var a = [2];
for (var k in a) {
    console.log(a[k]);
} 
// 2, function map() { ... }
使用ES5可以避免这个问题,ES5允许您将不可枚举的属性注入到对象中


这主要是一个高层次的设计选择,每个人都需要意识到/同意这一点。

使用“猴子补丁”来纠正一个特定的已知问题是完全合理的,而另一种选择是等待补丁修复它。这意味着暂时承担修复的责任,直到有一个“适当的”,正式发布的修复,您可以部署


Gilad Bracha对Monkey Patching的一个深思熟虑的意见是:

Monkey Patching与编程工具箱中的许多工具一样,既可以用于善,也可以用于恶。问题是,总的来说,这些工具在哪里使用最多。根据我使用Ruby的经验,天平在“邪恶”方面的分量很大

那么猴子修补术的“邪恶”用途是什么呢?一般来说,猴子打补丁会让你面临重大的、潜在的无法诊断的冲突。我有一门课
a
。我有一种猴子补丁模块
MB
,它补丁
A
,包括
method1
method2
method3
。我有另一个猴子修补模块
MC
,它也修补
A
,包括
method2
method3
method4
。现在我左右为难。我调用A.method2的实例:调用谁的方法?答案取决于很多因素:

  • 我按什么顺序引入了配线模块
  • 补丁是立即应用还是在某种条件下应用
  • aaaaaargh!蜘蛛从里面把我的眼球吃掉了 好吧,那么#3可能有点夸张了

    无论如何,这就是猴子修补的问题:可怕的碰撞问题。考虑到通常支持它的语言的高度动态性,您已经面临许多潜在的“远距离恐怖行为”问题;猴子修补只是增加了这些


    如果你是一个负责任的开发人员,有猴子补丁是很好的。不幸的是,在IME中,往往会有人看到猴子修补程序,并说:“好极了!我只是用猴子修补它,而不是检查其他机制是否更合适。”这种情况大致类似于人们创建的Lisp代码库,他们在考虑将宏作为一种函数来执行之前,先使用宏。您描述的条件(添加(不更改)现有行为,而不将代码发布到外部世界)似乎相对安全。但是,如果Ruby、JavaScript或Rails的下一个版本更改了它们的API,则可能会出现问题。例如,如果jQuery的未来版本检查Array.map是否已经定义,并假设它是map的EMCA5Script版本,而实际上它是您的monkey补丁,该怎么办


    类似地,如果您在Ruby中定义了“sum”,有一天您决定在Rails中使用该Ruby代码,或者将活动支持gem添加到您的项目中,该怎么办。主动支持还定义了一个求和方法(在可枚举上),因此存在冲突。

    关于Javascript:

    假设您正在向接口添加内容,而不更改现有行为,那么是否有很好的理由避免这样做

    对。最糟糕的情况是,即使您不改变现有的行为,也可能会破坏该语言未来的语法

    这正是和所发生的事情。简言之,规范是为这些方法编写的,他们的建议得到了采纳,然后浏览器开始发布它。但是,在这两种情况下,都发现有一些古老的库使用与新方法同名的方法修补内置的
    数组
    对象,并且具有不同的行为;结果,网站崩溃了,浏览器不得不退出新方法的实现,而speci
    if (!Array.prototype.flatMap) {
      Array.prototype.flatMap = function(...
        // ...
      }
    }