精品伊人久久大香线蕉,开心久久婷婷综合中文字幕,杏田冲梨,人妻无码aⅴ不卡中文字幕

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
JavaScript高級程序設計讀書筆記

JavaScript簡介

JavaScript簡史

JavaScript 誕生于 1995 年。


JavaScript實現

一個完整的 JavaScript 實現由下列三個不同的部分組成:

  1. 核心(ECMAScript);
  2. 文檔對象模型(DOM);
  3. 瀏覽器對象模型(BOM);

ECMAScript

ECMA-262 標準沒有參照 web 瀏覽器,它規定了這門語言的下列組成部分:語法、類型、語句、關鍵字、保留字、操作符、對象。


文檔對象模型(DOM)

文檔對象模型(DOM,Document Object Model)是針對 XML 但經過擴展用于 HTML 的應用程序編程接口(API)。


瀏覽器對象模型(BOM)

瀏覽器對象模型(BOM,Browser Object Model)從根本上將,BOM 只處理瀏覽器窗口和框架,但人們習慣上也把所有針對瀏覽器的 JavaScript 擴展算作 BOM 的一部分,下面就是一些這樣的擴展:

  • 彈出新瀏覽器窗口的功能;
  • 移動、縮放和關閉瀏覽器窗口的功能;
  • 提供瀏覽器詳細信息的 navigator 對象;
  • 提供瀏覽器所加載頁面的詳細信息的 location 對象;
  • 提供用戶顯示器分辨率詳細信息的 screen 對象;
  • 對 cookies 的支持;
  • 像 XMLHttpRequest 和 IE 的 ActiveXObject 這樣的自定義對象;

小結

JavaScript 是一種專門與網頁交互而設計的腳本語言,由下列三個部分組成:

  1. ECMAScript,由 ECMA-262 定義,提供核心語言功能;
  2. 文檔對象模型(DOM),提供訪問和操作網頁內容的方法和接口;
  3. 瀏覽器對象模型(BOM),提供與瀏覽器交互的方法和接口;

在HTML中使用JavaScript

script元素

向 HTML 頁面中插入 JavaScript 的主要方法就是使用 <script> 元素。

使用 <script> 元素的方式有兩種:直接在頁面中嵌入 JavaScript 代碼和包含外部 JavaScript 文件。

注意:使用 <script> 引入外部 JavaScript 文件時,不要在標簽內添加額外的 JS 代碼,如果添加了將會被忽略。


標簽的位置

按照傳統的做法,所有 <script> 元素都應該放在頁面中 <head> 元素中,這種做法的目的就是把所有外部文件(CSS文件和JavaScript文件)的引用都放在相同的地方。

可是這種做法有一種缺點就是,必須要等到全部 JS 代碼都被下載、解析和執行完成以后,才能開始出現頁面的內容(瀏覽器在遇到 <body> 標簽時才開始出現內容)。對于需要很多 JS 代碼的頁面來說,這會導致頁面出現明顯的延遲,而在延遲期間頁面是一片空白。所以,為了避免這個問題,我們應該把 JS 引用放在 <body> 結束標簽前面,即:

<body> 
    <!--  html代碼  -->   
    <script type="text/javascript" src="index.js"></script>
</body>

延遲腳本

<script> 標簽的 defer 屬性用途是表明腳本在執行時不會影響頁面的構造。也就是說,腳本會被延遲到整個頁面都解析完畢后再運行。因此,在 <script> 元素中設置 defer 屬性,相當于告訴瀏覽器立即下載,但延遲執行。

假設把 <script> 元素放在 <head> 元素之中,并加上 defer 屬性,但其中包含的腳本將延遲到瀏覽器遇到 </html> 標簽后再執行。HTML5 規范要求腳本按照它們出現的先后順序執行,因此第一個延遲腳本會先于第二個延遲腳本執行,而這兩個腳本會先于 DOMContentLoaded 事件執行。但在現實中,延遲腳本不一定會按順序執行,也不一定會在 DOMContentLoaded 事件觸發前執行,因此最好只包含一個延遲腳本。

defer 屬性只適用于外部腳本文件。


異步腳本

HTML5 為 <script> 元素定義了 async 屬性。與 defer 屬性類似,都用于改變處理腳本的行為,也只適用于外部腳本文件,并告訴瀏覽器立即下載文件。但不同的是,標記為 async 的腳本并不保證按照指定它們的先后順序執行。

例如,在 <head> 元素中放兩個 <script> 元素。第二個腳本文件可能會在第一個腳本文件前執行。指定 async 屬性的目的是不讓頁面等待兩個腳本下載和執行,從而異步加載頁面其他內容。因此,建議異步腳本不要在加載期間修改 DOM。

異步腳本一定會在頁面的 load 事件前執行,但可能會在 DOMContentLoaded 事件觸發前或后執行。


嵌入代碼與外部文件

使用外部文件的優點:

  1. 可維護性;
  2. 可緩存;
  3. 適應未來;

文檔模式

兩種文檔模式:混雜模式(quirks mode)、標準模式(standards mode)。


noscript元素

這個元素用以在不支持 JS 的瀏覽器中顯示替代的內容。

包含 <noscript> 元素中的內容只有在下面的情況才會顯示出來:

  1. 瀏覽器不支持腳本;
  2. 瀏覽器支持腳本,但腳本被禁用;

基本概念

語法

區分大小寫

ECMAScript 中的一切(變量、函數名和操作符)都區分大小寫。


標識符

標識符就是指變量、函數、屬性的名字,或函數的參數。

標識符按照以下規則組合:

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

