1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Document</title>
6 </head>
7 <body>
8 <script>
9
10 /*//demo1
11 var v = "hello";
12 (function(){
13 console.log(v);
14 var v = "world";
15
16 })();//undefined*/
17
18 //1、function作用域里的变量v遮盖了上层作用域变量v。
19 //2、在function作用域内,变量v的声明被提升了。所以最初的代码相当于:
20
21 // var v = "hello";
22 // (function(){
23 // var v;
24 // console.log(v);
25 // v = "world";
26 // })();
27
28 // 所以这总类型我们叫做 声明提升 ,
29 //声明提升:当前作用域内的声明都会提升到作用域的最前面,包括变量和函数的声明
30 //实例如下:
31
32 //demo2
33 /* (function(){
34
35 console.log(a);
36 console.log(a+b+c);
37 var a = "1";
38 var f = function(){};
39 var b = "2";
40 var c = "3";
41
42 })();*/
43
44 // 这个代码是怎么进行声明提升的?
45 // 变量a,f,b,c的声明会被提升到函数作用域的最前面,类似如下:
46 /*(function(){
47 var a,f,b,c;
48 alert(a);
49 a = 1;
50 f = function(){};
51 b = 2;
52 c = 3;
53 alert(a+b+c);
54 })();*/
55 // 请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:
56
57 //demo3
58 /*function(){
59
60 var f1 = function aa(){};
61 function f2(){
62 alert(1);
63 }
64 };
65 aa();
66 f2();
67
68 */
69 //var f1,function f2(){}; //hoisting,被隐式提升的声明
70 // 上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明是被提升的。
71
72
73 //demo4
74 /*var a = 1;
75 function outer(){
76 var b = 2;
77 function inner(){
78 var c = 4;
79 console.log(a); //1
80 }
81 inner(); //调用inner函数
82 }
83 outer(); //调用rainman函数 */
84
85 //JavaScript的作用域链
86 //观察alert(a);这句代码。JavaScript首先在inner函数中查找是否定义了变量a,如果定义了则使用inner函数中的a变量;如果inner函数中没有定义a变量,JavaScript则会继续在onter函数中查找是否定义了a变量,在这段代码中outer函数体内没有定义a变量,则JavaScript引擎会继续向上(全局对象)查找是否定义了a;在全局对象中我们定义了a = 1,因此最终结果会弹出'1'。
87
88 //作用域链:JavaScript需要查询一个变量x时,首先会查找作用域链的第一个对象,如果以第一个对象没有定义x变量,JavaScript会继续查找有没有定义x变量,如果第二个对象没有定义则会继续查找,以此类推。
89
90 //上面的代码涉及到了三个作用域链对象,依次是:inner、outer、window。
91
92
93 //demo5
94 var a = 1; //定义全局变量 a
95 function check(){
96 a = 100; //不加var还是全局变量
97 var a=100;//a是局部变量
98 console.log(a); //100
99 }
100 check();
101 console.log(a); //1
102
103 //demo6
104 /*var v = "hello";
105 if(true){
106 console.log(v);
107 var v = "world";
108 console.log(v);
109 }//hello word
110 */
111 // 输出结果为”hello”,说明javascript是没有块级作用域的。函数是JavaScript中唯一拥有自身作用域的结构。
112
113 //demo7
114 function rain(){
115 var x = 1;
116 function man(){
117 x = 100;
118
119 }
120 man(); //调用man
121 console.log( x ); //100
122 }
123 rain(); //调用rain 100
124
125 //上面得代码说明了,变量x在整个rain函数体内都可以使用,并可以重新赋值。
126
127
128 // // demo8
129 // var x = 1;
130 // function rain(){
131 // console.log( x );
132 // var x = 'man';
133 // console.log( x );
134 // }
135 // rain() //undefined.man
136
137
138 //demo9
139 /* function rain(){
140 x = 100;
141 }
142 rain();
143 console.log( x ); //100
144
145 //未使用var关键字定义的变量都是全局变量。 */
146
147
148 //demo10
149 /* var x = 100 ;
150 console.log(window.x); //100 .100
151 console.log(x);
152 */
153 //全局变量都是window对象的属性相当于:
154 // window.x = 100;
155 // alert( window.x );
156 // alert(x)
157
158
159 //demo11
160 /* var x = 10;
161 function outer(){
162 var x = 20;
163 function inner(){
164 var x = 30;
165 console.log(x);//30
166 }
167 inner();
168 console.log(x);//20
169 }
170 outer();
171 console.log(x);//10
172 */
173
174 //解释如下:
175 // var x = 10;//全局定义了一个变量x=10
176 // function outer(){//这有一个函数(进入局部)
177 // var x = 20;//局部定义了一个x=20
178 // function inner(){//在外边的局部又进入一个局部
179 // var x = 30;//里边的局部定义了一x=30
180 // alert(x);//弹x,这里弹得是里边局部定义的x 30
181 // }
182 // inner();//调用里边函数 弹30
183 // alert(x);//这个是弹第一个局部的x 20
184 // }
185 // outer();//调用第一个局部,第二个局部的出了局部就销毁了。弹20
186 // alert(x);//局部已经销毁,弹得是全局的 x=10
187
188
189 //demo12
190 /*var t='a';
191 function test2(){
192 console.log(t);//undefined
193 var t='b';
194 console.log(t);//b
195 }
196 test2();//0*/
197
198
199 //解释如下:
200 // var t='a';//全局定义一个字符串t=‘a’;
201 // function test2(){//函数,进入了局部
202 // alert(t);//这个时候js已经找完整个局部,发现局部下边也定义有t,那么这个已经用不了全局的变量,但是这个代码执行的时候局部定义的t还没有执行到。所以弹出undefined,找不到
203 // var t='b';//这个时候才定义了一个局部变量t
204 // alert(t);//弹出上边定义的局部变量 弹得是“b”
205 // }
206 // test2();
207
208
209 //demo13
210 /*var t='a';
211 function test2(){
212 console.log(t);
213 t='b';
214 console.log(t);
215 }
216 console.log(t);//a
217 test2();//a,b
218 console.log(t);//b*/
219
220
221 //解释如下:
222 // var t='a';//全局定义一个字符串t=‘a’;
223 // function test2(){//函数,进入了局部
224 // alert(t);//这个时候js已经找完整个局部,发现局部下边没有定义有t,只是在下边给t赋了个值,但是赋值是在这个代码后边,所以这个弹得是全局变量的t。 弹出 a
225 // t='b';//把b赋值给t。注意不是定义t等于b,而是赋值。
226 // alert(t);//上边t被赋值为b 所以弹出b
227 // }
228 // test2();
229
230
231 //demo14
232 /* var a="Hello";
233 function test(){
234 var a;
235 alert(a);//局部定义有a 但是没有赋值,所以弹出undefined
236 a="World";
237 alert(a);//a在局部被赋值,弹出 World。
238 }
239 test();//undefined,word*/
240
241
242 // demo15
243 /* var a="Hello";
244 function test(){
245 alert(a);
246 a="World";
247 alert(a);
248 }
249 test();//hello,word
250 */
251
252 //demo16
253 var a =1;
254 function test(){
255 console.log(a);
256 var a=4;
257 console.log(a);
258 a=2;
259 console.log(a);
260 }
261 test(); //undefined,4,2
262 console.log(a);//2
263 </script>
264 </body>
265 </html>