var name = 'window';
function outerFun(){
var name = 'night';
console.log('1',this.name);
var innerFun = function(){
console.log('2',name);
console.log('3',this.name);
};
return innerFun;
};
outerFun()();
结果:
1 window
2 night
3 window
分析
示例代码在执行的时候,可以进行如下分解:
var name = 'window';
var fun1 = outerFun();
var fun2 = fun1();//fun2是fun1的闭包
fun2();//最终调用
对于JS的闭包(Closure)的概念,以及闭包的作用域具有全局性。我针对我自己的实战感受,这里简单谈谈。
概念
闭包(Closure),是指有权访问另一个函数作用域中的变量的函数。
创建闭包,常见的一种方式就是在一个函数内部创建另一个函数。
示例
举个例子来解释下这个概念:
分析
示例代码在执行的时候,可以进行如下分解:
再来继续加工下:
为什么能这么变形呢?因为在最外层,其实所有变量都是window对象的!
经过上面的分解,我们知道最终调用
fun2()
的时候,其实fun2函数,已经相当于是window环境了。所以,我们知道任何闭包,都是最终都相当于在window环境下执行的,这也就是为什么闭包的作用域具有全局性了。
深究
接下来再来看单独拆分下每个函数:
fun1
的函数:为什么
fun1
中的结果是:window 而不是 night?知识点:
this
和arguments
,fun1中的this(调用它的对象,也叫活动对象),即:window全局作用域
和局部作用域
的最大区别就是,局部作用域在函数内部定义,并且在非闭包的情况下,函数运行完毕就释放掉了。所以:
console.log('1',this.name);
其实就是在window中寻找name
属性,这个肯定是window
了,因为在函数之前,我们定了var name
=window.name
。至于
fun1
中的name
其实在函数中,根本就没有被使用,而如果我们不明确指定this.name
,即:那么结果肯定是:night,再如果fun1内部未定义name,那么最终还是会通过原型链(或者叫上下文)找到全局的name。
fun2
的函数:fun2所处的活动对象其实有3个:
console.log('2',name);
会优先从内部寻找name
变量,没找到!那么就从为其提供闭包的父函数fun1
中找,找到了,即:nightconsole.log('3',this.name);
这里明确指定了this.name
那么,系统就会从原型链开始寻找this.name
,由于this
指向的是window
,那么结果自然就是:window扩展
其实闭包函数,在我们的日常工作中经常用到。
定义对象过程中经常会涉及到
方法中包含setTimeout
其实,还有很多这方面的例子,但是不管怎么样,你要记住一个概念:函数中的函数。
而且闭包有一个优势:就是能访问创建闭包对象的变量。