【javascript知识进阶】变量声明和提升规则和自定义作用域

来源:互联网 发布:交换机基于mac的acl 编辑:程序博客网 时间:2024/06/11 07:41

1.作用域

尽管 JavaScript 支持一对花括号创建的代码段,但是并不支持块级作用域; 而仅仅支持 函数作用域。

function test() { // 一个作用域    for(var i = 0; i < 10; i++) { // 不是一个作用域        // count    }    console.log(i); // 10}

2.变量声明提升

JavaScript 会提升变量声明。这意味着 var 表达式和 function 声明都将会被提升到当前作用域的顶部。

bar();var bar = function() {};var someValue = 42;test();function test(data) {    if (false) {        goo = 1;    } else {        var goo = 2;    }    for(var i = 0; i < 100; i++) {        var e = data[i];    }}

上面代码在运行之前将会被转化。JavaScript 将会把 var 表达式和 function 声明提升到当前作用域的顶部。

// var 表达式被移动到这里var bar, someValue; // 缺省值是 'undefined'// 函数声明也会提升function test(data) {    var goo, i, e; // 没有块级作用域,这些变量被移动到函数顶部    if (false) {        goo = 1;    } else {        goo = 2;    }    for(i = 0; i < 100; i++) {        e = data[i];    }}bar(); // 出错:TypeError,因为 bar 依然是 'undefined'someValue = 42; // 赋值语句不会被提升规则(hoisting)影响bar = function() {};test();

没有块级作用域不仅导致 var 表达式被从循环内移到外部,而且使一些 if 表达式更难看懂。

在原来代码中,if 表达式看起来修改了全局变量 goo,实际上在提升规则被应用后,却是在修改局部变量。

如果没有提升规则(hoisting)的知识,下面的代码看起来会抛出异常 ==ReferenceError==。

// 检查 SomeImportantThing 是否已经被初始化if (!SomeImportantThing) {    var SomeImportantThing = {};}

实际上,上面的代码正常运行,因为 var 表达式会被提升到全局作用域的顶部。

var SomeImportantThing;// 其它一些代码,可能会初始化 SomeImportantThing,也可能不会// 检查是否已经被初始化if (!SomeImportantThing) {    SomeImportantThing = {};}

如果你能理解下面函数为什么弹出==undefined==,那么大概就能理解变量声明提升规则了

var myvar = 'my value';  (function() {      alert(myvar); // undefined      var myvar = 'local value';  })(); 

3.名称解析顺序

比如,当访问函数内的 foo 变量时,JavaScript 会按照下面顺序查找:

  1. 当前作用域内是否有 var foo 的定义。
  2. 函数形式参数是否有使用 foo 名称的。
    函数自身是否叫做 foo。
  3. 回溯到上一级作用域,然后从 #1 重新开始。

4.自定义作用域

只有一个全局作用域导致的常见错误是命名冲突。

在上一篇博文中的关于for循环中定义setTimeout错误也是这个问题。

在 JavaScript中,这可以通过 ==自执行函数== 轻松解决。

(function() {    // 函数创建一个命名空间    window.foo = function() {        // 对外公开的函数,创建了闭包    };})(); // 立即执行此匿名函数

自执行函数被认为是 表达式;因此为了可调用性,它们首先会被执行。

( // 小括号内的函数首先被执行function() {}) // 并且返回函数对象() // 调用上面的执行结果,也就是函数对象

大量使用全局变量被认为是不好的习惯。这样的代码容易产生错误并且维护成本较高。

原创粉丝点击