龙盟编程博客 | 无障碍搜索 | 云盘搜索神器
快速搜索
主页 > web编程 > Javascript编程 >

编写高质量JavaScript代码的基本要点(1)(4)

时间:2013-03-06 14:58来源:未知 作者:admin 点击:
分享到:
(不)扩展内置原型((Not) Augmenting Built-in Prototypes) 扩增构造函数的prototype属性是个很强大的增加功能的方法,但有时候它太强大了。 增加内置的构造函数原型

(不)扩展内置原型((Not) Augmenting Built-in Prototypes)

扩增构造函数的prototype属性是个很强大的增加功能的方法,但有时候它太强大了。

增加内置的构造函数原型(如Object(), Array(), 或Function())挺诱人的,但是这严重降低了可维护性,因为它让你的代码变得难以预测。使用你代码的其他开发人员很可能更期望使用内置的 JavaScript方法来持续不断地工作,而不是你另加的方法。

另外,属性添加到原型中,可能会导致不使用hasOwnProperty属性时在循环中显示出来,这会造成混乱。

因此,不增加内置原型是最好的。你可以指定一个规则,仅当下面的条件均满足时例外:

◆ 可以预期将来的ECMAScript版本或是JavaScript实现将一直将此功能当作内置方法来实现。例如,你可以添加ECMAScript 5中描述的方法,一直到各个浏览器都迎头赶上。这种情况下,你只是提前定义了有用的方法。

◆ 如果您检查您的自定义属性或方法已不存在——也许已经在代码的其他地方实现或已经是你支持的浏览器JavaScript引擎部分。

◆ 你清楚地文档记录并和团队交流了变化。

如果这三个条件得到满足,你可以给原型进行自定义的添加,形式如下:

  1. if (typeof Object.protoype.myMethod !== "function") {  
  2.    Object.protoype.myMethod = function () {  
  3.       // 实现...  
  4.    };  

switch模式(switch Pattern)

你可以通过类似下面形式的switch语句增强可读性和健壮性:

  1. var inspect_me = 0,  
  2.     result = '';  
  3. switch (inspect_me) {  
  4. case 0:  
  5.    result = "zero";  
  6.    break;  
  7. case 1:  
  8.    result = "one";  
  9.    break;  
  10. default:  
  11.    result = "unknown";  

这个简单的例子中所遵循的风格约定如下:

◆ 每个case和switch对齐(花括号缩进规则除外)

◆ 每个case中代码缩进

◆ 每个case以break清除结束

◆ 避免贯穿(故意忽略break)。如果你非常确信贯穿是最好的方法,务必记录此情况,因为对于有些阅读人而言,它们可能看起来是错误的。

◆ 以default结束switch:确保总有健全的结果,即使无情况匹配。

避免隐式类型转换(Avoiding Implied Typecasting )

JavaScript的变量在比较的时候会隐式类型转换。这就是为什么一些诸如:false == 0 或 “” == 0 返回的结果是true。为避免引起混乱的隐含类型转换,在你比较值和表达式类型的时候始终使用===和!==操作符。

  1. var zero = 0;  
  2. if (zero === false) {  
  3.    // 不执行,因为zero为0, 而不是false  
  4. }  
  5.  
  6. // 反面示例  
  7. if (zero == false) {  
  8.    // 执行了...  

还有另外一种思想观点认为==就足够了===是多余的。例如,当你使用typeof你就知道它会返回一个字符串,所以没有使用严格相等的理由。然而,JSLint要求严格相等,它使代码看上去更有一致性,可以降低代码阅读时的精力消耗。(“==是故意的还是一个疏漏?”)

避免(Avoiding) eval()

如果你现在的代码中使用了eval(),记住该咒语“eval()是魔鬼”。此方法接受任意的字符串,并当作JavaScript代码来处理。当有 问题的代码是事先知道的(不是运行时确定的),没有理由使用eval()。如果代码是在运行时动态生成,有一个更好的方式不使用eval而达到同样的目 标。例如,用方括号表示法来访问动态属性会更好更简单:

  1. // 反面示例  
  2. var property = "name";  
  3. alert(eval("obj." + property));  
  4.  
  5. // 更好的  
  6. var property = "name";  
  7. alert(obj[property]); 

使用eval()也带来了安全隐患,因为被执行的代码(例如从网络来)可能已被篡改。这是个很常见的反面教材,当处理Ajax请求得到的JSON 相应的时候。在这些情况下,最好使用JavaScript内置方法来解析JSON相应,以确保安全和有效。若浏览器不支持JSON.parse(),你可 以使用来自JSON.org的库。

同样重要的是要记住,给setInterval(), setTimeout()和Function()构造函数传递字符串,大部分情况下,与使用eval()是类似的,因此要避免。在幕后,JavaScript仍需要评估和执行你给程序传递的字符串:

  1. // 反面示例  
  2. setTimeout("myFunc()", 1000);  
  3. setTimeout("myFunc(1, 2, 3)", 1000);  
  4.  
  5. // 更好的  
  6. setTimeout(myFunc, 1000);  
  7. setTimeout(function () {  
  8.    myFunc(1, 2, 3);  
  9. }, 1000); 

使用新的Function()构造就类似于eval(),应小心接近。这可能是一个强大的构造,但往往被误用。如果你绝对必须使用eval(),你 可以考虑使用new Function()代替。有一个小的潜在好处,因为在新Function()中作代码评估是在局部函数作用域中运行,所以代码中任何被评估的通过var 定义的变量都不会自动变成全局变量。另一种方法来阻止自动全局变量是封装eval()调用到一个即时函数中。

考虑下面这个例子,这里仅un作为全局变量污染了命名空间。

  1. console.log(typeof un);    // "undefined"  
  2. console.log(typeof deux); // "undefined"  
  3. console.log(typeof trois); // "undefined"  
  4.  
  5. var jsstring = "var un = 1; console.log(un);";  
  6. eval(jsstring); // logs "1"  
  7.  
  8. jsstring = "var deux = 2; console.log(deux);";  
  9. new Function(jsstring)(); // logs "2"  
  10.  
  11. jsstring = "var trois = 3; console.log(trois);";  
  12. (function () {  
  13.    eval(jsstring);  
  14. }()); // logs "3"  
  15.  
  16. console.log(typeof un); // number  
  17. console.log(typeof deux); // "undefined"  
  18. console.log(typeof trois); // "undefined" 

另一间eval()和Function构造不同的是eval()可以干扰作用域链,而Function()更安分守己些。不管你在哪里执行 Function(),它只看到全局作用域。所以其能很好的避免本地变量污染。在下面这个例子中,eval()可以访问和修改它外部作用域中的变量,这是 Function做不来的(注意到使用Function和new Function是相同的)。

  1. (function () {  
  2.    var local = 1;  
  3.    eval("local = 3; console.log(local)"); // logs "3"  
  4.    console.log(local); // logs "3"  
  5. }());  
  6.  
  7. (function () {  
  8.    var local = 1;  
  9.    Function("console.log(typeof local);")(); // logs undefined  
  10. }()); 

精彩图集

赞助商链接