变量声明是全部的编程语言中最基础部分之一。然而,JavaScript 有一个怪异点,称之为变量提高(hositing),这个可以让一个看上去可有可无的声明变成一个小bug。编程
在当前上下文遇到一个变量,若是不是私有的,则向上级上下文中查找一直找到全局上下文为止, 若是全局上下文中也没有:浏览器
二者之间存在映射关系(建立一个全局变量,也至关于给window设置一个属性)编程语言
在全局上下文代码执行的时候,遇到一个变量,首先看是否为全局变量(若是是操做全局变量,【var/function声明的会给window也设置一份】),不是全局变量则继续看是否为GO的属性(若是是至关于省略window),若是也不是则按照没有声明这个变量的错误处理函数
直接输出window.a是对象的成员访问,哪怕没有属性a,属性值是undefined,也不会报错spa
建议从新读一遍变量提高的概念,再作这三道题。code
console.log(a); var a=12; function fn(){ console.log(a); var a=13; } fn(); console.log(a);
console.log(a); var a=12; function fn(){ console.log(a); a=13; } fn(); console.log(a);
console.log(a); a=12; function fn(){ console.log(a); a=13; } fn(); console.log(a);
var foo='hello'; (function(foo){ console.log(foo); var foo=foo||'world'; console.log(foo); })(foo); console.log(foo);
解析:对象
代码在执行的时候遇到大括号{}(排除函数、对象的),在看到{}中有let、const、function才会把其当作块级做用域。blog
if(true) { var a = 1 } // 不是块级做用域 if(true) { let a = 1 } // 是块级做用域 if(true) { function a(){} } // 是块级做用域
console.log(foo) { console.log(foo) function foo() {} foo = 1; console.log(foo) } console.log(foo); // undefined function 1 function
解析:ip
建议把上面的四句话多读几遍再作作用域
console.log(foo); { console.log(foo); function foo() {} // 此时以前对FOO的操做不会映射,等待最后一次再处理 foo = 1; function foo() {} console.log(foo); } console.log(foo);
console.log(foo); { function foo() {} foo = 1; function foo() {} foo = 2; } console.log(foo);
公众号地址,欢迎关注!