不能把關鍵字、保留字、true、false、null 用作標識符。


注釋

// 單行注釋

/*
這是多行注釋
這是多行注釋
*/

嚴格模式

嚴格模式是為 JS 定義了一種不同的解析與執行模型。在嚴格模式下,一些不確定的行為將得到處理,對某些不安全的操作會拋出錯誤。

要在整個腳本中啟用嚴格模式,可以在頂部添加下列代碼:

"use strict";

它是一個編譯指示(pragma),用來告訴支持 JS 引擎切換到嚴格模式。

可以指定函數在嚴格模式下執行:

function doSomething(){
    "use strict";
    //函數體
}

語句

ECMAScript 中語句以一個分號結尾。如果省略分號,則由解析器確定語句的結尾。

雖然語句結尾的分號并不是必須的,但最好還是不要省略。因為加上分號可以避免很多錯誤,也會在某些情況下增進代碼性能。


關鍵字和保留字

關鍵字可用于表示控制語句的開始或結束,或用于執行特定操作等。關鍵字不能用作標識符。

ECMA-262 還描述了一組不能用作標識符的保留字


變量

ECMAScript 的變量是松散類型的,就是可以用來保存任何類型的數據。

定義變量時要使用 var 操作符(var是一個關鍵字),后跟變量名(即標識符)。

如果省略 var 操作符可以定義全局變量,但這也不是我們所推薦的。因為在局部作用域中定義的全局變量很難維護,而且如果有意地忽略了 var 操作符,也會由于相應變量不會馬上就有定義而導致不必要的混亂。給未經聲明的變量賦值在嚴格模式下會拋出 ReferenceError 錯誤。


數據類型

簡單數據類型(基本數據類型):undefined、null、boolean、number、string、symbol(ES 6新引入的數據類型)。

復雜數據類型:object。

typeof操作符

typeof 用來檢測給定變量的數據類型,只適用于基本數據類型的類型判斷。

對一個值使用 typeof 操作符可能返回下列某個字符串:

  • “undefined” - 如果這個值未定義;
  • “boolean” - 如果這個值是布爾值;
  • “string” - 如果這個值是字符串;
  • “number” - 如果這個值是數值;
  • “object” - 如果這個值是對象或 null;
  • “function” - 如果這個值是函數;

undefined類型

undefined 類型只有一個值,即特殊的 undefined。在使用 var 聲明變量但未對其加以初始化時,這個變量的值就是 undefined。

對未初始化的變量執行 typeof 操作符會返回 undefined 值,而對未聲明的變量執行 typeof 操作符同樣也會返回 undefined 值。


null類型

null 類型也只有一個值,這個特殊的值是 null。

使用 typeof 操作符檢測 null 值時會返回 “object” :

var car = null
alert(typeof car);    // "object"

boolean類型

boolean 類型只有兩個值:true、false

注意:boolean 類型的值是區分大小寫的,True、False(以及其他的混合大小寫形式)都不是 boolean 的值,只是標識符。

要將一個值轉換為其對應的 boolean 值,可以調用轉型函數 Boolean()。


number類型

八進制字面值的第一位必須是零(0),然后是八進制數字序列(0~7)。如果字面值中的數值超出了范圍,那前導零將被忽略,后面的數值將被當作十進制數解析。

十六進制字面值的前兩位必須是0x,后面跟任何十六進制數字(09及AF),其他A~F可以大寫,也可以小寫。

在進行算術計算時,所有以八進制、十六進制表示的數值最后將被轉換成十進制數值。


浮點數值

浮點數值就是該數值中必須包含一個小數點,并且小數點后面必須至少有一位數字。


數值范圍

ECMAScript 能夠表示的最小數值存在 Number.MIN_VALUE 中,在大多數瀏覽器中,這個值是 5e-324。

ECMAScript 能夠表示的最大數值存在 Number.MAX_VALUE 中,在大多數瀏覽器中,這個值是 1.7976931348623157e+308。

如果計算結果超出了 JavaScript 數值范圍時,那么這個數值將被自動轉換成 Infinity 值。如果這個數值為負數,將被轉換成 -Infinity(負無窮),如果這個數值為正數,將被轉換成 Infinity(正無窮)。


NaN

即非數值是一個特殊的數值,這個數值用于表示一個本來要返回數值的操作數未返回數值的情況(這樣就不會拋出錯誤)。

有兩個特點。首先,任何涉及 NaN 的操作都會返回 NaN,這個特點在多步計算中有可能導致問題。其次,NaN 與任何值都不相等,包括 NaN 本身。

alert(NaN == NaN);    // false

針對這兩個特點,ECMAScript 定義了 isNaN() 函數。這個函數接受一個參數,該參數可以是任何類型,而函數會幫我們確定這個參數是否“不是數值”。某些不是數值的值會直接轉換為數值。

alert(isNaN(NaN));    // true
alert(isNaN(10));       // false(10是數值)
alert(isNaN("10"));    // false(可以被轉換成數值10)
alert(isNaN("blue"));    // true(不能轉換為數值)
alert(isNaN(true));    // false(可以被轉換成數值1) 

數值轉換

有三個函數可以把非數值轉換為數值:Number()、parseInt()、parseFloat()。

Number() 函數可以用于任何數據類型,另外兩個函數則專門用于把字符串轉為數值。這三個函數對于同樣的輸入會有返回不同的結果。

