一眼看穿?JS基本概念

命名最頭痛發表於2019-02-16

前段時間忙,好久沒更新了,繼續梳理基礎知識
這期總結的是JS的基本概念

識別符號

所謂的識別符號是指變數,函式屬性的名字,或者函式的引數

第一個字元必須是一個字母,下劃線(_)或者一個美元符號($),其他字母可以是字母,下劃線,美元符號或數字。

嚴格模式

嚴格模式是為JS定義一種不同的解析與執行模型,要啟用嚴格模式,可新增如下程式碼

"use strict"

新增區域

  • 想要整個指令碼都啟用,則加到指令碼頂部
  • 想在某個函式體內啟用,則在函式體內的頂部新增

新增目的

  • 消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為
  • 消除程式碼執行的一些不安全之處,保證程式碼執行的安全
  • 提高編譯器效率,增加執行速度
  • 為未來新版本的Javascript做好鋪墊

變數

ECMAScript的變數是鬆散型別的,所謂鬆散型別就是可以用來儲存任何型別的資料

變數的定義

  • var
  • let(ES6引入)

資料型別

ECMAScript中有7種資料型別,其中6種是基本資料型別,1種是複雜資料型別
基本資料型別 String,Number,Boolean,Null,Undefined,Symbol
複雜資料型別 Object

typeof操作符

typeof操作符用於判斷資料型別,可返回值有

  • string
  • number
  • boolean
  • undefined
  • object
  • function
  • symbol

typeof對於基本型別,除了null都可以顯示正確型別

typeof對於物件,除了函式都會顯示 object

對於 null 來說,雖然它是基本型別,但是會顯示 object,這是一個存在很久了的 Bug,因為在 JS 的最初版本中,使用的是 32位系統,為了效能考慮使用低位儲存了變數的型別資訊,000 開頭代表是物件,然而 null 表示為全零,所以將它錯誤的判斷為 object。雖然現在的內部型別判斷程式碼已經改變了,但是對於這個 Bug 卻是一直流傳下來。

如果我們想獲得一個變數的正確型別,可以通過 Object.prototype.toString.call(xx)。這樣我們就可以獲得類似 [object Type] 的字串。

只有一個值的資料型別:undefined,null

如果定義的變數準備在將來用於儲存物件,那麼最好將該變數初始化為null而不是其他值,這樣一來,只要直接檢查null值就可以知道相應的變數是否已經儲存了一個物件的引用

實際上,undefined值是派生自null值的,因此對他們的相等性測試要返回true
也就是說

null == undefined // true
null === undefined // false

Boolean(any :any) :boolean

n/a 或 N/A 指不適用的意思

資料型別 轉換為true的值 轉換為false的值
Boolean true false
String 任何非空字串 **(空字串)
Number 任何非零數字值(包括無窮大) 0和NaN
Object 任何物件 null
undefined n/a undefined
null n/a null

Number型別

八進位制字面值的第一位必須是零(0),十六進位制的字面值的前兩位必須是0x

八進位制字面量在嚴格模式下是無效的,會導致支援該模式的JS引擎丟擲錯誤

在進行算數計算時,所有以八進位制和十六進位制表示的數值最終都將被轉換成十進位制的值

儲存浮點數值需要的記憶體空間是儲存整數值的兩倍

isFinite()函式可用於測試一個數值是不是有窮的

NaN

NaN,即非數值,是一個特殊的數值,這個數值用於表示一個本來要返回數值的運算元未返回數值的情況,這樣做可以防止丟擲錯誤而停止程式碼執行

NaN特點

  • 任何涉及NaN(例:NaN/6)都會返回NaN
  • NaN與任何值都不相等,包括NaN本身

isNaN()該函式可用於確認引數是否”不是數值”,該函式接收到一個值後,會嘗試將這個值轉換為數值,而任何不能被轉換為數值的值都會導致這個函式返回true

數值轉換

有三個函式可以把非數值轉換為數值: Number()、parseInt()和parseFloat(),Number()適用於任何資料型別,而後者則專門用於把字串轉換成數值。

