let a="a"; let c="c"; function bar(){ let a="bra_a"; console.log(c); //c 该值由查询到全局作用域后获取 function foo(){ console.log(a); //bra_a,这是一个取值操作,首先查询foo作用域没有,再查询bar作用域查到了就停止。 //console.log(b); // ReferenceError: b is not defined console.log(c); //c 该值由查询到全局作用域后获取 } foo(); }3. bar();
4 作用域的分类 4.1 全局作用域 最上层的作用域,javascript语言中编译最先开始工作的作用域。 4.2 函数作用域。 4.2.1 函数作用域的所在的作用域等级由函数定义所以决定。
let a="a" function foo(){ console.log(a);//a 在fun中执行时,foo作用域并不是在fun作用域的下级,所以这里输出a // console.log(b);//ReferenceError:报错 尽管在fun作用域内执行此方法,但是它的作用域与fun作用域属于同等级关系关系。 } function fun(){ let a="a_fun"; let b="b_fun"; function boo(){ console.log(a);//“a_fun” 由于boo作用域定义时处在fun作用域内,所以这里在boo作用域未查找到后,往上查fun作用域。 console.log(b);//"b_fun" } foo(); boo(); } fun();4.2.2 函数的参数:函数作用域规则中的一部分。
1 function fun(a){ 2 console.log(a); 3 } 4 fun(5);为了方便理解,以下是个人的理解。关于函数参数与该函数作用域的关系。 1 函数在定义时就创建声明了一个arguments的类数组对象,此时arguments类似一个空数组,当函数执行时将参数push进了arguments。 2 函数括号中的参数名称,首先在函数定义是将这些名称在函数中进行了变量声明,此时并没有赋值。当函数执行时这些参数变量会依次指向arguments类数组中的元素中指向的引用(类似双向绑定,也可以说两个指向同一个引用),函数中参数变量发生改变时arguments中相应元素值也会发生该改变(我觉得应该可以理解为参数名称和元素指向同一引用的值发生改变了)。 不过这里需要注意的时当函数定义时,给参数名称赋初始值后,函数内参数名称或相应arguments元素发生改变就不会一起改变了。参考变量C(这里理解是参数名称在函数定义时给初始值,造成函数执行时参数名称和arguments相应的元素指向的引用不是同一个了,所以在函数执行时只是将相应元素指向引用的值赋值给了函数名称指向引用的值。)
1 function fun(a,b,c=77) { 2 console.log("a:",a);//5 3 console.log("b",b);//6 4 console.log("c",c);//7 5 console.log("arguments:",arguments); //{ '0': 5, '1': 6 } 6 b=12 ;//var b=10;这里都一样 7 arguments[0]=10; 8 c=14; 9 arguments[2]=21; 10 console.log("b:",b); // 12 11 console.log("a:",a);//10 12 console.log("c:",c);//7 13 console.log("arguments:",arguments); //{ '0': 10, '1': 6, '2': 7 } 14 } 15 fun(5,6,7)4.3 块作用域 在javascript中除了最常见的函数作用域单元外,还有很多块级作用域比如;if(){},for(){},with(){},try{}catch(){}等。