Number() 函數的轉換規則:

  • 如果是 boolean 值,true、false 將分別轉為 1 和 0。
  • 如果是數字值,只是簡單的傳入和返回。
  • 如果是 null 值,返回 0。
  • 如果是 undefined,返回 NaN。
  • 如果是字符串,遵循下列規則:
    1. 如果字符串中只包含數字(包括帶正負號情況),則將其轉換為十進制數值(前導的零會被忽略)。
    2. 如果字符串中包含有效的浮點格式,則將其轉換為對應的浮點數值(前導的零會被忽略)。
    3. 如果字符串中包含有效的十六進制格式,則將其轉換為相同大小的十進制數值。
    4. 如果字符串為空(不含任何字符),則將其轉換為 0。
    5. 如果字符串中包含除上述格式以外的字符,則將其轉換為 NaN。
  • 如果是對象,則調用對象的 valueOf() 方法,然后依照前面的規則轉換返回的值。如果轉換結果為 NaN,則調用對象的 toString() 方法,然后再依照前面的規則轉換返回的字符串值。

string類型

string 類型用于表示由零或多個 16 位 Unicode 字符組成的字符序列,即字符串。

字符字面量

String 數據類型包含一些特殊的字符字面量,也叫轉義序列。

\n 換行
\t 制表
\b 退格
\r 回車
\f 進紙
\\ 斜杠
' 單引號(')
" 雙引號(")


字符串的特點

ECMAScript 的字符串是不可變的,也就是說,字符串一旦創建,它們的值就不能改變。如果要改變某個變量保存的字符串,首先要摧毀原來的字符串,然后再用另一個包含新值得字符串填充該變量。


轉換為字符串

把一個值轉換為一個字符串有兩種方式。第一種是使用幾乎每個值都有得 toString() 方法。

在不知道要轉換的值是不是 null 或 undefined 的情況時,還可以使用轉型函數 String(),這個函數能夠將任何類型的值轉換為字符串。

String()函數遵循下列轉換規則:

  • 如果值由 toString() 方法,則調用該方法(沒有參數)并返回相應的結果。
  • 如果值是 null,則返回 "null"。
  • 如果值是 undefined,則返回 "undefined"。

Object類型

ECMAScript 中的對象其實就是一組數據和功能的集合。

對象可以通過執行 new 操作符后跟要創建的對象類型的名稱來創建。而創建 Object 類型的實例并為其添加屬性和(或)方法,就可以創建自定義對象。

Object 的每個實例都具有下列屬性和方法:

  • constructor:保存著用于創建當前對象的函數。
  • hasOwnProperty(propertyName):用于檢查給定的屬性在當前對象實例中是否存在。
  • isPrototypeOf(object):用于檢查傳入的對象是否是當前對象的原型。
  • propertyIsEnumerable(propertyName):用于檢查給定的屬性是否能夠使用 for-in 語句來枚舉。
  • toLocaleString():返回對象的字符串表示,該字符串與執行環境的地區對應。
  • toString():返回對象的字符串表示。
  • valueOf():返回對象的字符串、數值或布爾值表示,通常與 toString() 方法的返回值相同。

操作符

操作符包括算術操作符(如加號和減號)、位操作符、關系操作符、相等操作符

一元操作符

只能操作一個值的操作符叫一元操作符。

遞增和遞減操作符

前置型、后置型。前置型應該位于要操作的變量之前,后置型應該位于要操作的變量之后。

執行前置遞增和遞減操作時,變量的值都是在語句被求值以前改變的。

后置的遞增和遞減操作是在包含它們的語句被求值之后才執行的。

在應用于不同的值時,遞增和遞減操作符遵循下列規則:

  • 在應用于一個包含有效數字字符的字符串時,先將其轉換為數字值,再執行加減 1 的操作。字符串變量變成數值變量。
  • 在應用于一個不包含有效數字字符的字符串時,將變量的值設置為 NaN。字符串變量變成數值變量。
  • 在應用于布爾值 false 時,先將其轉換為 0 再執行加減 1 的操作。布爾值變量變成數值變量。
  • 在應用于布爾值 true 時,先將其轉換為 1 再執行加減 1 的操作。布爾值變量變成數值變量。
  • 在應用于浮點數值時,執行加減 1 的操作。
  • 在應用于對象時,先調用對象的 value() 方法以取得一個可供操作的值。然后對該值應用前述規則。如果結果是 NaN,則在調用 toString() 方法后再應用前述規則。

一元加和減操作符

一元加操作符以一個加號(+)表示,放在數值前面,對數值不會產生任何影響。

一元減操作符主要用于表示負數。


位操作符

位操作符不直接操作 64 位的值,而是先將 64 位的值轉換成 32 位的整數,然后執行操作,最后再將結果轉換回 64 位。

對于有符號的整數,32 位中的前 31 位用于表示整數的值。第 32 位表示數值的符號:0表示正數,1表示負數。這個表示符號的位叫符號位

負數以二進制碼存儲,使用的格式是二進制補碼,計算一個數值的二進制補碼,經過以下步驟:

  1. 求這個數值絕對值的二進制碼;
  2. 求二進制反碼,即將 0 替換為 1,1 替換為 0;
  3. 得到的二進制反碼加 1。
    根據這 3 個步驟求 -18 的二進制碼,首先求 18 的二進制碼:
    0000  0000  0000  0000  0000  0000  0001  0010
    然后,求其二進制反碼:
    1111  1111  1111  1111  1111  1111  1110  1101
    最后,二進制反碼加1:
    1111  1111  1111  1111  1111  1111  1110  1101
                                   1
    -------------------------------------------------------------------------------
    1111  1111  1111  1111  1111  1111  1110  1110
    就求得-18的二進制表示。

