在JS中,变量的定义并不是以代码块作为作用域的。而是以函数作为作用域。也就是说,如果变量是在某个函数中定义的,那么它在函数以外的地方是不可见的。
在JS总,全局变量指的是定义在所有函数之外的变量,局部变量则是定义在函数内的变量,函数内的代码可以调用全局变量,反之则不行。
比如说:
```
>>> var global = 1;
undefined
>>> function f(){
... var local = 2;
... global++;
... return global;
... }
undefined
>>> f();
2
>>> f();
3
>>> local;
Exception: ReferenceError: Can't find variable: local
```
- 函数f()可以访问变量global
- 在函数f()以外,变量local是不存在的
如果我们声明一个变量时没有使用var语句,默认是全局变量
```
>>> function f(){
... local = 2;
... }
undefined
>>> local;
Exception: ReferenceError: Can't find variable: local
>>> f();
undefined
>>> local;
2
```
在实际开发中:
- 尽量将全局变量的数量减到最低,以避免命名冲突。如果有两个人在同一段脚本的不同函数中使用了相同的全局变量名,就很容易导致不可预测的结果和难以察觉的bug。
- 最哈总是使用var语句来声明变量
- 可以考虑使用“单一 var”模式,也就是在函数体内第一行使用var来定义这个作用域中的所需的变量
变量提升
```
var a = 123;
function f(){
alert(a);
var a = 1;
alert(a);
}
f();
```
第一次弹出undefined,第二次弹出1.
因为函数域使用优先于全局域,所以局部变量a会覆盖所有与他同名的全局变量,尽管alert()第一次被调用时,a还没有被正式定义,但该变量本身已经存在与本地空间了。这种特殊的现象我们叫做提升(hoisting)。
这个概念很重要,也就是说,当JS执行过程中进入新的函数时,这个函数内被声明的所有变量都会被提升。
被提升的只有变量的声明,与之相关的赋值操作并不会被提升。比如说刚才的demo中,局部变两本书被提升到了函数最开始处,但并没有在开始处就被赋值1。
上面的demo可以改成:
```
var a = 123;
function f(){
var a;
alert(a);
var a = 1;
alert(a);
}
f();
```
- 前言
- 第1章 面向对象的JavaScript
- 1.6 面向对象的程序设计
- 1.6.1 对象
- 1.6.2 类
- 1.6.3 封装
- 1.6.4 聚合
- 1.6.5 继承
- 1.6.6 多态
- 1.7 OOP小结
- 第2章 基本数据类型、数组、循环及条件表达式
- 2.1 变量
- 2.2 操作符
- 2.3 基本数据类型
- 2.3.1 查看类型操作符
- 2.3.2 数字
- 2.3.3 字符串
- 2.3.3.1 字符串转换
- 2.3.3.2 特殊字符串
- 2.3.4 布尔值
- 2.3.4.1 逻辑运算符
- 2.3.4.2 操作符优先级
- 2.3.4.3 惰性求值
- 2.3.4.4 比较运算符
- 2.3.5 undefined与null
- 2.4 基本数据类型综述
- 2.5 数组
- 2.5.1 增加、更新数组元素
- 2.5.2 删除元素
- 2.5.3 数组的数组
- 2.6 条件与循环
- 2.6.1 if条件表达式
- 2.6.1.1 三元运算符
- 2.6.1.2 switch语句
- 2.6.2 else语句
- 2.6.3 代码块
- 2.6.4 检查变量是否存在
- 2.6.5 循环
- 2.6.5.1 while循环
- 2.6.5.2 do-while循环
- 2.6.5.3 for循环
- 2.6.5.4 for-in循环
- 2.7 注释
- 第2章 面试题
- 第2章 面试题及解答
- 第3章 函数
- 主要内容
- 3.1 什么是函数
- 3.1.1 调用函数
- 3.1.2 参数
- 3.2 预定义函数
- 3.2.1 parseInt
- 3.2.2 parseFloat
- 3.2.3 isNaN
- 3.2.4 ifFinite
- 3.2.5 URI的编码与反编码
- 3.2.6 eval
- 3.2.7 alert
- 3.3 变量的作用域
- 3.4 函数也是数据
- 3.4.1 匿名函数
- 3.4.2 回调函数
- 3.4.3 回调示例
- 3.4.4 既时函数
- 3.4.5 内部(私有)函数
- 3.4.6 返回函数的函数
- 3.4.7 能重写自己的函数
- 3.5 闭包
- 3.5.1 作用域链
- 3.5.2 利用闭包突破作用域链
- 3.5.3 getter与setter
- 3.5.4 迭代器
- 第3章 面试题
- 第3章 面试题及解答
- 第4章 对象
- 4.1 从数组到对象
- 4.1.1 元素、属性、方法与成员
- 4.1.2 哈希表、关联型数组
- 4.1.3 访问对象属性
- 4.1.4 调用对象方法
- 4.1.5 修改属性与方法
- 4.1.6 使用this值
- 4.1.7 构造器函数
- 4.1.8 全局对象
- 4.1.9 构造器属性
- 4.1.10 instanceof操作符
- 4.1.11 返回对象的函数
- 4.1.12 传递对象
- 4.1.13 比较对象
- 4.1.14 Webkit控制台中的对象
- 4.2 内建对象
- 4.2.1 Object
- 4.2.2 Array
- 4.2.3 Function
- 第8章 编程模式与设计模式
- 8.1 编程模式
- 8.1.1 行为隔离
- 8.1.2 命名空间