文章目录
  1. 1. JavaScript系列——作用域和作用域链
    1. 1.1. 作用域
    2. 1.2. 作用域链
    3. 1.3. 预编译

JavaScript系列——作用域和作用域链

作用域

JavaScript通过函数管理作用域。在函数内部声明的变量只在这个函数内部,函数外面不可用。另一方面,全局变量就是在任何函数外面声明的或是未声明直接简单使用的。在实现项目中,为了避免全局变量冲突导致,我们应该尽量的减少全局变量的使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function sum(x, y) {
// 不推荐写法: 隐式全局变量
result = x + y; //优化:var result = x + y; 使用var
return result;
}

// 反例,勿使用
function foo() {
//相当于:
//var a = 0 ;
//b = 0; 隐式全局变量
var a = b = 0;
// ...
}

隐式全局变量和明确定义的全局变量间有些小的差异,就是通过delete操作符让变量未定义的能力。

  • 通过var创建的全局变量(任何函数之外的程序中创建)是不能被删除的。
  • 无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的。

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 定义三个全局变量
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"

Javascript没有代码块作用域的概念,局部作用域是针对函数来说的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function fun()
{

for( var i = 0 ; i < 10 ; i++)
{}
//如果在Java中i此时应当属于未声明的变量,但是js中i的作用域依然存在
console.log(i);//10

if(true)
{
var b = "helloworld";
}
console.log(b);//helloworld
}
fun();

作用域链

在JavaScript中,函数也是对象,实际上,JavaScript里一切都是对象。函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var name="hello";
function s(){
var name="hello1";
function ss(){
var name="hello2";
console.log(name);
}
function sss(){
console.log(name);
}
ss();
sss();
}
s();

当执行到ss()的时候,创建ss的运行期上下文对象,并将它放入到作用域链表的头部,之后还有s()的运行期上下文对象,之后就是全局对象,所有再查找name的时候,先从链表头部中查找,也就是会输出“hello2”;当执行到sss()的时候,在sss的运行期上下文中找不到name就会继续从下一个找,也就是s()的运行期上下文,也就会输出“hello1”。

预编译

JavaScript解析过程可以分为编译和执行两个阶段。编译也就是我们常说的JavaScript预处理(即预编译)

  • 先预定义var变量,在预定义function函数
  • 变量的预定义只做变量声明,不做初始化,此时值为undefined
  • function函数也做变量声明,值初始化为函数体
  • 匿名函数不做预编译
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
alert(om);       // 显示 undefined
var om = 'abc';
alert(om); // 显示 abc

alert(sum);
/*
返回:
function sum(a,b){
return a+b;
}
*/

function sum(a,b){
return a+b;
}

alert(1,2); //返回:3
文章目录
  1. 1. JavaScript系列——作用域和作用域链
    1. 1.1. 作用域
    2. 1.2. 作用域链
    3. 1.3. 预编译