作用域
作用域的分类
全局作用域
在一个js脚本中,最外层的作用域就是全局作用域,在此范围内声明的任何变量都会是全局变量,可以在程序的任意位置访问
局部作用域
函数作用域
var locales = {school: function() {// 这里的school(学校)是局部作用域var student = "公众号:搞前端的半夏";var apartment = function() {//这里的apartment(宿舍楼)也是局部作用域var room = function() {// 这里的room依然是局部作用域console.log(student); // 公众号:搞前端的半夏};room();};apartment();}};locales.school(); //公众号:搞前端的半夏
我们想找到student,是怎么查找的呢,首先我们在他的宿舍查找,没有找到,然后会往上一层宿舍楼进行查找,宿舍楼没有找到,然后在往学校查找,最终找到了student。
代码块作用域
在代码块(if, for,while等等)中使用let和const声明变量,let和const会为这个代码块创建一个新的块级作用域。
function f(n) {if (true) {const msg = '你好';let name = n;console.log(msg + " " + name);//公众号-搞前端的半夏}console.log(msg + " " + name);//报错 msg is not defined}f('公众号-搞前端的半夏');
通过let和const在块级作用域外是无法被访问的。
function f(n) {if (true) {var msg = '你好';var name = n;console.log(msg + " " + name);//公众号-搞前端的半夏}console.log(msg + " " + name); //公众号-搞前端的半夏}
当我们使用var关键字时,变量在整个函数作用域都是可访问的
在 JavaScript 中,可以在多层嵌套范围内指定同名变量。在这种情况下,局部变量优先于全局变量。如果你声明了一个同名的局部变量和一个全局变量,当你在函数或块中使用它时,局部变量将优先。
JavaScript 解释器从当时正在执行的最内层范围开始,一直持续到找到第一个匹配项,无论外层级别中是否存在其他同名变量。
var test = "我是全局";function testScope() {var test = "我是局部";console.log (test);}testScope(); // output: 我是局部console.log(test);// output: 我是全局
即使名称相同,局部变量在函数执行后也不会覆盖全局变量testScope()。
var test = "我是全局";function testScope() {test = "我是局部";console.log(test);}console.log(test);// output: 我是全局testScope(); // output: 我是局部console.log(test);// output: 我是局部
这一次,局部变量test覆盖了同名的全局变量。当我们在testScope()函数内部运行代码时,全局变量被重新分配。如果一个局部变量在没有首先用关键字声明的情况下被赋值var,它就变成了一个全局变量。为避免此类情况,应始终在使用局部变量之前声明它们。在函数中使用关键字声明的任何变量var都是局部变量。
总结
var 变量是函数作用域let and const 变量是块级作用域使用var关键字声明的全局作用域变量属于window对象。使用let关键字声明的全局作用域变量不属于window对象。var关键字定义的变量可以先使用后声明。
let关键字定义的变量需要先声明再使用。
const关键字定义的常量,声明时必须进行初始化,且初始化后不可再修改。
变量提升
var a = 1function fn(){console.log(a)var a = 2}fn() //undefined
这个代码相当于
var a = 1function fn(){var a //undefinedconsole.log(a)a = 2}fn() //undefined
变量声明提升
函数提升
function f() {x();function x() {console.log(1);}}f();
这个代码等价于
function f() {function x() {console.log(1);}x();}f();
扩展
var fn = function(){}和function fn(){}的区别:前者为变量提升,后者为函数提升。
fn1() //fn1fn2() //fn2 is not functionfunction fn1() {console.log("fn1")}var fn2 = function() {console.log("fn2")}f();
如果是用变量提升来声明函数,如果在此前调用该函数,此时的函数对象并没有创建,变量fn2赋值为undefined,所以浏览器不能识别,把它当做函数来调用,所以最后报错。
在js中,函数优先级最高
被覆盖的不是函数fn,而是var fn =3;
console.log(fn)function fn() {console.log("hello world")}var fn = 1
结果