首先要知道一點,js跟python都是同樣的,先編譯後執行前端
惟一的區別在於,js對於只聲明,未定義的變量,報錯是未定義,後面代碼會有這個例子python
編譯的過程只有賦值和開闢空間的過程函數
只有函數,類纔有做用域this
若是,單寫一個變量,例如python代碼 x , js代碼 <script>x</script>都會報錯,沒有定義,可是換成字符串就不會報錯spa
在代碼中任何地方都能訪問到的對象擁有全局做用域,通常來講一下幾種情形擁有全局做用域:code
(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)全部末定義直接賦值的變量自動聲明爲擁有全局做用域,例如:blog
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對象的屬性擁有全局做用域ip
通常狀況下,window對象的內置屬性都都擁有全局做用域,例如window.alert()、window.location、window.top等等。作用域
查找過程:
內往外-局部,全局,內置
外往內-全-內置
和全局做用域相反,局部做用域通常只在固定的代碼片斷內可訪問到,最多見的例如函數內部,全部在一些地方也會看到有人把這種做用域成爲函數做用域.
在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,
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>