参考文章:
理解 js的作用域--Seven
深入理解javascript原型和闭包(14)——从【自由变量】到【作用域链】--王福明
一、JavaScript 作用域
1.在 JavaScript 中, 对象和函数同样也是变量。
2.在 JavaScript 中, 作用域为可访问变量,对象,函数的集合。
3.JavaScript 函数作用域: 作用域在函数内修改。
4.只有全局作用域和函数作用域,并没有块作用域,
for(var i =0;i<10;i++){
}
console.log(i)//10
当然我们可以实现块作用域的功能。看下面代码:
(function(){
for(var i =0;i<10;i++){
}
})()
console.log(i)//报错:i未定义
这种写法叫做立即调用函数表达式(IIFE),这其实就创建了一个局部作用域,该作用域声明的变量只有在该块内有效,外部访问不了。这种写法的好处就是可以做到不污染全局变量。
5.ES6中的作用域
在ES6中,用let替换了var的声明,不过为了兼容ES5你还是可以使用以前的var。
let为js添加了新的作用域就是块作用域。
{
let i=1000;
var j=1000;
}
console.log(j);//1000
console.log(i);//报错:i未定义
而且使用let声明的变量,在声明是不可以使用的。
a=3
let a =10;
alert(a)//报错:a未定义
只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。ES6明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。当然他解释为什么的时候提到了暂时性死区,建议看一下阮一峰的ES6 http://es6.ruanyifeng.com/#docs/let
二、JavaScript 局部作用域
1.变量在函数内声明,变量为局部作用域。
2.局部变量:只能在函数内部访问。
function fun() {
var aa = "aa";
console.log(aa);
}
fun();//aa
console.log(aa);//报错:aa未定义
三、
JavaScript 全局变量
1.变量在函数外定义,即为全局变量。
2.全局变量有 全局作用域: 网页中所有脚本和函数均可使用。
var aa = " aaa";
function fun() {
console.log(aa);
}
fun();//aaa
3.如果变量在函数内没有声明(没有使用 var 关键字),该变量为全局变量。
(我认为这样写相当于 ”this.变量”的写法, 而this指向全局对象window,所以变量就绑定在全局对象上。而在js严格模式下,禁止this关键字指向全局对象。)
"use strict"
function fun1(){
aa="aa"
}
fun1();//报错: aa未定义
console.log(aa);
以下实例中 aa/bb在函数内,但是为全局变量。
function fun1(){
aa="aa"
(function fun2(){
bb="bb"
})();
console.log(bb);
}
fun1();//aa
console.log(aa);//aa
console.log(bb);//bb
四、JavaScript 变量生命周期
1.JavaScript 变量生命周期在它声明时初始化。
2.局部变量在函数执行完毕后销毁。
3.全局变量在页面关闭后销毁。
五、自由变量的取值 var x=10;
function fun(){
var b=20;
console.log(x+b);
}
2.自由变量取值
var x=10;
function fun1(){
console.log(x);
}
function fun2(f){
var x=20;
(function(){
f();//10,而不是20
})();
f();//10,而不是20
}
fun2(fun1);
对于本文第一段代码,在fn函数中,取自由变量x的值时,要到哪个作用域中取?——要到创建fn函数的那个作用域中取——无论fn函数将在哪里调用。