Number(any :any) :number

  • boolean: true和false分別被轉換成0和1
  • number: 返回原值
  • null: 返回0
  • undefined: 返回NaN
  • string:

    • 字串只包含數字,則將其轉換成十進位制數值
    • 字串中包含有效的浮點格式,則將其轉換為相應的浮點數值
    • 字串中包含有效的十六進位制格式,則將其轉換為相同大小的十進位制整數值
    • 字串為空,轉換成0
    • 字串中包含除上述格式之外的字元,將其轉換成NaN
  • object: 會先呼叫物件的valueOf()方法,然後依照前面的規則轉換返回的值,如果轉換的結果是NaN,則呼叫物件toString()方法,然後再次依照前面規則轉換返回的字串值

parseInt(str: string, base?: number) :number

  • 轉換成字串時,會忽略字串前面的空格,直至找到第一個非空格字元,如果第一個字元不是數字字元或者負號,則會返回NaN
  • 該函式會一直解析,直到遇到一個非數字字元,則停止轉換。例:parseInt(`123abc`) // 123
  • 遇到浮點數字符串,則會去小數取整。例parseInt(`11.3`) // 11
  • 如果以Ox開頭且後面跟數字字元,會將其當做一個十六進位制整數,如果字串以0開頭後跟數字字元,則會將其當作一個八進位制數來解析
  • 第二個引數是可選的,代表進位制,十六進位制則填16

parseFloat(str: string) :number

  • parseFloat和parseInt類似,只不過他可以解析整數和浮點數
  • 該函式只能解析十進位制值,因此它沒有用第二個引數指定基數的用法

String型別

  • 字串的特點是不可變的,也就是說,字串一旦建立,它們的值就不能改變。要改變某個變數儲存的字串,首先要銷燬原來的字串,然後再用另一個包含新值的字串填充該變數。

toString(base ?: number) :string

  • 該方法用於將一個值轉換為字串型別,幾乎所有型別都有這個函式,除了null和undefined, 該函式有個引數,用於設定輸出數值的基數。

String(any :any) :string

  • 該函式能將任何型別轉換成字串
  • 規則:

    • 如果值有toString()方法, 則呼叫該方法(沒有引數)並返回相應的結果
    • 如果值是null,則返回”null”
    • 如果值是undefined,則返回”undefined”

Object型別

在ECMAScript中的物件其實就是一組資料和功能的集合。物件可以通過執行new操作符後跟要建立的物件型別的名稱來建立。在不給建構函式傳遞引數時,括號可省略。
所有引用型別的值都是Object的例項

僅僅建立Object的例項並沒有什麼用處,關鍵是要理解一個重要的思想: 在ECMAScript中,Object型別是它的例項的基礎,換句話說,Object型別所具有的任何屬性和方法也同樣存在於更具體的物件中。
每個物件都具有下列屬性和方法

  • constructor: 儲存著用於建立當前物件的函式,對於前面的例子而言,建構函式就是Object()
  • hasOwnProperty(propertyName: string) :boolean, 用於檢查給定的屬性在當前物件例項中(而不是例項的原型中)是否存在。其中,作為引數的屬性名(propertyName)必須以字串形式指定。
  • toLocaleString() :string, 返回物件的字串表示,該字串與執行環境的地區對應。
  • toString() :string, 返回物件的字串表示。
  • valueOf() ,返回物件的字串、數值或布林值表示,通常與toString() 方法的返回值相同。

操作符

一元操作符(只能操作一個值的操作符)

遞增遞減操作符(++, –),包括兩類,前置型和後置型

  • 前置型指將操作符放在數值變數前面,在計算數值時優先執行變數數值
  • 後置型指將操作符放在數值變數後面,在計算數值時最後執行變數數值
  • 遞增遞減操作符適用於任何型別的值,它遵循如下規則

    • 字串數字型別時,先將其轉換為數字值,再執行加減操作,字串變數變成數值變數。
    • 非字串數字型別時,將變數值設定為NaN,字串變數變成數值變數。
    • 布林型別時,先將其轉換成0或1,再執行加減操作,布林值變數變成數值變數。
    • 浮點型別時,直接執行加減1操作。
    • 物件時,先呼叫物件的valueOf()方法,已取得一個可供操作的值,然後對該值應用前述規則。如果結果是NaN,則在呼叫toString()方法後再應用前述規則,物件變數變成數值變數

