好吧,首先我提个题外话,我记得之前面试有个面试官问我,你知道为什么js是单线程的吗?what the fox say
有兴趣的去阮一峰大大哪里去看,附上链接一枚js运行机制
作用域指程序在源代码中定义变量的区域。它规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。JavaScript采用的是词法作用域(lexical scoping),也就是静态作用域。
静态作用域:函数的作用域在函数定义的时候就已经决定了
动态作用域:函数的作用域是在函数调用的时候决定的
我们看两个列子
var value = 1; // 全局变量
function foo() {
console.log(value)
}
function bar() {
var value = 2; // 局部变量 局部变量的优先级要高于同名的全局变量
foo();
}
bar() //这里打印的是1哦
---我们假设一下JavaScript采用的是动态作用域,那么执行foo()时找不到内部有value,就会从调用函数的作用域bar方法里去查找变量value,会打印2。打印1正是以为JavaScript采用的静态作用域,找不到value会根据书写的位置查找上层代码,也就是var value = 1;
涉及到作用域的话,那么你就得掌握JavaScript的变量提升
我们都知道JavaScript是从上而下执行代码的,那么我们先看下两个列子
eg1:
a = 123;
var a;
console.log(a) // 你觉得应该是undefined吧,因为第二行声明了但没赋值
eg2:
console.log(a); //你可能认为报错, 因为在输出a之前,没有定义a变量
var a = 123;
那么告诉你这样想你就错了,告诉你吧 第一个是123 第二个是undefined,有没有感到amazing -。-
我们转换一下代码你就知道原因了
第一个例子变量提升后会变成:
var a;
a=123;
console.log(a) //123
第二个列子变量提升后会变成:
var a;
console.log(a) // undefined
a = 123
变量提升了解了,那么我们了解下函数有没有提升呢
有,函数声明会被提升,但是函数表达式不会被提升
a() //1
function a () {console.log(1)}
-------------------------------------------------------------
b() // 报错,b is not a function
var b = function() {console.log(1)}
那又有一个问题, 函数提升优先级和变量提升的谁高?
eg: show(); // 3
var show;
function show() { console.log(1) };
show= function() {console.log(2)}
function show() { console.log(3) }
当出现同名的函数声明,变量声明的时候, 函数声明会被优先提升,变量声明会被忽略,如果出现同名的函数声明,后者会覆盖前面的,所以是3而不是1
注意:局部变量在整个函数体始终是有定义的 ,即在函数体内局部变量覆盖了同名全局变量,而且,程序只有在执行到var语句时,局部变量才会被真正赋值