作用域
变量的作用域无非两种:全局变量,局部变量。
ES6之前,javascript没有块级作用域,它的作用域是相对函数而言,最外层函数定义的变量拥有全局作用域,即对任何内部函数来说,都是可以访问的。
var outerVar = "outer";
function fn(){
console.log(outerVar);// outer
}
fn();
for不是函数,可以看到定义的i是全局变量。js函数内的变量值不是在编译的时候就确定的,而是等在运行时期再去寻找的。
for(var i = 1; i < 10; i++){
//coding
}
console.log(i); //10
ES6,let定义的变量,作用于当前块级。
{
let name = 'yang'
}
console.log(name)//name is not defined
如果函数内部定义了一个和外部变量相同的变量名称,那么函数内部使用这个变量时,只会获取函数内部所定义的值。
var outerVar = "outer";
function fn(){
var outerVar = 'inner'
console.log(outerVar);// inner
}
fn();
var定义的变量具有提升作用。
var outerVar = "outer";
function fn(){
console.log(outerVar);// undefined
var outerVar = 'inner'
console.log(outerVar);// inner
}
fn();
函数参数的作用域:
var a = '1'
var b = { age : '2' }
var c = [3]
function start(a,b,c){
a = '3'
b = { age : '4'}
c.push(5)
}
start(a,b,c)
console.log(a,b,c)// 1,{age:'2'},[3,5]
函数进行声明初始化时,参数会形成一个单独的作用域,等到初始化完成,这个作用域会消失。函数的参数的作用域为本函数。
所以,函数的参数初始化时,相当于为它们各自重新声明了一个变量,并且有初始化值。
var a = '1'
var b = { age : '2'}
var c = [3]
然后函数内部改变这些参数的值,相当于函数内部开辟了值为'3','{age:"4"}'的新空间,并把a和b的值分别指向这两个新地址。
a = '3'
b= {age:'4'}
c的情况比较特殊,它是数组,不是赋值的方式,而是push的方式。而且我们知道,数组是在堆中的对象,所以c实质上是一个指向堆的地址,push就是往这个堆里,放进去一个新的数值。所以c.push会改变外面c的值。
如果在函数中,直接用另一个数组赋值给c,相当于函数内部开辟了一个新堆,并且把c指向这个新堆,则不会改变外面的c:
var c = [3]
function start(c){
c = [4]
}
start(c)
console.log(c)// [3]
作用域链
执行程序时,遇到变量,就会在当前作用域中寻找,找不到,就往上一级作用域找,如果一直找不到,就会返回undefined。