作用域指的是变量的可见区域
1.全局作用域
- 全局作用域在网页运行时创建,在网页关闭时销毁
- 直接写到script标签中的代码都在全局作用域中
- 全局作用域中的变量是全局变量,可在任意地方访问
let a = 9 //全局作用域之全局变量,任何地方都能访问 console.log(a);//9 { console.log(a);//9 function xxx(){ console.log(a);//9 function yyy(){ { console.log(a);//9 } }; yyy(); }; xxx(); }
2.局部作用域
1)块级作用域
- 块级作用域是一种局部作用域
- 块级作用域在代码块执行时创建,在代码块执行完毕就销毁
- 在块级作用域中声明的变量只能在块内部访问,外部访问不了
2)函数作用域
- 函数作用域也是一种局部作用域
- 函数作用域在函数调用时创建,调用结束后销毁
- 函数每一次调用都会产生一个全新的函数作用域,它们都是独立的,互不影响
- 在函数作用域中声明的变量只能在块函数内部访问,外部访问不了
let a = 9 console.log(a);//9 { let a = 10 let c = 100 console.log(a);//10 function xxx(){ console.log(a);//10 console.log(b);//b is not defined function yyy(){ { let b = 11 console.log(b);//11 } }; yyy(); }; xxx(); } console.log(c);//c is not defined
3.作用域链
当我们使用一个变量时,JS解释器会优先在当前作用域中寻找变量,如果找到了则直接使用,如果没找到,则去上一层作用域中寻找,找到了则使用如果没找到,则继续去上一层寻找,以此类推如果一直到全局作用域都没找到,则报错 xxx is not defined
let a = 9 let b = 1 function x(){ let b = 10 function y(){ let c = 100 function z(){ { { console.log(a,b,c,d);//9 10 100 "d is not defined" } } } z() } y() } x()
总结:外面的变量里面可以访问,里面的变量外面访问不了。
4.var
1)Window对象
- 在浏览器中,浏览器为我们提供了一个window对象,可以直接访问
- window对象代表的是浏览器窗口,通过该对象可以对浏览器窗口进行各种操作
- 除此之外window对象还负责存储JS中的内置对象( String( ),Number( )...)和浏览器的宿主对象( alert( ),console.log( )...)
- window对象的属性可以通过window对象访问,也可以直接访问
- 函数可以认为是window对象的方法
- 向window对象中添加的属性会自动成为全局变量
2)var
- 声明变量,作用和let相同,但是var不具有块作用域
- 全局中使用var声明的变量,都会作为window对象的属性保存
- 用function声明的函数,都会作为window的方法保存
- 使用let声明的变量不会存储在window对象中,而存在一个秘密的小地方(无法访问)
- var虽然没有块作用域,但有函数作用域
// 直接访问或通过window访问 console.log(Number("123")); //123 console.log(window.Number("123")); //123 window.console.log(Number("123")); //123 window.console.log(window.Number("123")); //123 // 函数可以看做是window的方法 function x(){ console.log(1); } x() //1 window.x() //1 // 向window对象中添加的属性会自动成为全局变量 window.prop = "你好" console.log(prop); //"你好" { function xx(){ console.log(prop);//"你好" } { xx() } } //全局中使用var声明的变量,作为window对象的属性保存,let则不是 var a = 100 console.log(window.a);//100 console.log(a);//100 let b = 200 console.log(window.b);//undefined console.log(b);//200 // var没有块作用域,但有函数作用域 function xxx(){ var aaa = 1000 } console.log(aaa);//aaa is not defined { var bbb = 1000 } console.log(bbb);//1000
5.提升
javascript代码执行是从上到下挨个执行,当有var,函数声明创建的函数时,会先把它们全部找出来,先执行它们,再依次逐行执行,这个就是提升。
1)变量的提升
- 使用var声明的变量,它会在所有代码执行前被声明,所以我们可以在变量声明前就访问变量,此时的值为undefined(var a = 1,当程序开始执行,var a会被拿到最前面执行)
2)函数的提升
- 使用函数声明创建的函数function fn(){ },会在其他代码执行前先执行,所以我们可以在函数声明前调用函数
3)let声明的变量实际也会提升,但是在赋值之前解释器禁止对该变量的访问
var a = 1 function fn(){ a = 2 //没有声明变全局 console.log(a);//2 } fn() console.log(a); //2 全局为2它为2 var a = 1 function fn2(){ console.log(a);//undefined var a = 2; console.log(a);//2 } fn2() console.log(a);//1 function fn3(a){ //形参相当于变量声明 console.log(a);//undefined a = 2; console.log(a);//2 } fn3() console.log(a);//1 function fn4(a){ console.log(a);//1 a = 2; console.log(a);//2 } fn4(a) console.log(a);//1 // 函数提升 console.log(b);// ƒ b(){alert(111)} var b = 10; b() //直接弹出111 function b(){ alert(111) }