例如:
var a = a;console.log(a); // undefined.
看吧,明明都差不多,結(jié)果卻全然不同。
但是實(shí)際上卻沒什么卵用,見下面的代碼:
var a = a;console.log(a 2); // NaN
結(jié)果是NaN, 得到了一個(gè)我們完全不想要的結(jié)果。在如果無(wú)法順利數(shù)學(xué)計(jì)算時(shí),Javascript便會(huì)給出一個(gè)非數(shù)字的結(jié)果,用NaN表示。但是比較有趣的是,如果你用typeof去驗(yàn)證NaN類型:
typeof NaN ; // number
卻告訴我們,這TMD是一個(gè)數(shù)值 number。
Javascript莫名其妙的地方還有許多許多,不過我們還是不要繼續(xù)調(diào)戲javascript了,開始認(rèn)真學(xué)習(xí)了。
類型與存儲(chǔ)
Javascript一共有 7 種原始類型 和 1 種 引用類型,如下:
原始類型
1、number
2、string
3、boolean
4、symbol
5、bigint
6、undefined
7、null
引用類型:
object
(這里面我就用小寫了,因?yàn)?code>typeof返回的是小寫的)
我就是介紹一下這些必須要了解的東西,具體用法其他資料都有我就不贅述了。不過關(guān)于typeof還有要補(bǔ)充的一點(diǎn)是,它對(duì)于null和function結(jié)果:
function sayHello(){
console.log('hello the world');
}
console.log(typeof sayHello); // function
console.log(typeof null); // object
……對(duì)于一個(gè)函數(shù),它真的返回的是一個(gè)“函數(shù)”,某種意義上用處很大,不過對(duì)null值返回一個(gè)object,這只能說(shuō)有得就有缺吧。
我覺得對(duì)變量加深了解的辦法就是明白它的底層運(yùn)作方式。其實(shí)也沒有什么了不起的,原始值是直接放在內(nèi)存棧區(qū), 引用類型值則是放在內(nèi)存堆區(qū)(這是它的實(shí)際存儲(chǔ)區(qū)位置);(如果是常量,那么就會(huì)放在池中,好像也是棧區(qū)的一部分)。正常情況下,變量取值都是直接都是從內(nèi)存棧區(qū)中獲取的,但是引用類型的值是放在內(nèi)存堆中,那么怎么辦?
引用類型值的訪問:
1、一個(gè)引用類型的變量,會(huì)在內(nèi)存棧中保存一個(gè)指針
2、這個(gè)指針是用于引用內(nèi)存堆中的存儲(chǔ)區(qū)的內(nèi)存地址
3、在訪問一個(gè)類型值時(shí)
4、會(huì)通過指針找到內(nèi)存堆中的存儲(chǔ)區(qū),然后從中獲取值。
例如:
var first = {
name:'hahei...'
}
var gggiii=111222;
映射圖如下:
注意:此處我用 ref. first表示 存儲(chǔ)區(qū)的引用 , 因?yàn)殡m然保存的盡管是指針,但是在訪問這個(gè)值時(shí),會(huì)進(jìn)行二次解析(即通過這個(gè)指針找到存儲(chǔ)區(qū)), 而不是直接返回這個(gè)指針的具體數(shù)據(jù)。詳細(xì)可以參考 C 引用。
初識(shí)詞法環(huán)境
想必各位都已經(jīng)對(duì)什么是作用域了若指掌,但是我還是必須重新提一下。作用域是標(biāo)識(shí)符的可訪問范圍,在Javascript中的任何操作,幾乎都有作用域的參與。Javascript中使用詞法環(huán)境決定作用域,在下面我會(huì)簡(jiǎn)單介紹一下。(請(qǐng)注意,這里我沒有用變量這個(gè)術(shù)語(yǔ),因?yàn)榻馕鰳?biāo)識(shí)符范圍時(shí),應(yīng)該還沒有真正生成代碼,感興趣的可以去了解一下AST語(yǔ)法樹)
看,以下代碼:
var val=111;
function hahaha(){
console.log(val);
}
function hihihi(){
hahaha();
}
hihihi(); /// 111
的確是正確輸出了,111。
但是我更喜歡把 val放在一個(gè)函數(shù)中,如:
function hahaha(){
console.log(val); /// (**)
}
function hihihi(){
var val=111; /// (*)
hahaha();
}
hihihi();
結(jié)果就是Uncaught ReferenceError: val is not defined, 根本沒找到val這個(gè)標(biāo)識(shí)符,這是為什么?
因?yàn)閳?zhí)行過程是這樣的:
hihihi函數(shù)執(zhí)行 , 然后為 val賦值……hahaha函數(shù)執(zhí)行在hahaha找不到val標(biāo)識(shí)符,便去外部詞法環(huán)境hahaha外部詞法環(huán)境就是** hahaha函數(shù)聲明時(shí)代碼的外部**,即全局代碼(下稱全局詞法環(huán)境)在全局詞法環(huán)境沒找到val,終了。
(請(qǐng)注意3-5步, 找val找的是函數(shù)聲明代碼的外部,而不是函數(shù)調(diào)用時(shí)的位置。)
現(xiàn)在應(yīng)該提一下概念了,詞法環(huán)境(Lexical Environment)就是根據(jù)代碼結(jié)構(gòu)時(shí)決定的作用域,也可以稱作詞法作用域(Lexical Scoping)它是靜態(tài)作用域。可以這么說(shuō),在源代碼寫好時(shí),所有標(biāo)識(shí)符的作用域就已經(jīng)被決定。當(dāng)然也有動(dòng)態(tài)作用域,你可以去試試bash腳本,它就是動(dòng)態(tài)的。嘿嘿。詳細(xì)也可以參考靜態(tài)作用域、詞法作用域。
此處只要發(fā)現(xiàn)了個(gè)中區(qū)別就極好掌握,所以我就略了。
詞法環(huán)境的抽象
在Javascript常用三種詞法環(huán)境: 一、塊級(jí)作用域 二、全局作用域 三、函數(shù)作用域。
有時(shí),我們會(huì)將一個(gè)詞法環(huán)境(即作用域,下面我會(huì)正式使用詞法環(huán)境替代作用域這個(gè)術(shù)語(yǔ))抽象成偽代碼,如下:
LexicalEnvironment = {
OuterEnv: < ... > ,
This : < ... > ,
EnvironmentRecord:{
// ... identifiername:variable
}
}
很簡(jiǎn)單:
OuterEnv:當(dāng)前詞法環(huán)境的外部詞法環(huán)境This: 當(dāng)前詞法環(huán)境的 this的值,但它是運(yùn)行時(shí)決定的。EnvironmentRecord(環(huán)境記錄): 標(biāo)識(shí)符-變量的映射,注意,這里的標(biāo)識(shí)符只是單純的字符串,變量指的是存儲(chǔ)區(qū)的數(shù)據(jù)。而且標(biāo)識(shí)符必須是當(dāng)前詞法環(huán)境,而不是當(dāng)前代碼的。
例如:
function first(){
var a =100;
let d = 220;
{ // Block,
var b = a 100;
let c = b*10;
console.log(a,b,c,d);
}
}
first(); // 100 200 2000 220
一定不要忽略first函數(shù)中的塊級(jí)作用域,這很重要。
然后寫成抽象就是:
函數(shù)內(nèi)部的塊級(jí)作用域:
BlockEnv = {
OuterEnv: < FuncFirstEnv > ,
This : < window > ,
EnvironmentRecord:{
c:< 2000 > // 這里沒有b
}
}
函數(shù)作用域:
FuncEnv = {
OuterEnv: < GlobalEnv > ,
This : < window > ,
EnvRec:{
a:< 100 >,
d:< 220 >,
b:< 200 >
}
}
OKay,先到這里吧。
一些問題:
1、為什么用詞法環(huán)境代替作用域?
–詞法環(huán)境涵蓋了作用域,但反之則不能。
–但注意,詞法作用域和詞法作用域鏈與作用域以及作用域鏈都可通用。
2、環(huán)境記錄是什么?
–當(dāng)前環(huán)境下的標(biāo)識(shí)符-變量的映射
–但是標(biāo)識(shí)符只是“合法標(biāo)識(shí)符”的字符串形式。
–變量是是指存儲(chǔ)區(qū)的內(nèi)容,但是確切說(shuō)法是存儲(chǔ)區(qū)。
最后
我把我的筆記,重新整理后發(fā)到博客上后發(fā)現(xiàn)——我筆記干凈了好多,艸。
這種只深入核心的內(nèi)容很有用,而且在寫代碼時(shí)也變得靈活很多了。我覺得這就是最有用的地方。
最后:
個(gè)人理解,常有失誤;細(xì)細(xì)查看不知何處,望君做到心中有數(shù)。
本文轉(zhuǎn)載自:https://blog.csdn.net/krfwill/article/details/106155266
相關(guān)教程推薦:JavaScript視頻教程
更多關(guān)于云服務(wù)器,域名注冊(cè),虛擬主機(jī)的問題,請(qǐng)?jiān)L問西部數(shù)碼官網(wǎng):m.ps-sw.cn