提前声明hoisting
JavaScript的函数作用域是指在函数内声明的所有变量在函数体内始终是可见的。所以有时变量在声明之前就可以使用了
function test() { alert(ss); var ss = 123; } test();
这段代码的执行结果是undefined,并未发生不可预期的错误。
原因是因为javascript函数中所有的变量的声明都被提前至函数的顶部,其实这段代码相当
function test() { var ss; alert(ss); ss = 123; } test();
再看一个例子
var ss="123"; function test() { alert(ss);
//.... var ss="321"; }
可以猜测一下这个函数test的执行结果,理解了声明提前立刻就能知道这个的结果还是undefined,因为它的执行结果等价于
var ss="123"; function test() { var ss; alert(ss); ss="321"; }
声明提前导致了局部变量ss的值覆盖了全局的变量ss的值,因此在执行alert的时候ss的值还是undefined。
注意:声明提前并不会赋值提前,注意上述红色代码的位置并没有改变
由此而引起的代码规范:
在函数内部中,最好将函数的变量声明放在函数体的顶部,养成这样的好习惯可以避免因为变量声明提前而导致的错误。请看代码
function scroll() { var em, i = 0, arr1 = document.getElementsByTagName(‘span‘), arr2 = document.getElementsByTagName(‘label‘), text = [], txt; for (; i < arr1.length; i++) { txt = arr1[i].innerText; text.push(txt ); } i = 0; for (; i < arr2.length; i++) { text.push(arr2[i]); } return text; }
可以看到上述代码中变量的声明全部放在函数顶部,推荐这种写法。
示例中还将for循环的变量声明也提取出来了,这样多个循环可以使用这同一个变量。为什么要这么做呢?请看代码:
function scroll() { for(var i=0;i<10;i++); for(var j=0;j<10;j++); alert(i); alert(j); }
细心的人应该能猜到,上述alert的结果都是10。这都要源自于JavaScript没有块级作用域。
而i,j变量均没有经过垃圾回收机制进行回收,除非函数返回到上一层的执行环境中才有可能将i,j释放。显然想比较而言,用同一个变量来实现多个循环的比两个变量要好。
实际开发过程中,经常性的注意变量的释放,作用域等等,细心考虑,有助于提高代码的执行效率跟内存的使用率。