如果對非數值應用位操作符,會先使用 Number() 函數將該值轉換為一個數值,然后再應用位操作,得到的結果是一個數值。


按位非(NOT)

按位非操作符由一個波浪線(~)表示。

執行按位非得結果就是返回數值得反碼。

按位非操作的本質:操作數的負值減 1。

按位非是在數值表示的最底層執行操作,因此速度更快。


按位與(AND)

按位與操作符由一個和號字符(&)表示,它由兩個操作符數。

按位與操作只在兩個數值的對應位都是 1 時才返回 1,任何一位是 0,結果都是 0。


按位或(OR)

按位或操作符由一個豎線(|)表示,也有兩個操作符。

按位或操作在有一個位是 1 的情況下就返回 1,而只有在兩個位都是 0 的情況下才返回 0。


按位異或(XOR)

按位異或操作符由一個插入符號(^)表示,也有兩個操作符。

按位異或操作在兩個數值對應位上只有一個 1 時才返回 1,如果對應的兩位都是 1 或 0,則返回 0。


左移

左移操作符由兩個小于號(<<)表示,這個操作符會將數值的所有位向左移動指定的位數。

在向左移位后,原數值的右側就多出了空位,就用 0 來填充空位。

左移不會影響操作數的符號位。


有符號的右移

有符號的右移操作符由兩個大于號(>>)表示,這個操作符會將數值向右移動,但保留符號位(即正負號標記)。

在右移過程中,原數值出現空位,用符號位的值來填充空位。


無符號右移

無符號右移操作符由 3 個大于號(>>>)表示,這個操作符會將數值的所有 32 位都向右移動。對正數來說,無符號右移的結果與有符號右移相同。

對于負數來說,無符號右移是以 0 來填充空位。


布爾操作符

布爾操作符一共有 3 個:非(NOT)、與(AND)、或(OR)

邏輯非

邏輯非操作符由一個嘆號(!)表示。邏輯非操作符首先會將它的操作數轉換為一個布爾值,然后再對其求反。

邏輯非操作符遵循以下規則:

  • 如果操作數是一個對象,返回 false;
  • 如果操作數是一個空字符串,返回 true;
  • 如果操作數是一個非空字符串,返回 false;
  • 如果操作數是數值 0,返回 true;
  • 如果操作數是任意非 0 數值(包括Infinity),返回 false;
  • 如果操作數是 null,返回 true;
  • 如果操作數是 NaN,返回 true;
  • 如果操作數是 undefined,返回 true。

邏輯非操作符也可以用于將一個值轉換為與其對應的布爾值,用同時使用兩個邏輯非操作符(!!)。


邏輯與

邏輯與操作符由兩個和號(&&)表示,有兩個操作數。

在有一個操作數不是布爾值的情況下,邏輯與操作不一定返回布爾值,此時遵循下列規則:

  • 如果第一個操作數是對象,則返回第二個操作數;
  • 如果第二個操作數是對象,則只有在第一個操作數的求值結果為 true 的情況下才會返回該對象;
  • 如果兩個操作數都是對象,則返回第二個操作數;
  • 如果第一個操作數是 null,則返回 null;
  • 如果第一個操作數 NaN,則返回 NaN;
  • 如果一個操作數是 undefined,則返回 undefined。

邏輯與操作屬于短路操作,即第一個操作數能夠決定結果,那么就不會再對第二個操作數求值。


邏輯或

邏輯或操作符由兩個豎線符號(||)表示,也有兩個操作數。

遵循以下規則:

  • 如果第一個操作數是對象,則返回第一個操作數;
  • 如果第一個操作數的求值結果為 false,則返回第二個操作數;
  • 如果兩個操作數都是對象,則返回第一個操作數;
  • 如果兩個操作數都是 null,則返回 null;
  • 如果兩個操作數都是 NaN,則返回 NaN;
  • 如果兩個操作數都是 undefined,則返回 undefined。

邏輯或操作符也是短路操作符,如果第一個操作數的求值結果為 true,就不會對第二個操作數求值。


乘性操作符

3 個乘性操作符:乘法、除法、求模

乘法

乘法操作符由一個星號(*)表示,用于計算兩個數值的乘積。

在處理特殊值情況下,遵循下列特殊規則:

  • 如果操作數都是數值,執行常規的乘法計算;
  • 如果有一個操作數是 NaN,則結果是 NaN;
  • 如果是 Infinity 與 0 相乘,則結果是 NaN;
  • 如果是 Infinity 與非 0 數值相乘,則結果是 Infinity 或 -Infinity,取決于有符號操作符的符號;
  • 如果是 Infinity 與 Infinity 相乘,則結果是 Infinity;
  • 如果有一個操作數不是數值,則在后臺調用 Number() 將其轉換為數值,然后再應用以上規則。

除法

除法操作符由一個斜線符號(/)表示,執行第二個操作數除第一個操作數的計算。

在處理特殊值情況下,遵循下列特殊規則:

  • 如果操作數都是數值,執行常規的除法計算;
  • 如果有一個操作數是 NaN,則結果是 NaN;
  • 如果是 Infinity 被 Infinity 除,則結果是 NaN;
  • 如果是零被零除,則結果是 NaN;
  • 如果是非零的有限數被零除,則結果是 Infinity 或 -Infinity,取決于有符號操作數的符號;
  • 如果是 Infinity 被任何非零數值除,則結果是 Infinity 或 -Infinity,取決于有符號操作數的符號;
  • 如果有一個操作數不是數值,則在后臺調用 Number() 將其轉換為數值,然后再應用以上規則。

