【问题标题】:When should I use my own namespace and when should I extend native js objects?什么时候应该使用自己的命名空间,什么时候应该扩展原生 js 对象?
【发布时间】:2011-05-31 09:54:47
【问题描述】:

我正在重构我的代码。我无法决定如何准确地实现我拥有的几个实用功能。 具体来说,如果某些功能在我的个人命名空间中更好,或者直接扩展 js 对象。

扩展原生 JavaScript 对象的示例

(这是正确的术语吗?)。

String.prototype.prettyDate = function(){
  return (this.substr(5,2) + '/' + this.substr(8) + '/' + this.substr(0,4));
}
var myString = "2010-12-27";
//logs 12/27/2010
console.log(myString.prettyDate);

使用我自己的命名空间的示例

var myNamespace = (function(){
   var my = {};
   my.prettyDate = function ( dateStr ){
      return (dateStr.substr(5,2) + '/' + dateStr.substr(8) + '/' + dateStr.substr(0,4));
   }
return my;
}());
var pretifiedDate = myNamespace.prettyDate('2010-12-27');
//logs 12/27/2010
console.log(pretifiedDate);

需要考虑的问题

  1. 什么时候可以合理地将实用程序插入到原生 JavaScript 对象中?
  2. 如何判断实用程序何时最好放在我自己的命名空间中?

【问题讨论】:

  • 这应该是一个 WIKI。您接受的答案提出了很好的观点,但结论却非常不幸。就像任何语言功能一样,使用它,但要了解如何/何时使用它,以及可能的后果。有时这是个好主意,有时可能不是。

标签: javascript inheritance prototypal-inheritance application-structure


【解决方案1】:
  1. 几乎没有,因为:

    a/ 可能与其他库发生冲突

    b/ 扩展函数被in操作符迭代为属性,除非被hasOwnProperty(不常用)过滤掉,否则会带来问题

    您可以为小型的单一脚本工作证明这一点,但前提是您 200% 确定没有人永远不会尝试在某处重用该代码。在这种情况下,仅将其用于跨越多个代码模块的功能。使用 trim() 扩展字符串 - 好的,使用 prettyDate() 扩展字符串 - 值得怀疑,使用 displayAsPageHeader() 扩展 Object - 可怕。

  2. 所以,几乎总是这样。

【讨论】:

  • +1 用于对象迭代和 in 运算符的问题。 :)
  • “可能的冲突” 我认为开发人员会知道所使用的库的行为方式。 “被 in 迭代为属性” 这是一个很好的论点,不扩展 Object.prototype。否则,除非您对数组执行for/in,否则这无关紧要,这完全没有必要。我认为almost never/almost always 被夸大了。
  • +1 但就我个人而言,我会删除两个陈述中的“几乎”。
  • 去过那里,看到图书馆利用一切可能的机会和非常复杂的技术来阻止兼容性和互操作性。我什至见过全局变量 console 声明过一次,所以我更喜欢大胆地说:不要乱用原型!当然,每一个概括都是不好的。
  • @patrick dw:说“语言特性 X 是不必要的,因此我不在乎支持它”不是一个非常可靠的方法——有人会使用它。
【解决方案2】:

很遗憾,这个问题没有“正确”答案。这是一个很好的讨论,但我担心它会在这里关闭。是否应该扩展原生对象是一个主观的争论,如果你接受它是有条件的可以回答“什么时候?”是“取决于”。

如果您可以控制它的使用以及它是否会与其他代码发生冲突,那么您真的没有理由不这样做。它可以非常方便,并且可以显着减少代码大小。

扩展本机对象的真正问题是,当您在扩展程序旁边运行其他代码时,可能期望具有相同属性名称的不同扩展程序,或者可能不小心使用 for(var i in obj) 而不防范扩展程序在原型链上。

【讨论】:

  • 或者这可能是故意使用for (var i in obj)而不检查hasOwnProperty,因为他认为他可以利用javascript中的继承来组合对象。
【解决方案3】:

观看此视频:

John Resig 认为,扩展本机对象会导致灾难,尤其是当框架或应用程序可能会发展成远远超出最初预期的功能时。

【讨论】:

  • 他说的是扩展 DOM 元素,还是 Array、String 等类型?另外,它是从建立一个公共图书馆的角度出发的,还是一般意义上的?
  • @patrick dw - 我会说两者。不久前我看了那个视频,我脑海中浮现的是‘好吧,不再扩展原型,除非它是一个可能永远不会改变的单页简单应用程序’。除了 John R. 看起来非常紧张,而且他偶尔会感到不舒服和过长的停顿之外,这段视频非常值得一看:)
  • 我最终会给它一个手表(感谢资源)。我可以从提供广泛分布的库的角度来看待这些论点。对于个人使用,我的观点是 prototype 的用途。还不如用它。例外是Object.prototype。
【解决方案4】:

好吧...我不是这方面的专家,但几乎从不! 你做的事情在你的命名空间内更安全。如果您遵循模块模式http://www.yuiblog.com/blog/2007/06/12/module-pattern/

,一切都会正常工作

但是有一些小技巧可以让我们避免覆盖其他命名空间。举例:

var myNamespace = {}; //my namespace, unsafely written

//Better solution
if(typeof myNamespace === 'undefined'){
    var myNamespace = {};
}

//Shorter solution
var myNamespace = myNamespace || {};

【讨论】:

  • 你不需要===(严格相等比较)来测试typeof和String。
【解决方案5】:

这取决于您对正在运行/加载的代码的控制程度:

  1. 如果这一切都在您的控制之下,那么扩展内置对象并没有错,JavaScript 被设计为能够做到这一点。唯一的问题是,当两个库更改相同的内容时,您可能会遇到意想不到的问题。幸好你不会这样对自己,对吧?

  2. 如果您不知道/不知道,命名空间会更安全,尽管它笨重且冗长。这总是更安全。

就我个人而言,我更喜欢第二种选择,因为我不喜欢过于冗长的代码并且命名空间看起来很有趣。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-02
    • 2011-04-15
    • 2017-04-10
    • 2012-03-19
    相关资源
    最近更新 更多