js做用域和做用域鏈

做用域

首先要知道一點,js跟python都是同樣的,先編譯後執行前端

惟一的區別在於,js對於只聲明,未定義的變量,報錯是未定義,後面代碼會有這個例子python

編譯的過程只有賦值和開闢空間的過程函數

只有函數,類纔有做用域this

若是,單寫一個變量,例如python代碼 x , js代碼 <script>x</script>都會報錯,沒有定義,可是換成字符串就不會報錯spa

全局做用域(Global Scope)

在代碼中任何地方都能訪問到的對象擁有全局做用域,通常來講一下幾種情形擁有全局做用域: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等等。作用域

查找過程:

內往外-局部,全局,內置

外往內-全-內置

局部做用域(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>
相關文章
相關標籤/搜索