求模

求模(余數)操作符由一個百分號(%)表示。

在處理特殊值情況下,遵循下列特殊規則:

  • 如果操作數都是數值,執行常規的除法計算,返回除得的余數;
  • 如果被除數是無窮大值而除數是有限大的數值,則結果是 NaN;
  • 如果被除數是有限大的數值而除數是零,則結果是 NaN;
  • 如果是 Infinity 被 Infinity 除,則結果是 NaN;
  • 如果被除數是有限大的數值而除數是無窮大的數值,則結果是被除數;
  • 如果被除數是零,則結果是零;
  • 如果有一個操作數不是數值,則在后臺調用 Number() 將其轉換為數值,然后再應用以上規則。

加性操作符

加法

加法操作符(+)

如果兩個操作符都是數值,執行常規的加法計算,然后根據下列規則返回結果:

  • 如果有一個操作數是 NaN,則結果是 NaN;
  • 如果是 Infinity 加 Infinity,則結果是 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() 方法,并用得到的結果根據前面規則比較;
  • 如果一個操作數是布爾值,則先將其轉換為數值,然后再比較。

相等操作符

ES 提供兩組操作符:相等和不相等——先轉換再比較,全等和不全等——僅比較不轉換。

相等和不相等

相等操作符由兩個等于號(==)表示,如果兩個操作數相等,返回 true。

不相等操作符由嘆號后跟等于號(!=)表示,如果兩個操作數不相等,返回 false。

這兩個操作符都會先轉換操作數(通常稱為強制轉型),然后比較它們的相等性。

在轉換不同數據類型時,遵循下列規則:

  • 如果有一個操作數是布爾值,則在比較相等性之前先將其轉換為數值,false 轉換為 0,true 轉換為 1;
  • 如果一個操作數是字符串,另一個操作數是數值,在比較相等性之前先將字符串轉換為數值;
  • 如果一個操作數是對象,另一個操作數不是,則調用 valueOf() 方法,用得到的基本類型值按照前面規則比較;

這兩個操作符在比較時遵循下列規則:

  • null 和 undefined 是相等的;
  • 比較相等性之前,不能將 null 和 undefined 轉換成其他任何值;
  • 如果有一個操作數是 NaN,則相等操作符返回 false,而不相等操作符返回 true。注意:即使兩個操作數都是
  • 如果兩個操作數都是對象,則比較它們是不是同一個對象。如果兩個操作數都指向同一個對象,則相等操作符返回 true;否則返回 false。

全等和不全等

全等操作符由 3 個等于號(===)表示,它只在兩個操作數未經轉換就相等的情況下返回 true。

不全等操作符由一個嘆號后跟兩個等于號(!==)表示,它在兩個操作數未經轉換就不相等的情況下返回 true。

注意:null == undefined 返回 true,因為它們是類似的值;但 null === undefined 會返回 false。


條件操作符

條件操作符遵循與 Java 中的條件操作符相同的語法形式。


賦值操作符

簡單的賦值操作符由等于號(=)表示,其作用就是把右側的值賦給左側的變量。

如果在等于號(=)前面再添加乘性操作符、加性操作符或位操作符,就可以完成復合賦值操作。

每個主要算術操作符都有對應的復合賦值操作符,這些操作符如下:

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

逗號操作符

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

逗號操作符多用于聲明多個變量,還可以用于賦值。用于賦值時,逗號操作符總會返回表達式中的最后一項。


語句

語句通常使用一或多個關鍵字來完成給定任務。

if語句

語法如下:

if(condition){
    statement1
}else{
    statement2
}

其中的 condition(條件)可以是任意表達式。如果對 condition 求值的結果為 true,則執行 statement1(語句1),否則執行 statement2(語句2)。


do-while語句

do-while 語句是一種后測試循環語句,即只有在循環體中的代碼執行之后,才會測試出口條件。換句話說,在對條件表達式求值之前,循環體內的代碼至少會被執行一次。語法如下:

do{
    statement
}while(expression);

while語句

while 語句屬于前測試循環語句,也就是說,在循環體內的代碼被執行之前,就會對出口條件求值。因此,循環體內的代碼有可能永遠不會被執行。語法如下:

while(expression){
    statement
}

for語句

for 語句也是一種前測試循環語句,但它具有在執行循環之前初始化變量和定義循環后要執行的代碼能力。語法如下:

for(initialization;expression;post-loop-expression){
    statement
}

在 for 循環的變量初始化表達式中,也可以不使用 var 關鍵字,該變量的初始化可以在外部執行。

for 語句中的初始化表達式、控制表達式和循環后表達式都是可選的,如果將三個表達式全部省略,就會創建一個無限循環。


for-in語句

for-in 語句是一種精準的迭代語句,可以用來枚舉對象的屬性。語法如下:

for(property in expression){
    statement
}

如果表示要迭代的對象的變量值為 null 或 undefined,for-in 語句會拋出錯誤。ES5 更正了這一行為,對這種情況不再拋出錯誤,而只是不執行循環體。為了保證最大限度的兼容性,建議在使用 for-in 循環之前,先檢測該對象的值不是 null 或 undefined。


label語句

使用 label 語句可以在代碼中添加標簽,以便將來使用。語法如下:

label: statement

示例:

start:for(var i = 0; i < count; i++){
    alert(i);
}

break和continue語句

break 和 continue 語句用于在循環中精確地控制代碼的執行。

break 語句會立即退出循環,強制繼續執行循環后面的語句。continue 語句雖然也是立即退出循環,但退出循環后會從循環的頂部繼續執行。


