首先,词法作用域又叫静态作用域,区别于静态作用域。因为js的作用域在词法解析阶段就已经确定了,所以js的作用域叫词法作用域。
1.作用域
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();
a.动态作用域:区别于静态作用域,即在函数调用时才决定作用域,例如上面的代码如果按照动态作用域来解析,那么foo()函数首先检查自身没有value的值,他就会从调用函数的作用域,即bar()中查找值,于是便会打印出2。
b.词法作用域:对于js来说,执行上述代码时,首先会检查自身,然后便会从函数定义的外层,打印全局变量的value值。换言之,js在解析函数时便已经将对于value符号的引用定义到全局变量的value中。
c.函数作用域:首先这个是js语言区别于自身区别于块级作用域的特性,学过C语言都会知道我们通过{}来表示一个代码块,对于这个块中定义的变量不能被块以外的代码调用。而对于js来说,一个函数内定义的变量在一个函数中都可以被访问,这和他的变量声明提前特性有关。
d.全局作用域:这个也是一个区别于函数作用域的概念,后面我们会说到作用域链,全局作用域就是作用域链上最深的活动对象,所有的全局变量都以属性的方式被保存在全局作用域中。
2.声明提前
a.变量声明提前
var foo = function () {
console.log('foo1');
}
foo(); // foo1
var foo = function () {
console.log('foo2');
}
foo(); // foo2
上面的例子涉及到关于js的变量声明提前,即js引擎预编译的时候会先置顶对于变量的声明,注意只是声明而不包括对于变量的赋值和操作。
实际代码执行顺序:
var foo;
function foo() {
console.log('foo1');
}
foo(); // foo1
function foo() {
console.log('foo2');
}
foo(); // foo2
b.函数声明提前
function foo() {
console.log('foo1');
}
foo(); // foo2
function foo() {
console.log('foo2');
}
foo(); // foo2
函数声明提前也是函数声明的一个特性,类似于变量声明提前,上述代码实际执行顺序:
function foo() {
console.log('foo1');
}
function foo() {
console.log('foo2');
}
foo(); // foo2
foo(); // foo2