您好,登錄后才能下訂單哦!
本篇適合javascript新手或者學了前端一段時間,對js概念不清晰的同學~~。
學習目的
本文針對javascript基礎薄弱的同學,可以加深對javascript的理解。
本文將講述以下幾點對于初學者開說javascript(有的是大部分語言都有的)的坑
講解內容如下:
1. 連等
2. i++
3. 包裝對象
4. 引用類型
5. && 與 ||
講解部分
1. 連等
小試牛刀
連等是常見的表達式,但是并不是所有情況都適合連等,連等只適用于字面量并不適用于引用類型。
// 字面量連等得到想要的結果 var a,b; a = b = 2; a // 2 b // 2 // 引用類型連等不可預測 var arr1, arr2; arr1 = arr2 = [] arr1[0] = 10 arr2[0] // 10 //引用類型連等使得兩個引用指向一個對象,操作其中一個,兩個值都變
以上代碼是常見的連等,有時候我們需要兩個變量同賦值為一個值,我們就這樣來操作,但是,如果是引用類型可不能連等賦值哦。
此外,連等賦值會有一個很大的漏洞,就是會將變量泄露到全局中去,上面代碼我們沒有將其泄露,但看下面代碼:
function fn (num) { var a = b = num; a // num b // num } fn(10) a // 報錯 b // 10 // 我們并不沒有定義全局變量b
可以看到,我們執行了fn函數后,全局作用域中出現了b變量,這是為什么?看 var a = b = num這句話,這句話可以分成兩句來看
var a a = b = num //只聲明了a
我們其實只聲明了a變量,連等的b并沒有聲明,由此可以知道,b被掛在了全局的window對象上,造成了變量泄露到了全局。
初出茅廬
上面只是簡單的例子,接下來我們看一個復雜點的例子
var a = {x: 1} var b = a a.x = a = {y: 1} a.x // undefined b.x // {y: 1}
這個例子是在一個測試題中看到的,乍一看,好像不明覺厲,但是一點都不難理解。
1. a 和 b是引用了類型,同指向了一個對象 {x: 1}
2. a.x 引用了原對象的x屬性, a 則為一個引用變量
3. a = {y: 1} 只是將a這個引用變量的指針指向了另一個對象{y: 1}
4. a.x = a,前者還是代表著原來的對象的x屬性,也就是b引用的對象的x屬性
5. 賦值完畢。
可能你還沒有理解,不要急,下面我們將解剖javascript引擎讓你懂的明明白白
庖丁解牛
引擎的工作原理: 引擎在解析javascript表達式時,會進行LHS查詢, RHS查詢(詳見《你不知道的javascript》),我將它們理解為LHS(賦值),RHS(查找)。
下面,就上面例子,我們來演示一下引擎的工作流程
var a = {x: 1} // 引擎:我將要對a變量LHS(賦值),內容是{x: 1} // 作用域: 剛聲明了a變量,給你。 var b = a // 引擎: 我將要對a變量RHS(查找) // 作用域: 你剛剛給它LHS了,給你吧 // 引擎: 我將要對b變量LHS(賦值),內容為a變量指向的對象 // 作用域:剛聲明了b變量,給你。 a.x = a = {y: 1} // 引擎:我將要對a進行LHS(賦值),內容是另一個對象{y:1} // 作用域:可以,給你,但好像還有其他命令,先不要賦值。 // 引擎: 是的,下一步我還需要對a.x 進行LHS(賦值),內容是將要改變的a變量 // 作用域: 可以,a變量指向的對象有x屬性,不過馬上a就改變了,不過沒關系,b變量也指向那個對象,賦值完后,你可以用b變量引用舊對象。 // 引擎:了解了,我先把a變量賦值為一個新的對象,然后把原來的a變量指向的對象的x屬性賦值為 新a。 a.x // undefined // 引擎: 我需要拿到a變量指向的對象的x屬性 // 作用域: 你剛剛改變了a的指向,現在的a指向的對象已經沒有x屬性了 b.x // {y: 1} // 引擎: 我需要拿到b變量指向的對象的x屬性 // 作用域: 你是想拿到你舊對象的x屬性吧,給你,不過已經被你在之前改變了值,現在b.x的值就是a指向的新對象的值。
以上是我的理解,沒有權威認證。想詳細了解執行過程,請參考《你不知道的javascript》,如果本節有誤,請指出。
2. ++操作符
大家最很常用 ++ 操作符,其實也沒什么很大奇特之處,但是對于新手入門的你是否真正了解他。
var a = 1; var b = a++ a // 2 b // 1 var c = 1; var d = ++ c; c // 2 d // 2
前++和后++,一個是返回表達式自增后一個是返回表達式自增前的值。我們可以把兩個進行分解,看一下過程。
b = a++ // 等價于 ... b = a a = a + 1 //......................... b = ++ a // 等價于 ... a = a + 1 b = a
只是一個運算順序問題,這個可能好理解,但是也有一個坑,如下。
前幾天一個人問: 1++ 等于幾?答: 2
估計很多人第一反應就是2,但是這大錯特錯!那為什么不等于2呢,其實 1++是報錯了,并不是合法的表達式,原因如下:
1 ++ // 等價于 1 = 1 + 1 // 引擎對 1 進行LHS(賦值),作用域發現他是非法變量,所以會報錯 左值無效。
3. 包裝對象
我們在用字符串獲取長度、使用方法截取等行為時,你有沒有想過: 字面值只是個值,為什么他會有方法屬性,不是應該對象才有的嗎?的確是對象才有的,但是在執行表達式時,產生了包裝對象。也許你看過了此知識點,可以跳過。
var str = 'hello' str.length // 5 str.aaa = 5 str.aaa // undefined
我們定義一個str字符串,獲取長度為5,但是我們自己加一個屬性aaa缺獲取不到,這需要用包裝對象的聲明周期來解答:包裝對象的聲明周期只存在于一個表達式內
var str = 'hello' str.length // 等價于 new String(str).length str.aaa = 5 //等價于 new String(str).aaa = 5 str.aaa // 等價于 new String(str).aaa
也就是說,每一次用到str屬性時,都是先包裝成String對象,操作完后,對象釋放,可見,以上兩次str.aaa是不同的對象,所以第二次獲取aaa屬性當然沒有了。不了解可以百度一下js包裝對象,有詳細的解答。
4. 引用類型
大部分語言都有引用類型,其實就是對象變量。c語言中,我們將引用類型理解為指針,這個指針是動態指向一塊內存,通過代碼的變化,指針的指向會隨之改變。js也一樣。
在我們書寫代碼中,一定要記住引用類型變量和字面值變量的 區別,他們分別有不同的用處。
var global = new Object() function setColor (obj) { obj.color = 'blue' obj = new Object() obj.color = 'red' } setColor(global) global.color // blue
這是《javascript高級程序設計》里面的一個例子,我們傳遞一個對象global到setColor函數里,在內部進行了如上操作,我們打印出global.color是blue,為什么不是red?這里就是引用類型的結果。
1. global變量是引用類型,他指向一個對象,
2. 傳遞到setColor函數中,obj就引用了global指向的對象(下面稱為globalObj)
3. 給globalObj賦值一個color屬性為blue字符串,這時global.color是blue了
4. 將obj指向另一個新對象localObj,使得obj與global斷開連接。
5. 將localObj.color賦值為‘red'
可以看出,我們并沒有對global對象的color進行'red'賦值,'red'賦值給了另一個對象的color屬性。
結論:引用類型傳遞是將兩個變量指向同一個對象,而字面量的傳遞僅僅是值的賦值傳遞。我們可以將引用類型傳遞到函數進行改變,不可以在函數內改變傳遞進來的字面值。
5. && 與 ||
兩者的基本運用相信大家都了解,大部分用來if判斷,如:
var a = 2; var b = false if (a && b) { alert('best') } if (a || b) { alret('good') // 運行 }
他們的用法不局限于判斷 左右兩邊的 && 和 || 關系,還可以用來提供代碼的質量
var obj = {} if (obj.info.user === 'xu') { // terrible // .. } if (obj.info && obj.info.user === 'xu' ) { // good // ... }
如果僅僅判斷obj.info.user 會報錯造成程序終止,但是下面那樣判斷就大使得代碼健壯,不會那么容易崩潰。
重點: && 和 || 并不會返回true和false,他會返回終止此表達式的那個變量值。
true && 6 // 6 NaN && false // NaN '0' || 6 // '0' false || true // true false || 0 && 1 // 0 false || 1 && 0 // 0
&&和||, &&優先級大于||。
&&操作符,如果左邊為假,返回左邊值,否則,始終返回右邊值
||操作符,如果左邊為真,返回左邊值, 否則,始終返回右邊值。
結尾
javascript基礎本章簡單的介紹在這里,內容并不全面,還請多多見諒。如有錯誤,請指出。。。。
以上就是本文的全部內容,希望本文的內容對大家的學習或者工作能帶來一定的幫助,同時也希望多多支持億速云!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。