JavaScript作用域
简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。
<script type="text/javascript">
var v = 20; //定义了一个全局变量,那么这个变量在当前的JS脚本部分都可以
function(){
var v = 10;//在函数里面定义了一个局部变量,在函数外部无法访问到这个局部变量
}
alert(v); //弹出:20
访问到。
</script>
<script type="text/javascript">
//因为v是全局变量,所以这里仍然可以访问到。
alert(v); //弹出:20
</script>
在函数内部所有末定义直接赋值的变量自动声明为拥有全局作用域,例如:
function sum(){
var v = 20;
b = 10;
alert(v);
}
sum(); //20
alert(b); //10
alert(v); //脚本错误
JavaScript中有没有块级作用域?
<script type="text/javascript">
var m = 5;
if(m == 5){
var n = 10;
}
alert(n); //输出10- JavaScript的作用域是按照函数来划分的JavaScript没有块级作用域
</script>
当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充。
function add(num1,num2) {
var sum = num1 + num2;
return sum;
}
在函数add创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,
我们可以看到,由于函数作用域的特性,局部变量在整个函数体始终是由定义的,我们可以将变量声明”提前“到函数体顶部,同时变量初始化还在原来位置。
var scope="global";
function t(){
console.log(scope); // 是"undefined",而不是 "global"
var scope="local"
console.log(scope); //是"local"
}
t();
当执行s时,将创建函数s的执行环境(调用对象),并将该对象置于链表开头,然后将函数t的调用对象链接在之后,最后是全局对象。然后从链表开头寻找变量name,很明显name是"slwy",但执行ss()时,name是 tlwy。
name="lwy";
function t(){
var name="tlwy";
function s(){
var name="slwy";
console.log(name);
}
function ss(){
console.log(name);
}
s();
ss();
}
t();
闭包
闭包是指有权访问另一个函数作用域中的变量的函数
<script type="text/javascript">
function createSumFunction(num1, num2){
return function () {
return num1 + num2;
};
}
var sumFun = createSumFunction(3, 4);
var sum = sumFun();
alert(sum);
</script>
闭包中使用的局部变量的值,一定是局部变量的最后的值。
function a(){
var n = 0;
function inc() {
n++;
console.log(n);
}
inc();
inc();
}
a(); //控制台输出1,再输出2
常见的陷阱,以为输出 0~9 ,万万没想到输出10个10
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
var funcs = createFunctions();
for (var i=0; i < funcs.length; i++){
console.log(funcs[i]());
}
上面的解释就是:
var result = new Array(), i;
result[0] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
result[1] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
...
result[9] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
i = 10;
funcs = result;
result = null;
console.log(i); // funcs[0]()就是执行 return i 语句,就是返回10
console.log(i); // funcs[1]()就是执行 return i 语句,就是返回10
...
console.log(i); // funcs[9]()就是执行 return i 语句,就是返回10
闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗!另外使用闭包也要注意变量的值是否符合你的要求,因为他就像一个静态私有变量一样。