1
- # 前端知识点整理3—作用域、闭包、模块
2
- 日期:7.27
3
- 内容:作用域、闭包、模块
4
-
5
1
## 作用域
6
2
- 作用域:根据名称查找变量的一套规则。
7
3
- 编译的三个阶段:
@@ -38,25 +34,25 @@ JS引擎在2和3阶段都会进行性能优化,大部分情况下编译发生
38
34
- 缺点:由于闭包作用域不会被垃圾回收,内存占用。
39
35
- 优点:可以保留外部作用域对一个变量的私有引用;设计私有的方法和变量;避免全局变量的污染;
40
36
- 实例:
41
- 1)闭包函数作为函数参数传递给setTimeout()
42
- ```
37
+ 1)闭包函数作为函数参数传递给setTimeout()
38
+ < pre >
43
39
function wait(message) {
44
40
setTimeout( function timer(){
45
41
console.log( message );
46
42
}, 1000 );
47
43
}
48
44
wait( "Hello, closure!" );
49
- ```
45
+ </ pre >
50
46
2)在定时器、事件监听器、Ajax请求、跨窗口通信中,只要使用了回调函数,实际上就是在使用闭包。
51
- ```
47
+ < pre >
52
48
function setupBot(name,selector) {
53
49
$( selector ).click( function activator(){
54
50
console.log( "Activating: " + name );
55
51
} );
56
52
}
57
53
setupBot( "Closure Bot 1", "#bot_1" );
58
54
setupBot( "Closure Bot 2", "#bot_2" );
59
- ```
55
+ </ pre >
60
56
- ** 经典例子**
61
57
1)
62
58
```
@@ -72,7 +68,7 @@ i\*1000是每次都会计算,即1000,2000,3000,4000,5000
72
68
备注:如果setTimeout()函数中,i\* 1000改为0,则结果为同时输出6,6,6,6,6
73
69
问题:这里只有一个闭包作用域,如果要打印出1,2,3,4,5得要这5个延迟函数,分别引用不同的i,也就是不同的作用域。所以需要创建不同的作用域。
74
70
** 改写方式1** :立即执行函数能创建作用域
75
- ```
71
+ < pre >
76
72
for (var i=1; i<=5; i++) {
77
73
(function(){
78
74
var j = i;
@@ -81,41 +77,41 @@ for (var i=1; i<=5; i++) {
81
77
}, j*1000 );
82
78
})();
83
79
}
84
- ```
80
+ </ pre >
85
81
或者
86
- ```
82
+ < pre >
87
83
for (var i=1; i<=5; i++) {
88
84
(function(j){
89
85
setTimeout( function timer(){
90
86
console.log( j );
91
87
}, j*1000 );
92
88
})( i );
93
89
}
94
- ```
90
+ </ pre >
95
91
输出:每秒一次的频率输出0,1,2,3,4,5
96
92
** 改写方式2** :let可劫持块作用域
97
- ```
93
+ < pre >
98
94
for (var i=1; i<=5; i++) {
99
95
let j = i; // 闭包的块作用域
100
96
setTimeout( function timer(){
101
97
console.log( j );
102
98
}, j*1000 );
103
99
}
104
- ```
100
+ </ pre >
105
101
或者:for(let=i; ;)每次迭代都会产生新的let块作用域
106
- ```
102
+ < pre >
107
103
for (let i=1; i<=5; i++) {
108
104
setTimeout( function timer(){
109
105
console.log( i );
110
106
}, i*1000 );
111
107
}
112
- ```
108
+ </ pre >
113
109
输出:每秒一次的频率输出0,1,2,3,4,5
114
110
相关链接:
115
- [ 闭包面试题] ( http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552304&idx=2&sn=6abd16cf650f64cdcc12abfbb6231cbc&chksm=8025adf1b75224e789d21d12750949d3d4e9428b7f5add79aab6945c7d98cf1549da17a2b337&mpshare=1&scene=23&srcid=0729WeoziBvRKNSgKvHuBd9a#rd )
116
- ** 相关知识** :
111
+ [ 闭包面试题] ( http://mp.weixin.qq.com/s?__biz=MzAxODE2MjM1MA==&mid=2651552304&idx=2&sn=6abd16cf650f64cdcc12abfbb6231cbc&chksm=8025adf1b75224e789d21d12750949d3d4e9428b7f5add79aab6945c7d98cf1549da17a2b337&mpshare=1&scene=23&srcid=0729WeoziBvRKNSgKvHuBd9a#rd )
112
+ ** 相关知识** :
117
113
1.普通函数:
118
- ```
114
+ < pre >
119
115
function compare(value1,value2){
120
116
if(value1 < value2){
121
117
return -1;
@@ -126,11 +122,11 @@ function compare(value1,value2){
126
122
}
127
123
}
128
124
var result = compare(5,10);
129
- ```
130
- ![ 函数执行时的作用域链] ( http://upload-images.jianshu.io/upload_images/7008018-e2bf0b3e455a59de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
131
- 解释:在创建/声明compare()函数时,会创建一个预先包含全局变量对象的作用域链;当执行函数/函数被调用时,会创建一个执行环境及相应的作用域链,并且创建本地活动对象,并将其推入作用链前端;当compare()函数执行完毕后,执行环境的作用域链被销毁,compare()的活动对象已没用(标记清除或引用计数),最后被垃圾回收。
132
- 2.闭包函数
133
- ```
125
+ </ pre >
126
+ ![ 函数执行时的作用域链] ( http://upload-images.jianshu.io/upload_images/7008018-e2bf0b3e455a59de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
127
+ 解释:在创建/声明compare()函数时,会创建一个预先包含全局变量对象的作用域链;当执行函数/函数被调用时,会创建一个执行环境及相应的作用域链,并且创建本地活动对象,并将其推入作用链前端;当compare()函数执行完毕后,执行环境的作用域链被销毁,compare()的活动对象已没用(标记清除或引用计数),最后被垃圾回收。
128
+ 2.闭包函数
129
+ < pre >
134
130
function createComparisonFunction(propertyName){
135
131
return function(object1,object2){
136
132
var value1 = object1[propertyName];
@@ -147,15 +143,15 @@ function createComparisonFunction(propertyName){
147
143
var compareNames = createComparisonFunction("name");
148
144
var result = compareNames({name:"Nicholas"},{name:"Greg"});
149
145
compareNames = null; // 解除引用
150
- ```
146
+ </ pre >
151
147
152
- ![ 闭包函数执行时的作用域链] ( http://upload-images.jianshu.io/upload_images/7008018-0eb9b6b8c5728346.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
153
- 解释:当createComparisonFunction()函数执行完毕后,其执行环境的作用链被销毁,但是其活动对象依然被保留在内存中,还存在引用。直到匿名函数被销毁后,createComparisonFunction()的活动对象才会被销毁。
148
+ ![ 闭包函数执行时的作用域链] ( http://upload-images.jianshu.io/upload_images/7008018-0eb9b6b8c5728346.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240 )
149
+ 解释:当createComparisonFunction()函数执行完毕后,其执行环境的作用链被销毁,但是其活动对象依然被保留在内存中,还存在引用。直到匿名函数被销毁后,createComparisonFunction()的活动对象才会被销毁。
154
150
155
151
156
152
## 模块
157
153
- 模块函数内:声明私有变量和内部函数;内部函数可访问私有变量;返回对象,其属性为内部函数。
158
- ```
154
+ < pre >
159
155
function CoolModule() {
160
156
var something = "cool";
161
157
var another = [1, 2, 3];
@@ -176,11 +172,11 @@ function CoolModule() {
176
172
var foo = CoolModule();
177
173
foo.doSomething(); // cool
178
174
foo.doAnother(); // 1 ! 2 ! 3
179
- ```
180
- 备注:模块函数也可直接返回内部函数,例如jQuery中的$标识符就是jQuery模块的公共API。
181
- - ** 单例模式**
182
- 当只需要一个实例时
183
- ```
175
+ </ pre >
176
+ 备注:模块函数也可直接返回内部函数,例如jQuery中的$标识符就是jQuery模块的公共API。
177
+ - ** 单例模式**
178
+ 当只需要一个实例时
179
+ < pre >
184
180
var foo = (function CoolModule() {
185
181
var something = "cool";
186
182
var another = [1, 2, 3];
@@ -201,5 +197,5 @@ var foo = (function CoolModule() {
201
197
202
198
foo.doSomething(); // cool
203
199
foo.doAnother(); // 1 ! 2 ! 3
204
- ```
200
+ </ pre >
205
201
备注:将模块函数,改为立即执行函数。
0 commit comments