日期:2014-05-16  浏览次数:20441 次

JavaScript Patterns 笔记(三) 循环

For循环
遍历arrays或array-like对象(如:arguments、HTMLCollection)
// sub-optimal loop
for (var i = 0; i < myarray.length; i++) {
// do something with myarray[i]
}
每次循环都会去访问myarray的长度,因此会降低效率,尤其myarray不是array而是HTMLCollection时。HTMLCollection对象如:
document.getElementsByName()
document.getElementsByClassName()
document.getElementsByTagName()
document.images??? ??? // 所有的image对象
document.links??? // 所有的a对象
document.forms??? // 所有的form对象
document.forms[0].elements??? ??? //第一个form对象的所有的fields

因为collection是动态查询的,每次访问任何collection的legth,都会查询动态DOM(live Documnet); 通常对DOM的操作都是很昂贵的。
好的做法:缓存collection的legth
for (var i = 0, max = myarray.length; i < max; i++) {
// do something with myarray[i]
}
For循环微优化(micro-optimizations)
循环变量倒计数到0:通常与0作比较比与array的length作比较的效率要高
第一种:
var i, myarray = [];
for (i = myarray.length; i--;) {
// do something with myarray[i]
}
第二种使用while:
var myarray = [],
i = myarray.length;
while (i--) {
// do something with myarray[i]
}
?
for...in 循环(enumeration) 遍历对象properties
方法hasOwnProperty()用于过滤或筛选proerties.
例:
// the object
var man = {
hands: 2,
legs: 2,
heads: 1
};
// somewhere else in the code
// a method was added to all objects
if (typeof Object.prototype.clone === "undefined") {
Object.prototype.clone = function () {};
}

// 1.
// for-in loop
for (var i in man) {
if (man.hasOwnProperty(i)) { // filter
console.log(i, ":", man[i]);
}
}
/*
result in the console
hands : 2
legs : 2
heads : 1
*/
// 2.
// antipattern:
// for-in loop without checking hasOwnProperty()
for (var i in man) {
console.log(i, ":", man[i]);
}
/*
result in the console
hands : 2
legs : 2
heads : 1
clone: function()
*/
另一种:使用hasOwnProperty()的call过滤继承自原型的方法与属性的
for (var i in man) {
if (Object.prototype.hasOwnProperty.call(man, i)) { // filter
console.log(i, ":", man[i]);
}
}
使用局部变量缓存Object.prototype.hasOwnProperty
var i,
hasOwn = Object.prototype.hasOwnProperty;
for (i in man) {
if (hasOwn.call(man, i)) { // filter
console.log(i, ":", man[i]);
}
}

?
Switch
var inspect_me = 0,
result = '';
switch (inspect_me) {
case 0:
result = "zero";
break;
case 1:
result = "one";
break;
default:
result = "unknown";
}

JavaScript 在作比较时默认的作类型转换。
false == 0 或 "" == 0 返回true
避免默认的类型转换,使用===和!==对比较的数据进行类型和值的进行比较
var zero = 0;
if (zero === false) {
// not executing because zero is 0, not false
}
// antipattern
if (zero == false) {
// this block is executed...
}

避免使用eval() ,安全性差,使用[]访问动态properties更好更简单
eval() is evil (邪恶的, 带来麻烦的, 不幸的, 有害的, 诽谤的,邪恶, 不幸, 罪恶)
// antipattern
var property = "name";
alert(eval("obj." + property));

// preferred
var property = "name";
alert(obj[property]);

Ajax返回值是json时,可以使用如下代码解析json:(摘自JQuery)
// Try to use the native JSON parser first
return window.JSON && window.JSON.parse ?
??? ??? ??? ??? window.JSON.parse( data ) :
??? ??? ??? ??? (new Function("return " + data))();
或者直接使用JQuery的parseJSON函数

使用字符串给setInterval(), setTimeout() 和Function()的constructor传值,和使用eval()是一样的,应该避免使用。
// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);
// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
myFunc(1, 2, 3);
}, 1000);

如果不得的使用eval,可以使用new Function()代替(例如上面Jquery解析json),它是在局部的函数范围内被执行的,因此在代码中使用var定义的变量被执行时,不会变成全局变量。
另一种防止自动变成全局变量的方法是包装(使用immediate function)一下eval()
console.log(typeof un); // "undefined"
console.log(typeof deux); // "undefined"
console.log(typeof trois); // "undefined"
var jsstrin