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

JS 代码模式(2)

hasOwnProperty()


当遍历一个对象的属性时,可以使用hasOwnProperty方法进行过滤。例如:

// the object
var man = {
    hands: 2,
    legs: 2,
    heads: 1
};
// 为object增加clone方法
if (typeof  Object.prototype.clone === "undefined") {
    Object.prototype.clone = function () {};
}

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
*/

// 反模式
// 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()
*/

?

如果man对象有hasOwnProperty同名方法会出现问题,利用如下方法解决

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

?

也可以把for与if写在一起

// Warning: doesn't pass JSLint
var i,
    hasOwn = Object.prototype.hasOwnProperty;
for (i in man) if (hasOwn.call(man, i)) { // filter
    console.log(i, ":", man[i]);
}

?
为build-in prototype增加方法

?

?1. It’s expected that future ECMAScript versions or JavaScript implementations will
?implement this functionality as a built-in method consistently. For example, you
?can add methods described in ECMAScript 5 while waiting for the browsers to
?catch up. In this case you’re just defining the useful methods ahead of time.
?2. You check if your custom property or method doesn’t exist already—maybe al-
?ready implemented somewhere else in the code or already part of the JavaScript
?engine of one of the browsers you support.
?3. You clearly document and communicate the change with the team.

? 采用如下模式:

if (typeof Object.protoype.myMethod !== "function") {
    Object.protoype.myMethod = function () {
        // implementation...
    };
}

?

避免隐式的转换
当比较两个变量值时JS会有一个隐式转换,可能会导致和预期结果不一致的情况,例如:

var zero = 0;
if (zero === false) {
    不会执行到此,因为zero是零不是false
}

// antipattern
if (zero == false) {
    会执行到此.
}

?
因此为了避免这种隐式的转换应该采用 === 和? !==

?

避免使用 eval()
尽量避免使用eval方法,它可以把任意的字符串作为JS代码执行,如果代码是运行时动态生成的应该有更好的方法去实现,例如,用方括号去访问动态的属性:

// antipattern
var property = "name";
alert(eval("obj." + property));
// preferred
var property = "name";
alert(obj[property]);

?
使用eval()有安全的隐患,因为你可能执行一些已经被篡改了的代码,还有重要一点要注意当向setInterval,setTimeout传字符串和方法,在大多
数情况下类似于使用了eval()应此也应避免,在这种情况下,JS仍然把你传过来的字符串当作代码解析和执行。

// antipatterns
setTimeout("myFunc()", 1000);
setTimeout("myFunc(1, 2, 3)", 1000);
// preferred
setTimeout(myFunc, 1000);
setTimeout(function () {
    myFunc(1, 2, 3);
}, 1000);

?
使用new Function()也类似于eval方法应该也要注意,如果你非要使用eval,可以使用new Function()来代替,因为在new Function()中被解释的代码
将运行在function的作用域中,不会变量全局变量,另外还有一种方法可以阻止eval自动声明为全局变量,在立即函数里调用

console.log(typeof un);    // "undefined"
console.log(typeof deux);  // "undefined"
console.log(typeof trois); // "undefined"
var jsstring = "var un = 1; console.log(un);";
eval(jsstring); // logs "1"
jsstring = "var deux = 2; console.log(deux);";
new Function(jsstring)(); // logs "2"
jsstring = "var trois = 3; console.log(trois);";
(function () {
    eval(jsstring);
}()); // logs "3"
console.log(typeof un);    // "number"
console.log(typeof deux);  // "undefined"
console.log(typeof trois); // "undefined"

?

另外处理json的响应时应避免使用:
var str = "{name:'zhangxing'}";
var obj = eval("(" + str + ")");
应该用j