作用域指的是声明的变量可以被访问到的范围
看到一道题目,瞬间觉得需要了解一下
// 正常的
if (a) {
function a() {}
}
// 奇葩的
if (a) {
a = 1;
function a() {};
a = 2;
}
作用域的分类
全局作用域
全局变量的作用域是全局的:网页的所有脚本和函数都能够访问它(参考w3c的定义)
局部作用域
函数在执行的时候,会形成自己的作用域,里面声明的变量,仅在函数内部访问到。
块级作用域
在块语句(或其他语言的复合语句),通过let和cosnt声明的语句,仅仅可以在块级语句中访问到。
块语句
并不是碰到块语句就会形成块级作用域
-
块语句中通过
let,const声明的变量作用域才是当前的语句 -
块语句中通过
var声明的变量不是当前的作用域,而是会变量提升 -
块语句中
function声明的变量在不同的浏览器里可能有不同的效果(但是变量名会被提升)
特殊的function声明(在不同浏览器中处理不同)
块语句中通过function声明的变量,语句执行前的表现
-
safari会在执行前提升到全局为function -
google在执行前提升变量但是不赋值为undefined,但是在块级语句执行的时候,变量立即变成function
块语句中function声明语句执行时的表现
safari会赋值到全局的变量google会在声明语句后生成一个同名的块级变量
if(false) {
function a() {}
}
console.log(a) // google: undefined safari: 'funciton'
总结:
通过前3条可以知道,块语句中用了var,function,这些变量会提升。执行过后,块级语句的外部也可以访问到这些变量
// 正常的一些问题
var globalFunc = 2
console.log(globalScope)
console.log(globalFunc1)
if (true) {
console.log(globalFunc)
let blockScope = 'a';
var globalScope = 'c';
globalFunc1 = 'e';
function globalFunc() {}
function globalFunc1() {}
}
// 在外部访问的情况
blockScope // Uncaught ReferenceError: is not defind
globalScope // 'c'
globalFunc // function...
globalFunc1 // 'e'
现在看一下例外的情况
当然大家都不可能这么写,但是大胆的讨论一下
if (true) {
a = 1;
function a() {};
a = 2;
}
// 就如MDN里面说的不同浏览器不同效果
// google下:window.a为1
// safari下:window.a为2
// google可能是在funciton a() {}语句后,声明了let a,才会出现这个结果
// safari 就是比较中规中矩的表现