切入正題之前,我們先看一段**~
var x=10;
function fn()
function show(f))();
}show(fn)
注:(function(){})表示乙個匿名函式。function(arg)定義了乙個引數為arg的匿名函式,然後使用(function(arg))(param)來呼叫這個匿名函式。其中param是傳入這個匿名函式的引數。需要注意與$(function(){})的區別:$(function(){}) 是 $(document).ready(function(){}) 的簡寫,用來在dom載入完成之後執行一系列預先定義好的函式。
這裡我們就可以引入另乙個概念了:自由變數。
什麼叫自由變數呢?在a作用域中使用的變數x,卻沒有在a作用域中宣告(即在其他作用域中宣告的),對於a作用域來說,x就是乙個自由變數。
var x=10;
function fn()
上文中的x就是個自由變數。
那你們猜猜,這段**將在控制台輸出的數字是多少?
答案是——20!!!
啥?你也是這樣以為的?
嘿嘿,那你就錯了,上面我是逗你玩兒的。
正確答案是:10。
沒錯,正確答案就是10。
這是為什麼呢?其實,在呼叫乙個函式時,要到建立這個函式的那個作用域中取值——是「建立」,而不是「呼叫」,切記切記——其實這就是所謂的「靜態作用域」。
對於本文第一段**,在fn函式中,取自由變數x的值時,要到哪個作用域中取?——要到建立fn函式的那個作用域中取——無論fn函式將在**呼叫。
上面描述的只是跨一步作用域去尋找。
如果跨了一步,還沒找到呢?——接著跨!——一直跨到全域性作用域為止。要是在全域性作用域中都沒有找到,那就是真的沒有了。
這個一步一步「跨」的路線,我們稱之為——作用域鏈。
我們拿文字總結一下取自由變數時的這個「作用域鏈」過程:(假設a是自由量)
第一步,現在當前作用域查詢a,如果有則獲取並結束。如果沒有則繼續;
第二步,如果當前作用域是全域性作用域,則證明a未定義,結束;否則繼續;
第三步,(不是全域性作用域,那就是函式作用域)將建立該函式的作用域作為當前作用域;
第四步,跳轉到第一步。
好了,我們就拿這個按這個步驟來看看上面的**。
第一步,在當前作用域(即fn()函式域)查詢x,沒有找到.
第二步,在fn()作用域沒有找到x,則返回到建立fn的作用域去找,找到x=10,結束。
因此,控制台將輸出10。
到這裡大家獲取還是不夠清楚,那麼我們再舉乙個更複雜的例子。
阿福!關門!放**~~
var a=10;
function fn()
return b;
}var x=fn();
b=200;
x();
這段**,控制台會輸出什麼呢?
我們來分析一下:
第一步,fn()函式 return 回來的是函式b,則x=函式b。x()=b()。即執行b函式,b函式中有兩個變數,a和b。在b()中沒有a也沒有b,因此返回到建立b()函式的作用域繼續查詢,該作用域為fn()函式作用域。
第二步,在fn()作用域中,查詢到b=20,依舊沒有找到a。則返回到建立fn()的作用域去查詢。該作用域為全域性作用域。
第三步,在全域性作用域中,查詢到a=10,因此a+b=30。控制台輸出三十,結束。
biu~~~
高階js 變數提公升以及自由變數
q首先一道題 if false console.log a undefined 我以為輸出referenceerror aa is not defined 但是實際輸出undefined 因為js沒有塊級作用域,所以最後 就成了這樣 vara if false console.log a 1 let...
Javascript變數作用域
1.變數作用域是什麼鬼?2.全域性變數 全域性變數擁有全域性作用域 作用範圍在整個頁面中 在 的任何地方都有定義。擁有全域性作用域的情形 1 宣告在函式外部的變數。eg var a 全域性變數 function b 2 宣告變數時,缺少關鍵字var。eg function b 函式引數的變數 fun...
JavaScript 型別和變數
在程式語言中,能夠表示並且操作的型別叫資料型別,但我們需要將值儲存起來以備以後使用的時候,我們就需要將值儲存到乙個變數中。js中資料分為兩類 原始型別 primitive type 和物件型別 object type 原始型別資料報括數字 字串和布林值,並且js中有兩個特殊的原始值null 空 和u...