一、 什么是作用域
作用域,即 变量起作用的区域。
变量定义后,可以在哪个范围内使用该变量
二、两种作用域
1.词法作用域、
2.块级作用域
块级作用域:
用一个块(代码块)结构限制变量的访问区域。
即,块内的每一段代码都有各自的作用域,变量在声明它们的代码段之外是不可见的。
代表语言: C 语言( C系,如:Java、Object-C、C#)
案例
for(var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i);
}
console.log(i);//10
三、词法作用域
概念:变量的作用范围, 在书写代码的时候就已经决定, 与运行时无关。
函数在定义它们的作用域中运行,而不是在调用它们的作用域里运行
JavaScript中只有函数才能形成作用域,因此也叫做函数作用域
案例:
// 1
function foo() {
var num = 123;
function foo() {
var num = 123;
console.log(num); //
}
foo();
foo();
console.log(num); //
变量提升后:
function foo(){
var num;
num = 123;
console.log(num); =>123
}
foo();
console.log(num);//先去当前作用域里面找,看有没有声明;因为是全局环境下,所以没有找到num,程序会报错
// 2
var scope = "global";
function foo() {
console.log(scope); //
var scope = "local";
console.log(scope); //
}
foo();
变量提升后:
var scope;
scope = "global";
function foo(){
var scope;
console.log(scope); =>先去当前作用域找变量的声明,如果没有则向上一级找,本例中,当前作用域中有声明,但是在该位置没有赋值,所以输出undefined
scope = "local";
console.log(scope); =>先去当前作用域找变量的声明,如果没有则向上一级找,有声明,并且有赋值,所以输出local
}
foo();
// 3
// 声明的变量都作为 window 全局对象的属性存在!
if("a" in window){
var a = 10; =>因为这里并不是一个作用域,所以变量会向上提升至全局环境,
}
alert(a); // ?
变量提升后
var a ;
if('a' in window){
a = 10;
}
alert(a); =>10;
if(!"a" in window){
var a = 10;
}
alert(a); // ?
var a = 10;
}
alert(a); // ?
// 4
var foo = 1;
function bar() {
if(!foo) {
var foo = 10;
}
alert(foo); //
}
var foo = 1;
function bar() {
if(!foo) {
var foo = 10;
}
alert(foo); //
}
bar();
变量提升后
var foo;
foo = 1;
function bar(){
var foo;
if(!foo){ =>foo声明未赋值,为undefined,隐式转换为false ,经过非运算符之后为true
foo = 10;
}
console.log(foo); =>因为上面条件为真,程序进入判断语句中,foo为10;所以最后输出10
}
bar();
四、变量提升和函数提升(hoisting)
- JavaScript的执行过程
JS运行的两个步骤:解析和执行
1 预解析(不是在执行代码)。 将所有的声明都加载到内存中,也就是:告诉解释器有什么东西了
2 一步一步的执行代码, 按照从上往下的顺序
- 变量提升的是:变量的声明
- 函数提升的是:整个函数
案例变式:
2 变式
if("b" in window) {
var a = 10;
}
alert(a); // ? undefined
变量提升后
var a ;
if('b' in window){
var a = 10;
}
console.log(a);
3 变式
if(true) {
function f() { alert("true"); }
} else {
function f() { alert("false"); }
}
f();// ? 不确定,会根据不同浏览器实现不同
4 变式
var f;
if(true) {
f = function () { alert("true"); }
} else {
f = function () { alert("false"); }
}
f();// true