with語句

with 語句的作用是將代碼的作用域設置到一個特定的對象中。語法如下:

with(expression)   statement;

定義 with 語句的目的主要是為了簡化多次編寫同一個對象的工作,實例:

var qs = location.search.substring(1);
var hostName = location.hostname;
var url = location.href;

以上代碼可以使用 with 語句改寫成如下:

with(location){
    var qs = search.substring(1);
    var hostName = hostname;
    var url = href;
}

注意:在嚴格模式下不允許使用 with 語句,否則將視為語法錯誤。

由于大量使用 with 語句會導致性能下降,同時也會給調試代碼造成困難,因此在開發大型應用程序時,不建議使用 with 語句。


switch語句

switch 語句與 if 語句的關系最為密切。語法如下:

switch(expression){
    case value:statement
        break;
    case value:statement
        break;
    case value:statement
        break;
    default:statement
}

含義為:如果表達式等于這個值(value),則執行后面的語句。而 break 關鍵字會導致代碼執行流跳出 switch 語句。如果省略 break,就會導致執行完當前 case 后,繼續執行下一個 case。最后的 default 關鍵字則用于在表達式不匹配前面任何一種情形時,執行機動代碼(也相當于 else 語句)。

switch 語句在比較值時使用的是全等操作符,因此不會發生類型轉換。


函數

通過函數可以封裝任意多條語句,而且可以在任何地方、任何時候調用執行。

ES 中的函數使用 function 關鍵字來聲明,后跟一組參數以及函數體。語法如下:

function functionName(arg0,arg1,...,argN){
    statements
}

ES 中的函數在定義時不必指定是否返回值。實際上,任何函數在任何時候都可以通過 return 語句后跟要返回的值來實現返回值。示例如下:

function sum(num1,num2){
    return num1 + num2;
}

這個 sum() 函數的作用是把兩個值加起來返回一個結果。

調用這個函數的代碼如下:

var result = sum(5,10);

這個函數會在執行完 return 語句之后停止并立即退出,因此位于 return 之后的任何代碼將不會被執行。

另外,return 語句也可以不帶有任何返回值。函數在停止執行后將返回 undefined 值,這種用法一般用在需要提前停止函數執行而又不需要返回值的情況下使用。

嚴格模式對函數有一些限制,如下:

  • 不能把函數命名為 eval 或 arguments;
  • 不能把參數命名為 eval 或 arguments;
  • 不能出現兩個命名參數同名的情況。
    如發生以上情況,將導致語法錯誤,無法執行。

理解參數

在函數體內可以通過 arguments 對象來訪問這個參數數組,從而獲取傳遞給函數的每一個參數。

ES 函數一個重要特定:命名的參數只提供便利,但不是必需的。

沒有傳遞值的命名參數將自動被賦予 undefined 值。

ES 中的所有參數傳遞的都是值,不可能通過引用傳遞參數。


沒有重載

ES 函數不能像傳統意義上那樣實現重載。ES 函數沒有簽名,因為其參數是由包含零或多個值的數組來表示的。而沒有函數簽名,真正的重載是不可能做到的。

如果在 ES 中定義了兩個名字相同的函數,則該名字只屬于后定義的函數。


小結

下面簡要總結 ES 中的基本要素

  • ES 中的基本數據類型包括 Undefined、Null、Boolean、Numbe 和 String。
  • ES 沒有為整數和浮點數值分別定義不同的數據類型,Number 類型可以用于表示所有數值。
  • ES 中有一種復雜的數據類型:Object 類型,該類型是所有對象的基礎類型。
  • 嚴格模式為這門語言中容易出錯的地方施加了限制。
  • ES 提供了很多基本操作符:算術操作符、布爾操作符、關系操作符、相等操作符及賦值操作符等等。
  • ES 中有很多流控制語句,如:if 語句、for 語句和 switch 語句等等。
  • 無須指定函數的返回值,因為 ES 函數都可以在任何時候返回任何值。
  • 未指定返回值的函數返回的是一個特殊的 undefined 值。
  • ES 中沒有函數簽名的概念,因為其函數參數是以一個包含零或多個值的數組的形式傳遞的。
  • 可以向 ES 函數傳遞任意數量的參數,并可以通過 arguments 對象來訪問這些參數。
  • 由于不存在函數簽名,ES 函數不能重載。

變量、作用域和內存問題

基本類型和引用類型的值

ES變量可能包含兩種不同數據類型的值:基本類型值和引用類型值

基本類型值指的是簡單的數據段,而引用類型值指那些可能由多個值構成的對象。

引用類型的值是保存在內存中的對象。JavaScript不允許直接訪問內存中的位置,也就是說不能直接操作對象的內存空間。在操作對象時,實際上是在操  作對象的引用而不是實際的對象。因此,引用類型的值是按引用訪問的。


動態的屬性

定義基本類型值和引用類型值的方式是類似的:創建一個變量并為該變量賦值。

我們不能給基本類型的值添加屬性,只能給引用類型值動態地添加屬性。


復制變量值

除了保存的方式不同之外,在從一個變量向另一個變量復制基本類型值和引用類型值時,也存在不同。如果從一個變量向另一個變量復制基本類型的值,會在變量對象上創建一個新值,然后把該值復制到為新變量分配的位置上,例如:

var num1 = 5;
var num2 = num1;

以上代碼中,num1中保存的值為5.當使用num1的值來初始化num2時,num2中也保存了值5.但num2中的5與num1的5是完全獨立的,該值只是num1中5的一個副本。此后,這兩個變量可以參與任何操作而不會相互影響。

