编写高质量js要点--读汤姆大叔博客笔记

全局变量的问题

  • javasript有隐含的全局概念,意味着不声明的任何变量都会成为一个全局对象属性(隐式全局变量),** 我们应始终使用var声明变量**
  • 使用任务链进行部分var声明会创建隐式全局变量
// 反例,勿使用 
function foo() {
   var a = b = 0;
   // ...
}

a是本地变量但b是全局变量

忘记var的副作用

  • 隐式全局变量和明确定义的全局变量间有些小的差异,就是通过delete操作符让变量未定义的能力。
    • 通过var创建的全局变量(任何函数之外的程序中创建)是不能被删除的
    • 无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的。
/ 定义三个全局变量
var global_var = 1;
global_novar = 2; // 反面教材
(function () {
   global_fromfunc = 3; // 反面教材
}());

// 试图删除
delete global_var; // false
delete global_novar; // true
delete global_fromfunc; // true

// 测试该删除
typeof global_var; // "number"
typeof global_novar; // "undefined"
typeof global_fromfunc; // "undefined"

这表明,在技术上,隐式全局变量并不是真正的全局变量,但它们是全局对象的属性。属性是可以通过delete操作符删除的,而变量是不能的

访问全局变量

var global=(function(){
    return this;
})();

单var形式

function func() {
   var a = 1,
       b = 2,
       sum = a + b,
       myobject = {},
       i,
       j;
   // function body...
}

预解析:var散布问题

  • 函数中的变量提升,在js中,你可以在函数的任何位置声明多个var语句,并且它们就像在函数顶部声明一样发挥作用
// 反例
myname = "global"; // 全局变量
function func() {
    alert(myname); // "undefined"
    var myname = "local";
    alert(myname); // "local"
}
func();

第一个弹出的是“undefined”,第二个弹出是“local”,上面代码执行行为如下:

myname = "global"; // global variable
function func() {
   var myname; // 等同于 -> var myname = undefined;
   alert(myname); // "undefined"
   myname = "local";
   alert(myname); // "local"}
func();

for循环

// 次佳的循环
for (var i = 0; i < myarray.length; i++) {
   // 使用myarray[i]做点什么
}
  • 这种形式的循环的不足在于每次循环时都要获取数组的长度,尤其是当myarray不是一个数组而是DOM 方法返回的对象,这意味着每次访问长度,都要实时查询DOM,方法:
  1. 缓存数组或集合的长度
function looper() {
   var i = 0,
        max,
        myarray = [];
   // ...
   for (i = 0, max = myarray.length; i < max; i++) {
      // 使用myarray[i]做点什么
   }
}
  • 使用i=i+1或者i+=1来替换i++
  • 还有两种变化形式:少了一个变量(无max),向下数到0,通常比较快
//第一种变化的形式:

var i, myarray = [];
for (i = myarray.length; i–-;) {
   // 使用myarray[i]做点什么
}

//第二种使用while循环:

var myarray = [],
    i = myarray.length;
while (i–-) {
   // 使用myarray[i]做点什么
}

for-in循环

  • 最好数组使用正常的for循环,对象使用for-in循环
  • 有个很重要的hasOwnProperty()方法,当遍历对象属性的时候可以过滤掉从原型链上下来的属性
// 对象
var man = {
   hands: 2,
   legs: 2,
   heads: 1
};

// 在代码的某个地方
// 一个方法添加给了所有对象
if (typeof Object.prototype.clone === "undefined") {
   Object.prototype.clone = function () {};
}

推荐阅读更多精彩内容