【javascript知识进阶】变量声明和提升规则和自定义作用域
2017-08-23 09:53
615 查看
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 会按照下面顺序查找:当前作用域内是否有 var foo 的定义。
函数形式参数是否有使用 foo 名称的。
函数自身是否叫做 foo。
回溯到上一级作用域,然后从 #1 重新开始。
4.自定义作用域
只有一个全局作用域导致的常见错误是命名冲突。在上一篇博文中的关于for循环中定义setTimeout错误也是这个问题。
在 JavaScript中,这可以通过 ==自执行函数== 轻松解决。
(function() { // 函数创建一个命名空间 window.foo = function() { // 对外公开的函数,创建了闭包 }; })(); // 立即执行此匿名函数
自执行函数被认为是 表达式;因此为了可调用性,它们首先会被执行。
( // 小括号内的函数首先被执行 function() {} ) // 并且返回函数对象 () // 调用上面的执行结果,也就是函数对象
大量使用全局变量被认为是不好的习惯。这样的代码容易产生错误并且维护成本较高。
相关文章推荐
- Javascript 作用域和变量提升
- javascript作用域和声明提升
- javascript的变量声明和函数声明提升
- JavaScript中作用域和作用域链的简单理解(变量提升)
- JavaScript机制:变量&函数声明提升的那些事
- javascript作用域之声明提升
- Javascript 作用域和变量提升
- 理解Javascript_15_作用域分配与变量访问规则,再送个闭包
- javascript的变量声明和函数声明提升
- JavaScript作用域与声明提升【翻译】
- javascript中变量声明提升(Hoisting)
- JavaScript的函数,声明变量和作用域等7个基础知识点总结
- javascript的变量声明提升
- JavaScript中的作用域与函数和变量声明的提升
- JavaScript中变量和函数声明的提升
- JavaScript 函数总体概述(函数声明/参数传递/返回值/加载/变量和作用域/变量声明提升/匿名函数/回调函数)
- javascript变量声明提升
- JavaScript 中的执行环境、作用域(scope)以及变量提升(hoisting)
- 浅谈JavaScript中变量和函数声明的提升