js作用域和作用域链
作用域
首先要知道一点,js跟python都是一样的,先编译后执行
唯一的区别在于,js对于只声明,未定义的变量,报错是未定义,后面代码会有这个例子
编译的过程只有赋值和开辟空间的过程
只有函数,类才有作用域
如果,单写一个变量,例如python代码 x , js代码 <script>x</script>都会报错,没有定义,但是换成字符串就不会报错
全局作用域(Global Scope)
在代码中任何地方都能访问到的对象拥有全局作用域,一般来说一下几种情形拥有全局作用域:
(1)最外层函数和在最外层函数外面定义的变量拥有全局作用域
1 var name="yuan"; # 全局定义 2 3 function foo(){ 4 var age=23; # 局部定义 5 function inner(){。# 局部函数 6 console.log(age); # //age 23 7 } 8 9 inner(); 10 } 11 12 console.log(name); // yuan 13 //console.log(age); // Uncaught ReferenceError: age is not defined,在外部没有这个变量 14 foo(); // 内嵌函数的打印23 15 inner(); // Uncaught ReferenceError: inner is not defined 因为内嵌函数,找不到这个函数
(2)所有末定义直接赋值的变量自动声明为拥有全局作用域,例如:
1 var name="yuan"; 2 3 function foo(){ 4 age=23; # 全局定义 5 6 var sex="male" # 局部定义 7 } 8 foo(); 9 console.log(age); // 23 10 console.log(sex); // sex is not defined
(3)所有window对象的属性拥有全局作用域
一般情况下,window对象的内置属性都都拥有全局作用域,例如window.alert()、window.location、window.top等等。
查找过程:
内往外-局部,全局,内置
外往内-全-内置
局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部,所有在一些地方也会看到有人把这种作用域成为函数作用域.
作用域链(Scope Chain)
在JavaScript中,函数也是对象,实际上,JavaScript里一切都是对象。函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性。其中一个内部属性是[[Scope]],由ECMA-262标准第三版定义,该内部属性包含了函数被创建的作用域中对象的集合,这个集合被称为函数的作用域链,它决定了哪些数据能被函数访问。、
1.1 实例js代码:
1 //-----**********************例1********************************* 2 3 var s=12; 4 function f(){ 5 var s=12; 6 console.log(s) 7 } 8 f(); 9 结果打印的是未定义 10 // if s=12,打印12,因为是修改了全局 11 12 //-----**********************例2********************************* 13 14 var s=10; 15 function foo(){ 16 console.log(s); # 打印函数 17 var s=5; 18 console.log(s); # 打印5 ,局部变量的赋值 19 function s(){console.log("ok")}// 函数的定义或声明是在词法分析时完成的,执行时已不再有任何操作 20 console.log(s); # 打印5 21 } 22 foo(); 23 24 //-----***********************例3******************************** 25 26 function bar(age) { 27 console.log(age); # 打印函数 28 var age = 99; 29 console.log(age); # 99 30 function age() { 31 alert(123) 32 }; 33 console.log(age); # 99 34 } 35 36 result=bar(5);
1.2 实例解析例2
当一个函数创建后,它的作用域链会被创建此函数的作用域中可访问的数据对象填充。在函数bar创建时,它的作用域链中会填入一个全局对象,该全局对象包含了所有全局变量,如下图所示:
解析到函数调用时,即bar(5),会生成一个active object的对象,该对象包含了函数的所有局部变量、命名参数、参数集合以及this,然后此对象会被推入作用域链的前端,当运行期上下文被销毁,活动对象也随之销毁。新的作用域链如下图所示:
当创建函数后,作用域链的部分是0指向全局的Go,
当函数引入的时候,作用域链的部分是0,1。0数的局部Ao,1 指向全局的Go,
如果函数嵌套函数,作用域链的部分是0,1,2。0指向嵌套函数的局部Ao,1指向函数的局部Ao,2指向全局的Go,
js的 函数传参
1 <script> 2 3 // 函数传的参数,位置参数传递跟python不一样,不对等不报错 4 function a(x) { 5 console.log(x) 6 } 7 a(1); 8 function b(x,y) { 9 console.log(x,y) // 打印1 10 } 11 b(1); 12 function c(x) { 13 console.log(x) // 打印1 14 } 15 c(1,2); 16 17 18 //arguments 可以打印传来的所有参数,包含在一个序列里面 # 也就是说可以对这个进行循环 for(var i=0;i<arguments.length;i++){console.log(arguments[i])} 19 function d() { 20 console.log(arguments) 21 //Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]0: 11: 22: 3callee: ƒ a()length: 3Symbol(Symbol.iterator): ƒ values()__proto__: Object 22 } 23 d(1,2,3); 24 function e(x,y) { 25 console.log(arguments) 26 } 27 e(1,2,3) 28 29 </script>