上述代码,不报错而是输出 undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值。所以,相当于上述实例中,函数在“预编译”时,已经执行了var xo;所以上述代码中输出的是undefined。
注意:我们平时在声明变量时一定要注意!!!还有不要滥用全局变量(在forin循环的时候特别注意)!!!
4、词法作用域是不可逆的,我们可以从下面的例子中看到结果:
// name = undefined
var scope1 = function () {
// name = undefined
var scope2 = function () {
// name = undefined
var scope3 = function () {
var name = 'Todd'; // locally scoped
};
};
};
--------------------------------------------------------------------------------
前面我们了解了作用域的一些基本知识,我们发现有作用域的存在能帮我们省去不少事,但是于此同时,也给我们带来了很多麻烦,比如说我们想在下面的函数A中,调用函数B,我们该怎么办呢?
function A(){
function B(){
//
}
}
思路:我们给函数B设一个返回值,然后在函数A中调用,代码如下:
function A(){
function B(){
console.log("Hello foodoir!");
}
return B;
}
var c = A();
c();//Hello foodoir!
这样我们就可以得到我们想要的结果。这样,我们基本上到了一个最简单的闭包形式。我们再回过头分析代码:
(1)定义了一个普通函数A
(2)在A中定义了普通函数B
(3)在A中返回B(确切的讲,在A中返回B的引用)
(4)执行A(),把A的返回结果赋值给变量 c
(5)执行 c()
把这5步操作总结成一句话:函数A的内部函数B被函数A外的一个变量 c 引用。当一个内部函数被其外部函数之外的变量引用时,就形成了一个闭包。
思考:我们还有没有其他的方法?
思路:使用匿名函数
function A(){
//匿名函数
var B = function(x,y) {
return x+y;
}
console.log(B(1,2));//3
return B(1,2);
}
var c = A();
console.log(c);//3
然而,在Javascript高级程序设计中是这样描述闭包的“闭包是指有权访问另一个函数作用域中的变量的函数”,但是我们看匿名函数的例子,很明显,这种方法不可取!
通过这个例子,能让我们更好的理解闭包。
下面我们再来看下面的几种闭包
demo1:
function fn(){
var b = "foodoir";
return function(){
console.log(b);//foodoir
return b;
}
}
//console.log(b);//b is not defined
var result = fn();
console.log(result());//foodoir
demo2:
var n;
function f(){
var b = "foodoir";
n = function(){
return b;
}
}
f();
console.log(n());//foodoir
demo3:
//相关定义与闭包
function f(arg){
var n = function(){
return arg;
};
arg++;
return n;
}
var m = f(123);
console.log(m());//124
//注意,当我们返回函数被调用时,arg++已经执行过一次递增操作了,所以m()返回的是更新后的值。
demo4:闭包中的读取与修改
//闭包中的设置与修改
var getValue,setValue;
(function(){
var n = 0;
getValue = function(){
return n;
};
setValue = function(x){
n = x;
}
})();
//console.log(n);
console.log(getValue());//0
console.log(setValue());//undefined
setValue(123);
console.log(getValue());//123
demo5:用闭包实现迭代效果
//用闭包实现迭代器效果
function test(x){
//得到一个数组内部指针的函数
var i=0;
return function(){
return x[i++];
};
}
var next = test(["a","b","c","d"]);
console.log(next());//a
console.log(next());//b
console.log(next());//c
console.log(next());//d
demo6:循环中的闭包