let a= 10; function func(){ console.log(a) } a; //10 func(); //10之前提到过最好不要使用 var 关键字定义变量,这是因为在浏览器环境中,使用 var 定义的全局变量,同时也会注册到全局对象 window 中(Node环境下不会),并且在浏览器开发环境中有经常需要使用到第三方库的情况,稍有不慎就会有同名的变量同时被注册到全局变量中,导致互相覆盖而引发问题,代码如下:
var x=10; globalThis.x; //10; var x="Hello"; globalThis.x; //"Hello"上方代码使用 var 定义了一个全局作用域的变量,并且使用 globalThis 访问全局变量,后面又使用同名变量覆盖了它的值,当再次访问时会发现变量值改变了,后续如果想再做与数字相关的操作,就会有问题。
globalThis 是 ES2020 中的新特性,用于统一访问全局对象,即在浏览器中是 window,而在 node 中则是global。
关于覆盖的问题,JavaScript 中使用 var 关键字定义的变量可以重复定义,后定义的变量会覆盖前边的,代码如下:var a=5; var a=6; console.log(a); //6要避免这个问题,可以使用 let 关键字,代码如下:
let b= 10; let b= 12; console.log(b); //SyntaxError:标识符b重复定义需要注意的是,如果是在 Chrome 开发者工具中的 Console 面板编写代码,则允许使用 let 重复定义变量,这是为了方便在同一个 Console 环境下,使用相同的变量名编写不同的测试代码,省去思考新变量名的困扰。
function func(){var x=5}; x; //引用错误:x未定义局部作用域可以访问全局作用域中的变量和函数,也可以访问父级及以上作用域中的变量和函数,如果有同名的变量或函数,则子作用域会覆盖父作用域中的变量或函数,代码如下:
let x=5; function outerFunc(){ let x=4; function innerFunc(){ let x=7; console.log(x); } console.log(x); return innerFunc; } let innerFunc=outerFunc(); innerFunc(); console.log(x);上方代码输出结果是:
{ let i=10; } console.log(i); //引用错误,i未定义 for(let j=0;j<10;j++){} console.log(j); //引用错误,j未定义不过对于 var 定义的变量,则没有块级作用域的概念,在上述语句块中使用 var 定义变量之后,在语句块之外还是可以访问的,它的作用域跟语句块所在的作用域是同级的。
for(var j=0;j<10;j++){} console.log(j); //10这里的 j 最后运行 j++ 之后会变成 10,在循环结束之后仍然可以访问它的值。
x=5; console.log(x); //5 var x;上边代码中的 var x 声明被提升到了 x=5 的上方,作为第一行代码,然后才给 x 赋值为 5,这样打印出来的值就是 5。
console.log(x); //undefined var x=5; console.log(x); //5它相当于如下代码:
var x; console.log(x); //undefined x=5; console.log(x); //5代码中的 var x 被提升到最顶部,剩下的赋值语句则保持在原位。
a=5; console.log(a); //引用错误,不能在初始化之前访问a let a;对于函数,使用 function 关键字定义的普通函数全部都会被提升到作用域的顶部。例如下方代码中,函数的定义会移动到 printValue() 上方,代码如下:
printValue(); //10 function printValue(){ console.log(10) }但是,对于保存在变量中的函数表达式则不会有提升机制,因为只有声明部分被提升了,而使用函数表达式进行赋值的部分并未被提升,代码如下:
printValue(); var printValue=function(){console.log(10)} //类型错误:printValue不是函数利用函数的提升,可以把函数定义的细节放到代码后边,把函数的调用放到前边,以便关注代码所执行的操作,屏蔽具体的实现细节,这样可以增强代码的可读性。
function func(){ return x; x=5; function x(){} var x; } console.log(func());代码输出的结果如下:
function func(){ function x(){} var x; return x; x=5; }
let a=5; function test(){ console.log(a); //引用错误,不能在初始化之前访问 'a' let a=6; } test();在代码中,函数 test() 的外部和内部定义了同名的变量 a,但是在函数中打印a的值时却抛出了错误。
let a=5; function test(){ const inner=()=>console.log(a); let a=6; inner(); } test(); //6这是因为在 inner() 函数调用前,临时隔离区在 let a=6 这行代码之后就已经结束了,a 在 test() 函数这个作用域中已经成功被初始化为 6,再在 inner() 中就可以访问它的值了。
本文链接:http://task.lmcjl.com/news/13763.html