一元加和減操作符

  • 對數值應用一元加減操作符時,代表正負號。
  • 對非數值應用一元加減操作符時,相當於呼叫Number()函式。

位操作符

  • ECMAScript中的所有數值都以64位格式儲存,但位操作符不能直接操作64位的值,而是先將64位的值轉換成32位的整數,然後執行操作,最後再將結果轉換成回64位。
  • 對於有符號的整數,32位中的前31位用於表示整數的值,第32位用於表示數值的符號,0表示整數,1表示負數。
  • 負數同樣以二進位制碼儲存,但使用的格式是二進位制補碼,計算一個數值的二進位制補碼需要經過下列步驟

    • 求這個數值絕對值的二進位制碼。
    • 求二進位制反碼,即將0替換為1,1替換為0
    • 得到的二進位制反碼加1

按位非

該操作符用一條波浪線(~)表示,執行按位非的結果就是返回數值的反碼。

按位非操作的本質:運算元的負值減1

按位與

該操作符用一個和號字元(&)表示,它有兩個操作符數,同1得1,有0得0。

按位或

該操作符用一個豎線符號(|)表示,它有兩個操作符數,有1得1,同0得0。

按位異或

該操作符用一個插入符號(^)表示,它有兩個操作符數,只有一個1才得1,兩位都是1或都是0,則返回0。

左移

該操作符由兩個小於號(<<)表示,這個操作符會將數值的所有位(不包括符號位)向移動指定的位數,不足補0,左移不會影響符號位。

有符號右移

該操作符由兩個大於號(>>)表示,這個操作符會將數值的所有位(不包括符號位)向移動指定的位數,不足補0,但保留符號位。

無符號右移

該操作符由三個大於號(>>>)表示,這個操作符會將數值的所有位(32位,包括符號位)向移動指定的位數,不足補0。

布林操作符

邏輯非(!號表示)返回一個布林值,可以應用於ECMAScript中的任何值

規則:

  • 如果運算元是一個物件,返回false
  • 如果運算元是一個空字串,返回true
  • 如果運算元是一個非空字串,返回false
  • 如果運算元是數值0,返回true
  • 如果運算元是任意非0數值(包括Infinity),返回false
  • 如果運算元是null,返回true
  • 如果運算元是NaN,返回true
  • 如果運算元是undefined,返回true

同時使用兩個邏輯非操作符,實際上就會模擬Boolean()轉換函式的行為,第一個邏輯非操作會基於無論什麼運算元返回一個布林值,而第二個邏輯非操作則對該布林值求反,於是就得到了這個值真正對應的布林值,真正結果與對這個值使用Boolean()函式相同。

邏輯與(&&表示)

邏輯與操作可以應用於任何型別的運算元,而不僅僅是布林值,在有一個運算元不是布林值的情況下,邏輯與操作就不一定返回布林值

規則:

  • 如果第一個運算元是物件,則返回第二個運算元。
  • 如果第二個運算元是物件,則只有在第一個運算元的求值結果為true的情況下才會返回該物件。
  • 如果兩個運算元都是物件,則返回第二個運算元
  • 如果第一個運算元是null,則返回null
  • 如果第一個運算元是NaN,則返回NaN
  • 如果第一個運算元是undefined,則返回undefined

邏輯與操作屬於短路操作,即如果第一個運算元能夠決定結果,那麼就不會再對第二個運算元求值。對於邏輯與操作而言,如果第一個運算元是false,則它不會執行第二個運算元。

邏輯或(||表示)

