什麼是做用域函數
就是一塊"地盤", 一個代碼段所在的區域,它是靜態的(相對於上下文對象), 在編寫代碼時就肯定了測試
做用域分類:全局做用域, 函數做用域, 沒有塊做用域(ES6有了)this
做用域的做用是隔離變量,不一樣做用域下同名變量不會有衝突spa
var a = 10, b = 20 function fn(x) { var a = 100, c = 300; console.log('fn()', a, b, c, x) // fn() 100 20 300 10 function bar(x) { var a = 1000, d = 400 console.log('bar()', a, b, c, d, x) } bar(100) // bar() 1000 20 300 400 100 bar(200) // bar() 1000 20 300 400 200 } fn(10)
做用域與執行上下文code
全局做用域以外,每一個函數都會建立本身的做用域,做用域在函數定義時就已經肯定了。而不是在函數調用時對象
全局執行上下文環境是在全局做用域肯定以後, js代碼立刻執行以前建立blog
函數執行上下文環境是在調用函數時, 函數體代碼執行以前建立作用域
做用域是靜態的, 只要函數定義好了就一直存在, 且不會再變化;上下文環境是動態的, 調用函數時建立, 函數調用結束時上下文環境就會被釋放io
聯繫:上下文環境(對象)是從屬於所在的做用域:全局上下文環境==>全局做用域,函數上下文環境==>對應的函數使用域console
var a = 10, b = 20 function fn(x) { var a = 100, c = 300; console.log('fn()', a, b, c, x) function bar(x) { var a = 1000, d = 400 console.log('bar()', a, b, c, d, x) } bar(100) bar(200) } fn(10)
做用域鏈
多個上下級關係的做用域造成的鏈, 它的方向是從下向上的(從內到外)
查找變量時就是沿着做用域鏈來查找的
查找一個變量的查找規則
在當前做用域下的執行上下文中查找對應的屬性, 若是有直接返回, 不然進入2
在上一級做用域的執行上下文中查找對應的屬性, 若是有直接返回, 不然進入3
再次執行2的相同操做, 直到全局做用域, 若是還找不到就拋出找不到的異常
var a = 2; function fn1() { var b = 3; function fn2() { var c = 4; console.log(c); // 4 console.log(b); // 3 console.log(a); //2 console.log(d); // 報錯:d is not defined } fn2(); } fn1();
做用域測試題
var x = 10; function fn() { console.log(x); // 10,由於fn的做用域再也不show方法裏,定義方法的時候做用域就肯定了 } function show(f) { var x = 20; f(); } show(fn);
var fn = function () { console.log(fn) // 輸入函數自己 } fn() var obj = { fn2: function () { console.log(obj.fn2) // 這樣纔是找obj對象下的fn2 console.log(this.fn2) // 這樣纔是找obj對象下的fn2 // 報錯:fn2 is not defined,先在這個方法裏面找fn2,若是沒有在外部做用域(window)找 console.log(fn2) } } obj.fn2()
var fn = function () { console.log(fn) } fn() // function定義,總共有兩個做用域:函數內部和全局上,函數內部沒有,找到全局有,因此打印出fn函數的定義 var obj = { fn2: function () { console.log(fn2) // 想輸出fn2屬性的值 // console.log(this.fn2) // obj.fn2也行, 但比較死 } } obj.fn2() //報錯,也是兩個做用域函數內部和全局的,函數內部沒有,全局也沒有因此fn2是沒有定義的,結果是報錯的