执行环境
执行环境是JavaScript中最重要的一个概念。执行环境定义了变量和函数访问其它数据的规范行为。
全局执行环境是最外围的一个执行环境。在Web 浏览器中,全局执行环境是window对象,所有的全局变量和函数都是作为window对象的属性和方法创建的。
每个函数都有自己的执行环境,当函数执行时,函数的执行环境就会被推入一个环境栈中。而当函数执行后,环境会被栈弹出。
作用域
当代码在环境中执行时,会创建变量对象的一个作用域链。
作用域链的作用是对执行环境有权访问的变量和函数进行有序访问。
当JavaScript需要查找一个变量时,她会从链中第一个对象开始查找,如果对象中找不到会继续查找链上的下一个对象,以此类推。如果作用域链上没有找到就会抛出一个引用错误(ReferenceError)异常
var color = 'blue'
function changeColor(){
var anotherColor = 'red'
function swapColors(){
var tempColor = anotherColor
anotherColor = color
color = tempColor
console.log('tempColor',tempColor);
}
swapColors()
console.log('anotherColor',anotherColor);
}
changeColor()
console.log('color',color);
// =>
tempColor red
anotherColor blue
color red
上面代码包含三个执行环境:全局环境,changeColor()的局部环境和swapColors()的局部环境。
全局环境可以访问变量color和函数changeColor().
changeColor()的局部环境可以访问变量anotherColor和函数swapColors(),同时还可以访问全局环境的变量color
swapColors()可以访问tempColor,以及changeColor()和全局环境中的变量。
内部环境可以通过作用域链访问所有的外部环境。但任何环境都不能通过向下搜索作用域链而进入执行环境。
函数作用域
javascript中没有块级作用域,使用的是函数作用域。函数作用域是指在函数内声明的所有变量在函数体内始终可见。
function test(o){
var i = 0 // 可在函数内访问
if(typeof o === "object" ){
var j = o // j在函数内定义了,可以在函数内任何地方访问
for (var k = 0; k < 10; k++) {
console.log(k); // 输出 0~9
}
console.log(k); // k已经定义,输出10
}
console.log(j); // j可以访问但可能没有初始化 值可能为o或者undefined
}
在这个例子中,由for循环创建的变量k即使在for循环执行完后依旧存在循环外部的环境。
声明提前
var scope = "global"
function f(){
console.log(scope); // 输出 undefined
var scope = "local" // 变量初始化赋值,但变量本身在函数体内始终定义的
console.log(scope); // 输出 local
}
等同于下面例子
function f(){
var scope // 在函数顶部声明了局部变量
console.log(scope); // 变量声明未初始化赋值,其值是 undefined
scope = "local" // 初始化赋值
console.log(scope); // 输出 local
}
将函数体内的变量声明提前至函数体顶部,变量初始化留在原来的位置
变量作用域
function add(x,y){
sum = x + y
return sum
}
var result = add(1,2)
console.log(result); // 3
这个例子中的变量sum在初始化时未使用var 关键字。于是变量sum被添加到全局环境,称为了全局变量,所以在函数外部可以访问。