python作用域和JavaScript作用域
JavaScript
一、JavaScript中无块级作用域
-
一个大括号一个作用域,就属于块级作用域,在Java和c#才存在块级作用域
function Main(){ if(1==1){ var name = 'seven'; } console.log(name); } // 输出: seven
二、JavaScript采用函数作用域
-
在JavaScript中每个函数作为一个作用域,在外部无法访问内部作用域中的变量
function Main(){ var innerValue = 'seven'; } Main(); console.log(innerValue); // 报错:Uncaught ReferenceError: innerValue is not defined
三、JavaScript的作用域链
-
由于JavaScript中的每个函数作为一个作用域,如果出现函数嵌套函数,就会出现作用域链
xo = 'alex'; function Func(){ var xo = "seven"; function inner(){ var xo = 'alvin'; console.log(xo); } inner(); } Func();
-
如果出现作用域链后,那么寻找变量时会出现顺序,是根据作用域链从内到外的优先级寻找,逐步往上找,没找到就抛出异常
四、JavaScript的作用域链执行前已创建
xo = 'alex'; function Func(){ var xo = "seven"; function inner(){ console.log(xo); } return inner; } var ret = Func(); ret(); // 输出结果: seven
上述代码,在函数被调用之前作用域链已经存在:
上述代码,在函数被调用之前作用域链已经存在:
- 全局作用域 -> Func函数作用域 -> inner函数作用域
当执行【ret();】时,由于其代指的是inner函数,此函数的作用域链在执行之前已经被定义为:全局作用域 -> Func函数作用域 -> inner函数作用域,所以,在执行【ret();】时,会根据已经存在的作用域链去寻找变量。
xo = 'alex'; function Func(){ var xo = "eirc"; function inner(){ console.log(xo); } xo = 'seven'; return inner; } var ret = Func(); ret(); // 输出结果: seven
上述代码和示例一的目的相同,也是强调在函数被调用之前作用域链已经存在:
- 全局作用域 -> Func函数作用域 -> inner函数作用域
不同的时,在执行【var ret = Func();】时,Func作用域中的xo变量的值已经由 “eric” 被重置为 “seven”,所以之后再执行【ret();】时,就只能找到“seven”。
xo = 'alex';<br> function Bar(){ console.log(xo); } function Func(){ var xo = "seven"; return Bar; } var ret = Func(); ret(); // 输出结果: alex
上述代码,在函数被执行之前已经创建了两条作用域链:
- 全局作用域 -> Bar函数作用域
- 全局作用域 -> Func函数作用域
当执行【ret();】时,ret代指的Bar函数,而Bar函数的作用域链已经存在:全局作用域 -> Bar函数作用域,所以,执行时会根据已经存在的作用域链去寻找。
五、声明提前
-
在JavaScript中如果不创建变量,直接去使用,则报错
console.log(xxoo); // 报错:Uncaught ReferenceError: xxoo is not defined
-
JavaScript中如果创建变量而不赋值,则默认赋值为undefined
var xxoo; console.log(xxoo); // 输出:undefined
而如果这么写
function Foo(){ console.log(xo); var xo = 'seven'; } Foo(); // 输出:undefined
上述代码,不报错而是输出undefined,其原因是:JavaScript的函数在被执行之前,会将其中的变量全部声明,而不赋值,所以,相当于上述实例中,函数在‘预编译’时,已经执行了var xo;所以上述代码中输出的是undefined
python
-
python能够改变变量作用域代码关键词:def、 class、 lambda
-
if语句,try异常捕获,for/while循环语句都不涉及变量作用域的更改,也就是他们的代码块中的变量,在外部也是可以访问的
def main(): if True: name = 'seven' print(name) main() #seven def Main(): inner = 'seven' Main() print(inner) #NameError: name 'inner' is not defined
-
python内部也是采用作用域链的形式,优先级是根据作用域从内到外找
name = 'alex' def func(): name = 'seven' def inner(): name = 'eric' print(name) inner() func()
#eric
name = 'alex' def func(): name = 'seven' def inner(): print(name) return inner ret = func() ret() #seven
-
函数被调用之前作用域链已经创建好
name = 'alex' def bar(): print(name) def func(): name = 'seven' return bar ret = func() ret() #alex
当内部作用域想修改外部作用域的变量时
-
修改的变量是在全局作用域上的,就要使用global声明
-
修改的变量在嵌套作用域上,就要使用nonlocal声明
#全局作用域 count = 10 def outer(): global count print(count) count = 100 print(count) outer() # 10 # 100 #嵌套作用域 def outer(): count = 10 def inner(): nonlocal count count = 20 print(count) inner() print(count) outer() # 20 # 20
-
变量查找顺序:作用域局部>外层作用域>当前模块中的全局作用域>python内置作用域