當從一個變量向另一個變量復制引用類型的值時,同樣也會將存儲在變量對象中的值復制一份到為新變量分配的空間中。不同的是,這個值的副本實際上是一個指針,而這個指針指向存儲在堆中的一個對象。復制操作結束后,兩個變量實際上將引用同一個對象。因此,改變其中一個變量,就會音響另一個變量,例如:

var obj1 = new Object();
var obj2 = obj1;
obj1.name = "zww"
alert(obj2.name);    //"zww"

以上代碼中,變量obj1保存了一個對象的新實例。然后這個值被復制到了obj2中。obj1和obj2都指向同一個對象。這樣,當為obj1添加name屬性后,可以通過obj2來訪問這個屬性。


傳遞參數

ES中所有函數的參數都是按值傳遞的。也就是說,把函數外部的值復制給函數內部的參數,就和把值從一個變量復制到另一個變量一樣。例子:

function addTen(num){
    num += 10;
    return num;
}
var count = 20;
var result = addTen(count);
alert(count);    //20,沒有變化
alert(result);    //30

以上代碼中,函數addTen()有一個參數num,而參數實際上是函數的局部變量。在調用函數時,變量count作用參數被傳遞給函數,這個變量值為20。于是數值20被復制給參數num以便在addTen()中使用。在函數內部,參數num值被加上了10,這一變化不會影響函數外部的count變量。


檢測類型

要檢測一個變量是不是基本數據類型,typeof操作符是最佳的工具。

typeof操作符是確定一個變量是字符串、數值、布爾值,還是undefined的最佳工具,如果變量值是null或對象,則會返回"object"。

var s = "zww";
var b = true;
var i = 19;
var u;
var n = null;
var o = new Object();
alert(typeof s);    //string
alert(typeof b);    //boolean
alert(typeof i);    //number
alert(typeof u);    //undefined
alert(typeof n);    //object
alert(typeof o);    //object

因此,ES提供了instanceof操作符,語法如下:

result = variable instanceof constructor

如果變量是給定引用類型的實例,那么instanceof操作符就會返回true。


執行環境及作用域

執行環境定義了變量或函數有權訪問的其他數據,決定了它們各自的行為。每個執行環境都有一個與之關聯的變量對象,環境中定義的所有變量和函數都保存在這個對象中。

每個函數都有自己的執行環境。當執行流進入一個函數時,函數的環境就會被推入一個環境棧中。而在函數執行之后,棧將其環境彈出,把控制權返回給之前的執行環境。

當代碼在一個環境中執行時,會創建變量對象的一個作用域鏈。作用域鏈的用途是保證對執行環境有權訪問的所有變量和函數的有序訪問。


延長作用域鏈

雖然執行環境的類型總共只有兩種:全局和局部(函數),但還是有其他辦法延長作用域鏈的。因為有些語句可以在作用域鏈的前端臨時增加一個變量對象,該變量對象會在代碼執行后被移除。在兩種情況下會發生這種情況。具體的說就是當執行流進入下列任何一個語句時,作用域鏈就會得到加長:

  • try-catch語句的catch塊;
  • with語句。

這兩個語句都會在作用域鏈的前端添加一個變量對象。對with語句來說,會將指定的對象添加到作用域鏈中。對catch來說,會創建一個新的變量對象,其中包含的是被拋出的錯誤對象的聲明。


沒有塊級作用域

聲明變量

使用var聲明的變量會自動被添加到最接近的環境中。在函數內部,最接近的環境就是函數的局部環境;在with語句中,最接近的環境是函數環境。如果初始化變量時沒有使用var聲明,該變量會自動被添加到全局環境。例如:

function add(num1,num2){
    var sum = num1 + num2;
    return sum;
}
var result = add(10,20);    //30
alert(sum);    //由于sum不是有效的變量,因此會導致錯誤

以上代碼中,函數add()定義了一個名為sum的局部變量,該變量包含加法的操作結果。雖然結果值從函數中返回了,但變量sum在函數外部是訪問不到的。如果省略例子中var關鍵字,那么add()執行完畢后,sum也將可以訪問到:

function add(num1,num2){
    sum = num1 + num2;
    return sum;
}
var result = add(10,20);    //30
alert(sum);    //30

查詢標識符

當在某個環境中為了讀取或寫入而引用一個標識符時,必須通過搜索來確定該標識符實際代表什么。搜索過程從作用域鏈的前端開始,向上逐級查詢與給定名字匹配的標識符。如果在局部環境中找到了該標識符,就停止搜索,變量就緒。如果在局部環境中沒有找到,則繼續沿作用域鏈向上搜索。搜索過程將一直追溯到全局環境的變量對象。如果在全局環境中沒有找到標識符,則意味著該變量尚未聲明。


垃圾收集

JavaScript具有自動垃圾收集機制,也就是說,執行環境會負責管理代碼執行過程中使用的內存。

標記清除

JavaScript中最常用的垃圾收集方式是標記清除。當變量進入環境時,就將這個變量標記為“進入環境”。從邏輯上講,永遠不能釋放進入環境的變量所占用的內存,因為只要執行流進入相應的環境,就可能會用到它們。而當變量離開環境時,則講其標記為“離開環境”。


引用計數