和邏輯與相似,如果有一個運算元不是布林值,邏輯或也不一定返回布林值;
規則:

  • 如果第一個運算元是物件,則返回第一個運算元
  • 如果第一個運算元的求職結果為false,則返回第二個運算元
  • 如果兩個運算元都是物件,則返回第一個運算元
  • 如果兩個運算元都是null,則返回null
  • 如果兩個運算元都是NaN,則返回NaN
  • 如果兩個運算元都是undefined,則返回undefined

邏輯或也是短路操作符,如果第一個運算元的求值結果為true,就不會對第二個運算元求值了。利用邏輯或這一行為來避免為變數賦null或undefined值

乘性操作符

乘性操作符在運算元不是數值情況下會先使用Number()將其轉換為數值。

乘法(*)

規則:

  • 兩個數都為數值,則執行相應的乘法運算,若數值超出Infinity則返回Infinity或-Infinity
  • 若有一個運算元為NaN,則結果為NaN
  • 若Infinity與0相乘,則結果為NaN
  • 若Infinity與非0相乘,則結果為Infinity,符號取決於有符號運算元的符號。
  • 若Infinity與Infinity相乘,則結果是Infinity
  • 若一個運算元不是數值,則在後臺呼叫Number()將其轉換為數值,再應用上面規則

除法(/)

規則:

  • 兩個數都是數值,則執行相應的除法運算,若數值超出Infinity則返回Infinity或-Infinity
  • 若有一個運算元是NaN,則結果是NaN
  • 若Infinity被Infinity除,則結果是NaN
  • 若0被0除,則結果是NaN
  • 若非0有限數除以0,則結果是Infinity或-Infinity
  • 若Infinity被任何非零數值除,結果是Infinity或-Infinity
  • 若一個運算元不是數值,則在後臺呼叫Number()將其轉換為數值,再應用上面規則

求模(%)

規則:

  • 兩個數都是數值,則執行相應的餘數運算
  • 如果被除數是無窮大值而除數是有限大的數值,則返回NaN
  • 如果被除數是有限大的數值而除數是零,則結果是NaN
  • 如果是Infinity被Infinity除,則結果是NaN
  • 如果被除數是有限大的數值而除數是無窮大的數值,則結果是被除數
  • 如果被除數是零,則結果是零
  • 若一個運算元不是數值,則在後臺呼叫Number()將其轉換為數值,再應用上面規則

加性操作符

加法

規則:

  • 兩個數都是數值,執行常規的加法運算,根據下列數值返回結果

    • 若一個運算元是NaN,則結果是NaN
    • 若兩個運算元都是Infinity,則結果是Infinity
    • 若兩個運算元都是-Infinity,則結果是-Infinity
    • 若Infinity加-Infinity,則結果是NaN
    • (+0) + (+0) = (+0)
    • (-0) + (-0) = (-0)
    • (+0) + (-0) = (+0)
  • 若有一個運算元是字串,則根據下列規則

    • 如果兩個運算元都是字串,則將第二個運算元與第一個運算元拼接起來
    • 如果只有一個運算元是字串,則將另一個運算元轉換為字串,然後將兩個字串拼接起來
  • 若有一個運算元是物件、數值或布林值,則呼叫他們的toString()方法取得相應的字串值,然後再應用前面關於字串的規則,對於undefined和null,則分別呼叫String()函式並取得字串”undefined”和”null”

減法

規則:

  • 若兩個數都是數值,執行常規的減法運算,並返回相應的結果
  • 若一個運算元是NaN,則結果是NaN
  • 若Infinity減Infinity,則結果是NaN
  • 若-Infinity減-Infinity,則結果是NaN
  • 若Infinity減-Infinity,則結果是Infinity
  • 若-Infinity減Infinity,則結果是-Infinity
  • (+0) – (+0) = (+0)
  • (-0) – (+0) = (-0)
  • (-0) – (-0) = (+0)
  • 若有一個運算元是字串,布林值,null或undefined,則先在後臺呼叫Number()函式將其轉換為數值,然後再根據前面的規則執行減法計算,若轉換結果是NaN,則結果是NaN
  • 若有一個運算元是物件,則呼叫物件的valueOf()方法以取得表示該物件的數值,若得到的值是NaN,則減法結果就是NaN,若物件沒有valueOf()方法,則呼叫其toString()方法並將得到的字串轉換為數值

