JavaScript有什么反模式?
我发现不应该做的是比应该做的更难的教训。
根据我的经验,将专家与中间人分开的能力是从各种表面上相同的方式中进行相同的select。
所以,谈到JavaScript ,你不应该做什么样的事情,为什么 ?
我可以find很多Java的这些,但由于JavaScript的典型上下文(在浏览器中)是非常不同于Java的,我很好奇,看看是什么出来。
语言:
-
命名空间通过在全局上下文中创build大量variables来进行污染。
-
以'foo.onclick = myFunc'的forms绑定事件处理程序(不可扩展,应该使用attachEvent / addEventListener)。
-
几乎在任何非JSON上下文中使用eval
-
几乎每一次使用document.write(使用像document.createElement这样的DOM方法)
-
针对Object对象的原型(BOOM!)
-
这是一个小问题,但是用“+”做大量string连接(创build一个数组并join数组效率更高)
-
引用不存在的
undefined
常量
devise/部署:
-
(一般)不提供无脚本支持。
-
不要将代码打包到单个资源中
-
将内联脚本(即body)脚本放在主体的顶部附近(阻止加载)
Ajax特定:
-
不向用户指示请求的开始,结束或错误
-
轮询
-
传递和parsingXML而不是JSON或HTML(在适当的情况下)
编辑:我一直在想更多!
除了那些已经提到的…
-
使用
for..in
构造来遍历数组
(遍历数组方法和索引) -
使用Javascript内联像
<body onload="doThis();">
(不灵活并阻止多个事件监听器) -
使用“Function()”构造函数
(由于相同的原因,eval()
不好) -
传递string而不是函数
setTimeout
或setInterval
(也在内部使用eval()
) -
依靠不使用分号的隐式语句
(不好的习惯去拿,并可能导致意想不到的行为) -
使用/ * .. * /来阻止代码行
(可能会干扰正则expression式,例如:/* /.*/ */
)<传福音>当然,不使用原型;)</传福音>
对我来说最大的不是理解JavaScript编程语言本身。
- 过度使用对象层次结构并构build非常深的inheritance链。 在JS中,浅层次结构在大多数情况下工作正常。
- 不理解基于原型的面向对象,而是build立大量的脚手架,使JS像传统的OO语言一样。
- 程序/function性程序devise可能更为简洁和高效时,无需使用面向对象的范例。
接下来是浏览器运行时间
- 不使用事件委托或观察者模式(pub / sub)等良好的事件模式来优化事件处理。
- 频繁的DOM更新(如循环中的.appendChild),当DOM节点可以在内存中并一次追加。 (巨大的性能优势)。
- 当使用本地方法(getElementById,getElementByTagName等)时,过度使用库来select具有复杂select器的节点。 这个问题现在越来越less了,但值得一提的是。
- 如果希望第三方脚本与您的页面位于同一页面,则可以扩展DOM对象(最终会破坏对方的代码)。
最后是部署问题。
- 不要缩小文件。
- Web服务器configuration – 不是gzip你的文件,不caching他们合理。
<plug>我有一些客户端优化技巧 ,涵盖了我上面提到的一些事情,以及更多,在我的博客上。</ plug>
- 浏览器检测(而不是testing你想使用的具体方法/字段是否存在)
- 在大多数情况下使用alert()
另请参阅Crockford的“Javascript:好的部分”以避免其他各种事情。 ( 编辑:警告,在他的一些build议中,比如使用“===”而不是“==”,所以要对他们进行一些盐的处理)
有几件事情在我头上。 当我想到更多时,我会编辑这个列表。
- 不要污染全局名称空间。 而不是在对象中组织东西;
- 不要忽略variables的“var”。 这会污染全局名称空间,并可能使您遇到其他此类脚本的麻烦。
任何使用“与”
与(document.forms [“mainForm”]。元素){
input1.value =“垃圾”;
input2.value =“垃圾”; }
任何参考
document.all
在你的代码中, 除非它是在特殊代码中,只是为了IE来克服一个IE的bug。 ( 咳嗽 document.getElementById() 咳嗽 )
不使用基于社区的框架来完成像DOM操作,事件处理等重复任务
在创build语句时不恰当地使用大括号定位
由于自动分号插入,您应该始终在语句后加一个大括号。
比如这个:
function() { return { price: 10 } }
与此大不相同:
function(){ return{ price: 10 } }
因为在第一个例子中,javascript会为你插入一个分号,其实就是这样的:
function() { return; // oh dear! { price: 10 } }
对可能长时间运行的任务使用setInterval。
对于需要重复执行某些操作的场合,您应该使用setTimeout而不是setInterval。
如果使用setInterval,但是定时器执行的函数在定时器下一次滴答时没有完成,这是不好的。 而应使用setTimeout使用以下模式
function doThisManyTimes(){ alert("It's happening again!"); } (function repeat(){ doThisManyTimes(); setTimeout(repeat, 500); })();
Paul Irish在他从jQuery源video中学到的10件事情上做了很好的解释
有效的caching很less完成:
- 当您可以使用像Google的Libraries API这样的共享API来加快页面加载时,不要在服务器上存储库的副本(jQuery,Prototype,Dojo)
- 把你所有的脚本合并并缩小成一个
- 使用mod_expires为您的所有脚本提供无限的caching生命周期(从不重新下载)
- 版本您的JavaScript文件名,以便客户端无需重新加载/重新启动(即myFile_r231.js,或myFile.js?r = 231)