参考自汤姆大叔“深入学习JavaScript系列”。http://www.cnblogs.com/TomXu/archive/2011/12/28/2286877.html 1、全局变量 全局变量
参考自汤姆大叔“深入学习JavaScript系列”。http://www.cnblogs.com/TomXu/archive/2011/12/28/2286877.html
1、全局变量
- 全局变量就是在任何函数外面声明的或是未声明直接简单引用的。
- 不声明的任何变量都会成为一个全局对象属性。
function sum(x,y){ result = x + y; return result;}
此段代码中result为全局变量。要让全局变量少的法则是始终使用var声明变量。
隐式全局变量和明确定义的全局变量差异(通过delete操作符让变量未定义):
- 通过var创建的全局变量(任何函数之外的程序中创建)是不能被删除的。
- 无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的。(在技术上,隐式全局变量并不是真正的全局变量,它们是全局对象的属性,属性是可以通过delete操作符删除的,而变量不能。)
var global_var = 1;global_novar = 2;(function(){ global_fromfunc = 3;}());delete global_var; //truedelete global_novar; //falsedelete global_fromfunc; //falseconsole.log(typeof global_var); //numberconsole.log(typeof global_novar); //undefinedconsole.log(typeof global_fromfunc); //undefined
2、使用单var形式(使用一个var语句声明多个变量,并以逗号分隔)
- 提供了一个单一的地方去寻找功能所需要的所有局部变量;
- 防止变量在定义之前使用的逻辑错误;
- 帮助记住声明的全局变量;
- 少代码
3、for循环
// 次佳循环for(var i = 0;i < myarray.length; i++){ //代码块}
不足: 每次循环的时候数组的长度都要去获取,尤其当myarray不是数组,而是Dom操作 HTMLCollection对象的时候。
//缓存数组或集合的长度是较好的形式for(var i = 0,max = myarray.length; i < max; i++){ //代码块}
在上面的循环中,只检索了一次长度值。
4、for-in循环:用在非数组对象的遍历上,使用for-in进行循环也被称为“枚举”。
hasOwnProperty():当遍历对象属性的时候可以过滤掉从原型链上下来的属性。
var man = { hands: 2, legs: 2, heads: 1};if(typeof Object.prototype.clone === 'undefined'){ Object.prototype.clone = function(){};}//for-in循环,hasOwnProperty()过滤原型属性for (var i in man){ if(man.hasOwnProperty(i)){ //过滤clone()方法 console.log(i, ':', man[i]); }}//不过滤for (var i in man){ console.log(i, ':', man[i]);}//使用hasOwnProperty()取消Object.prototype上的方法for (var i in man){ if(Object.prototype.hasOwnProperty.call(man, i)){ console.log(i, ':', man[i]); }}//局部变量“缓存”var i, hasOwn = Object.prototype.hasOwnProperty;for(i in man){ if(hasOwn.call(man, i)){ console.log(i, ':', man[i]); }}
5、避免隐式类型转换
JavaScript的变量在比较的时候会隐式类型转换。这就是为什么一些诸如:false == 0 或 “” == 0 返回的结果是true。为避免引起混乱的隐含类型转换,在你比较值和表达式类型的时候始终使用===和!==操作符。
var zero = 0;if (zero === false) { // 不执行,因为zero为0, 而不是false}// 反面示例if (zero == false) { // 执行了...}
6、避免eval()
使用eval()也带来了安全隐患,因为被执行的代码(例如从网络来)可能已被篡改。这是个很常见的反面教材,当处理Ajax请求得到的JSON 相应的时候。
// 反面示例var property = "name";alert(eval("obj." + property));// 更好的var property = "name";alert(obj[property]);
同样重要的是要记住,给setInterval(), setTimeout()和Function()构造函数传递字符串,大部分情况下,与使用eval()是类似的,因此要避免。
// 反面示例setTimeout("myFunc()", 1000);setTimeout("myFunc(1, 2, 3)", 1000);// 更好的setTimeout(myFunc, 1000);setTimeout(function () { myFunc(1, 2, 3);}, 1000);
使用新的Function()构造就类似于eval(),应小心接近。这可能是一个强大的构造,但往往被误用。如果你绝对必须使用eval(),你 可以考虑使用new Function()代替。有一个小的潜在好处,因为在新Function()中作代码评估是在局部函数作用域中运行,所以代码中任何被评估的通过var 定义的变量都不会自动变成全局变量。另一种方法来阻止自动全局变量是封装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); // numberconsole.log(typeof deux); // "undefined"console.log(typeof trois); // "undefined"
eval()和Function构造不同的是eval()可以干扰作用域链,而Function()更安分守己些。不管你在哪里执行 Function(),它只看到全局作用域。所以其能很好的避免本地变量污染。在下面这个例子中,eval()可以访问和修改它外部作用域中的变量,这是 Function做不来的(注意到使用Function和new Function是相同的)。
(function () { var local = 1; eval("local = 3; console.log(local)"); // logs "3" console.log(local); // logs "3"}());(function () { var local = 1; Function("console.log(typeof local);")(); // logs undefined}());