關係操作符

指小於(<),大於(>),小於等於(<=)和大於等於(>=),皆返回布林值
規則:

  • 若兩個運算元都是數值,則執行數值比較
  • 若兩個運算元都是字串,則比較兩個字串對應的字元編碼值
  • 如果一個運算元是數值,則將另一個運算元轉換為一個數值,然後執行數值比較
  • 如果一個運算元是物件,則呼叫這個物件的valueOf()方法,用得到的結果按照前面的規則執行比較,若物件沒有valueOf()方法,則呼叫toString()方法,並用得到的結果根據前面的規則執行比較
  • 若一個運算元是布林值,則先將其轉換為數值,然後再執行比較
  • 任何運算元與NaN比較,結果都是false

相等操作符

相等(==)和不相等(!=)——先轉換再比較

規則:

  • 若有一個運算元是布林值,則在比較相等性之前先將其轉換為數值,false轉換成0,true轉換成1。
  • 若一個運算元是字串,另一個運算元是數值,在比較相等性之前先將字串轉換為數值。
  • 如果一個運算元是物件,另一個運算元不是,則呼叫物件的valueOf()方法,用得到的基本型別值按照前面的規則進行比較
  • null和undefined是相等的。
  • 要比較相等性之前,不能將null和undefined轉換成其他任何值。
  • 如果有一個運算元是NaN,則相等操作符返回false,而不相等操作符返回true,即使兩個運算元都是NaN,相等操作符也返回false,因為NaN和NaN不相等
  • 如果兩個運算元都是物件,則比較它們是不是同一個物件,如果兩個運算元都指向同一物件,則相等操作符返回true,否則返回false。

全等(===)和不全等(!==)——僅比較不轉換

null==undefined會返回true,因為它們是類似的值,但null===undefined會返回false,因為它們是不同型別的值。

條件操作符

三元運算子 variable = boolean_expression ? true_value : false_value

賦值操作符

  • 乘/賦值(*=)
  • 除/賦值(/=)
  • 加/賦值(+=)
  • 減/賦值(-=)
  • 模/賦值(%=)
  • 左移/賦值(<<=)
  • 有符號右移/賦值(>>=)
  • 無符號右移/賦值(>>>=)

所有的賦值操作符規則都一樣

let num = 10
num += 1 // 等價於 num = num + 1

逗號操作符

逗號操作符可以在一條語句中執行多個操作

var num1 = 1, num2 = 2, num3 = 3; 

逗號操作符多用於宣告多個變數,除此之外,還可以用於賦值,在賦值時,逗號操作符總會返回表示式的最後一項

let num = (5, 1, 4, 3, 0); // num的值為0

語句

各語言的語句都差不多,這裡就不一一介紹了,這裡只列舉

  • if語句
  • do-while語句
  • while語句
  • for語句
  • for-in語句,迭代語句,可用來列舉物件的屬性; 如果表示要迭代的物件的變數值為null或undefined,for-in語句會丟擲錯誤,ES5雖然修正這一行為,他不會丟擲錯誤,只是不執行迴圈體,但是在使用for-in迴圈之前,先檢測確認該物件的值是不是null或undefined
  • label語句
  • break和continue語句,break和contiune的區別在於,break是退出當前迴圈體; continue是退出當前迴圈,繼續執行下一個迴圈
  • with語句,作用是把程式碼作用域設定到一個特定的物件中,目的是為了簡化多次編寫同一個物件的工作。大量使用with語句會導致效能下降。
  • switch語句,switch中可以使用任何的資料型別,無論是字串還是物件,case的值可以是常量,變數和表示式。switch中使用的是全等操作符,不會發生型別轉換

js裡面的函式沒有簽名,函式過載也不可能實現,即不能定義相同名字的函式,通過引數個數的多少來呼叫相應的函式

相關文章