另一種不太常見的垃圾收集策略叫引用計數。含義是跟蹤記錄每個值被引用的次數。當聲明了一個變量并將一個引用類型值賦給該變量時,則這個值的引用次數就是1。如果同一個值又被賦給另一個變量,則該值的引用次數加1。相反,如果包含對這個值引用的變量又取得另外一個值,則這個值的引用次數減1。當這個值的引用次數變為0時,則說明沒有辦法再訪問這個值了,因而就可以將其占用的內存空間回收回來。這樣,當垃圾收集器下次再運行時,它就會釋放那些引用次數為零的值所占用的內存。


性能問題

垃圾收集器是周期性運行的。

IE的垃圾收集器是根據內存分配量運行的,具體一點說就是256個變量、4096個對象(或數組)字面量和數組元素(slot)或者64KB的字符串,達到上述任何一個臨界值,垃圾收集器就會運行。

在IE中,調用window.CollectGarbage()方法會立即執行垃圾收集。


管理內存

JavaScript在進行內存管理及垃圾收集時,最主要的一個問題是,分配給web瀏覽器的可用內存數量通常要比分配給桌面應用程序的少。這樣做的目的主要是出于安全方面考慮,目的是防止運行JavaScript的網頁耗盡全部系統內存而導致系統崩潰。內存限制問題不僅會影響給變量分配內存,同時還會影響調用棧以及在一個線程中能夠同時執行的語句數量。

因此,確保占用最少的內存可以讓頁面獲得更好的性能。而優化內存占用的最佳方式,就是為執行中的代碼只保存必要的數據。一旦數據不再有用,最好通過將其值設置為null來釋放其引用,這個做法叫做解除引用。這一做法適用于大多數全局變量和全局對象的屬性。局部變量會在它們離開執行環境時自動被解除引用。


小結

JavaScript變量可以用來保存兩種類型的值:基本類型值和引用類型值。

基本類型值和引用類型值具有以下特點:

  • 基本類型值在內存中占據固定大小的空間,因此被保存在棧內存中;
  • 從一個變量向另一個變量復制基本類型的值,會創建這個值的一個副本;
  • 引用類型的值是對象,保存在堆內存中;
  • 包含引用類型值得變量實際上包含的并不是對象本身,而是一個指向該對象的指針;
  • 從一個變量向另一個變量復制引用類型的值,復制的其實是指針,因此兩個變量最終都指向同一個對象;
  • 確定一個值是哪種基本類型可以使用typeof操作符,而確定一個值是哪種引用類型可以使用instanceof操作符。

所有變量都存在于一個執行環境(也稱作用域)當中,這個執行環境決定了變量的生命周期,以及哪一部分代碼可以訪問其中的變量。

以下是關于執行環境的幾點總結:

  • 執行環境有全局執行環境和函數執行環境之分;
  • 每次進入一個新執行環境,都會創建一個用于搜索變量和函數的作用域鏈;
  • 函數的局部環境不僅有權訪問函數作用域中的變量,而且還有權訪問其包含(父)環境,乃至全局環境;
  • 全局環境只能訪問在全局環境中定義的變量和函數,而不能直接訪問局部環境中的任何數據;
  • 變量的執行環境有助于確定應該何時釋放內存。

JavaScript是一門具有自動垃圾收集機制的編程語言,開發人員不必關心內存分配和回收問題,可以對JavaScript的垃圾收集例程做如下總結:

  • 離開作用域的值將被自動標記為可以回收,因此將在垃圾收集期間被刪除;
  • “標記清除”是目前主流的垃圾收集算法,這種算法思想是給當前不使用的值加上標記,然后再回收其內存;
  • 另一個垃圾收集算法是“引用計數”,這種算法思想是跟蹤記錄所有值被引用的次數。JavaScript引擎目前都不再使用這種算法;
  • 當代碼中存在循環引用現象時,“引用計數”算法就會導致問題;
  • 解除變量的引用不僅有助于消除循環引用現象,而且對垃圾收集也有好處。為了確保有效地回收內存,應該及時解除不再使用的全局對象、全局對象屬性以及循環引用變量的引用。

引用類型

Object類型

創建Object實例的兩種方式:

  1. 使用new操作符后跟Object構造函數,例如:
var person = new Object();
person.name = "ZWW";
person.age = 22;
  1. 使用對象字面量表示法,例如:
var person = {
    name: "ZWW",
    age: 22
};

在對象字面量中,使用逗號來分隔不同的屬性,并且在最后一個屬性后面不能添加逗號。

在使用對象字面量時,屬性名也可以使用字符串;如果留空其花括號,則可以定義只包含默認屬性和方法的對象。

本站僅提供存儲服務,所有內容均由用戶發布,如發現有害或侵權內容,請點擊舉報
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
Lua筆記
Java編程入門(2.5):表達式
統計軟件SAS使用教程
◎Vbs腳本編程簡明教程之三
課堂筆記
第三章 VB語言基礎_Visual Basic基礎_
更多類似文章 >>
生活服務
分享 收藏 導長圖 關注 下載文章
綁定賬號成功
后續可登錄賬號暢享VIP特權!
如果VIP功能使用有故障,
可點擊這里聯系客服!

聯系客服

主站蜘蛛池模板: 台山市| 东源县| 南木林县| 昆明市| 金乡县| 庆云县| 永昌县| 永济市| 福贡县| 大港区| 海盐县| 广元市| 高台县| 本溪| 博野县| 多伦县| 黄石市| 肇庆市| 临颍县| 黄冈市| 普兰店市| 安达市| 白山市| 观塘区| 永寿县| 连云港市| 安吉县| 新晃| 黎平县| 龙门县| 鱼台县| 黎城县| 富蕴县| 昌都县| 炎陵县| 明溪县| 盐城市| 延庆县| 洛南县| 辰溪县| 漳浦县|