您好,登錄后才能下訂單哦!
小編給大家分享一下JavaScript的基礎(chǔ)知識有哪些,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
一、什么是JavaScript
1-1、JavaScript實(shí)現(xiàn)
雖然JavaScript和ECMAScript基本上是同義詞,但JavaScript遠(yuǎn)不限于ECMA-262所定義的那樣。完整的JavaScript實(shí)現(xiàn)包含:
核心(ECMAScript)
文檔對象模型(DOM)
瀏覽器對象模型(BOM)
Web瀏覽器只是ECMAScript實(shí)現(xiàn)可能存在的一種宿主環(huán)境(hostenvironment)。宿主環(huán)境提供ECMAScript的基準(zhǔn)實(shí)現(xiàn)和與環(huán)境自身交互必需的擴(kuò)展。擴(kuò)展(比如DOM)使用ECMAScript核心類型和語法,提供特定于環(huán)境的額外功能。其他宿主環(huán)境還有服務(wù)器端JavaScript平臺Node.js和即將被淘汰的Adobe Flash。
在基本層面,描述這門語言:語法,類型,語句,關(guān)鍵字,保留字,操作符,全局對象
ECMAScript只是對實(shí)現(xiàn)這個(gè)規(guī)范描述的所有方面的一門語言的稱
呼。JavaScript實(shí)現(xiàn)了ECMAScript,而Adobe ActionScript同樣也實(shí)現(xiàn)了
ECMAScript。
1-2、DOM
文檔對象模型(DOM,Document Object Model)是一個(gè)應(yīng)用編程接口(API),用于在HTML中使用擴(kuò)展的XML。DOM將整個(gè)頁面抽象為一組分層節(jié)點(diǎn)。HTML或XML頁面的每個(gè)組成部分都是一種節(jié)
點(diǎn),包含不同的數(shù)據(jù)。
DOM通過創(chuàng)建表示文檔的樹,讓開發(fā)者可以隨心所欲地控制網(wǎng)頁的內(nèi)容和結(jié)構(gòu)。使用DOM API,可以輕松地刪除、添加、替換、修改節(jié)點(diǎn)。
1-3、BOM
IE3和Netscape Navigator 3提供了瀏覽器對象模型(BOM) API,用于支持訪問和操作瀏覽器的窗口。使用BOM,開發(fā)者可以操控瀏覽器顯示頁面之外的部分。而BOM真正獨(dú)一無二的地方,當(dāng)然也是問題最多的地方,就是它是唯一一個(gè)沒有相關(guān)標(biāo)準(zhǔn)的JavaScript實(shí)現(xiàn)。HTML5改變了這個(gè)局面,這個(gè)版本的HTML以正式規(guī)范的形式涵蓋了盡可能多的BOM特性。由于HTML5的出現(xiàn),之前很多與BOM有關(guān)的問題都迎刃而解了。
總體來說,BOM主要針對瀏覽器窗口和子窗口(frame),不過
人們通常會把任何特定于瀏覽器的擴(kuò)展都?xì)w在BOM的范疇內(nèi)。下面就是這樣一些擴(kuò)展:
彈出新瀏覽器窗口的能力;
移動、縮放和關(guān)閉瀏覽器窗口的能力;
navigator 對象,提供關(guān)于瀏覽器的詳盡信息;
location 對象,提供瀏覽器加載頁面的詳盡信息;
screen 對象,提供關(guān)于用戶屏幕分辨率的詳盡信息;
performance 對象,提供瀏覽器內(nèi)存占用、導(dǎo)航行為和時(shí)間統(tǒng)
計(jì)的詳盡信息;
對cookie的支持;
其他自定義對象,如 XMLHttpRequest 和IE的
ActiveXObject
二、HTML中的JavaScript
2-1、script
元素
將JavaScript插入HTML的主要方法是使用 script 元素。這
個(gè)元素是由網(wǎng)景公司創(chuàng)造出來,并最早在Netscape Navigator 2中實(shí)現(xiàn)
的。后來,這個(gè)元素被正式加入到HTML規(guī)范。 script 元素有下
列8個(gè)屬性。
async
:可選。表示應(yīng)該立即開始下載腳本,但不能阻止其他頁面動作,比如下載資源或等待其他腳本加載。只對外部腳本文件有效。
charset :可選。使用 src 屬性指定的代碼字符集。這個(gè)屬性很少使用,因?yàn)榇蠖鄶?shù)瀏覽器不在乎它的值。
crossorigin :可選。配置相關(guān)請求的CORS(跨源資源共享)設(shè)置。默認(rèn)不使用CORS。crossorigin=“anonymous” 配置文件請求不必設(shè)置憑據(jù)標(biāo)志。 crossorigin=“use-credentials” 設(shè)置憑據(jù)標(biāo)志,意
味著出站請求會包含憑據(jù)。
defer :可選。表示在文檔解析和顯示完成后再執(zhí)行腳本是沒有問題的。只對外部腳本文件有效。在IE7及更早的版本中,對行內(nèi)腳本也可以指定這個(gè)屬性。
integrity :可選。允許比對接收到的資源和指定的加密簽名以驗(yàn)證子資源完整性(SRI,Subresource Intergrity)。如果接收到的資源的簽名與這個(gè)屬性指定的簽名不匹配,則頁面會報(bào)錯(cuò),腳本不會執(zhí)行。這個(gè)屬性可以用于確保內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN,Content Delivery Network)不會提供惡意內(nèi)容。
language :廢棄。最初用于表示代碼塊中的腳本語言(如 “JavaScript” 、 “JavaScript1.2” 或 “VBScript” )。大多數(shù)瀏覽器都會忽略這個(gè)屬性,不應(yīng)該再使用它。
src :可選。表示包含要執(zhí)行的代碼的外部文件。
type :可選。代替 language ,表示代碼塊中腳本語言的內(nèi)容類型(也稱MIME類型)。
包含在 script 內(nèi)的代碼會被從上到下解釋
2-2、
使用了 src 屬性的 script 元素不應(yīng)該再在 script 和 /script 標(biāo)簽中再包含其他JavaScript代碼。如果兩者都提供的話,則瀏覽器只會下載并執(zhí)行腳本文件,從而忽略行內(nèi)代碼。
script 元素的一個(gè)最為強(qiáng)大、同時(shí)也備受爭議的特性是,它可以包含來自外部域的JavaScript文件。跟 img 元素很像, script 元素的 src 屬性可以是一個(gè)完整的URL,而且這個(gè)URL指向的資源可以跟包含它的HTML頁面不在同一個(gè)域中
2-3、文檔模式
可以使用 doctype 切換文檔模式。最初的文檔模式有兩種:混雜模式(quirks mode)和標(biāo)準(zhǔn)模式(standards mode)。前者讓IE像IE5一樣(支持一些非標(biāo)準(zhǔn)的特性),后者讓IE具有兼容標(biāo)準(zhǔn)的行為。雖然這兩種模式的主要區(qū)別只體現(xiàn)在通過CSS渲染的內(nèi)容方面,但對JavaScript也有一些關(guān)聯(lián)影響,或稱為副作用。本書會經(jīng)常提到這些副作用。
IE初次支持文檔模式切換以后,其他瀏覽器也跟著實(shí)現(xiàn)了。隨著瀏覽器的普遍實(shí)現(xiàn),又出現(xiàn)了第三種文檔模式:準(zhǔn)標(biāo)準(zhǔn)模式(almost
standards mode)。這種模式下的瀏覽器支持很多標(biāo)準(zhǔn)的特性,但是沒有標(biāo)準(zhǔn)規(guī)定得那么嚴(yán)格。主要區(qū)別在于如何對待圖片元素周圍的空白(在表格中使用圖片時(shí)最明顯)。
混雜模式在所有瀏覽器中都以省略文檔開頭的 doctype 聲明作為開關(guān)。這種約定并不合理,因?yàn)榛祀s模式在不同瀏覽器中的差異非常大,不使用黑科技基本上就沒有瀏覽器一致性可言。
2-4、noscript 元素
針對早期瀏覽器不支持JavaScript的問題,需要一個(gè)頁面優(yōu)雅降級的處理方案。最終, 元素出現(xiàn),被用于給不支持JavaScript的瀏覽器提供替代內(nèi)容。雖然如今的瀏覽器已經(jīng)100%支持JavaScript,但對于禁用JavaScript的瀏覽器來說,這個(gè)元素仍然有它的用處。
元素可以包含任何可以出現(xiàn)在 中的HTML元素,
瀏覽器不支持腳本
瀏覽器對腳本的支持被關(guān)閉
三、語法基礎(chǔ)
3-1、語法
首先要知道的是,ECMAScript中一切都區(qū)分大小寫。無論是變量、函數(shù)名還是操作符,都區(qū)分大小寫。換句話說,變量 test 和變量 Test 是兩個(gè)不同的變量。類似地, typeof 不能作為函數(shù)名,因?yàn)樗且粋€(gè)關(guān)鍵字(后面會介紹)。但 Typeof 是一個(gè)完全有效的函數(shù)名。
3-2、標(biāo)識符
所謂標(biāo)識符,就是變量、函數(shù)、屬性或函數(shù)參數(shù)的名稱。標(biāo)識符可以由一或多個(gè)下列字符組成:
第一個(gè)字符必須是一個(gè)字母、下劃線( _ )或美元符號( $ );
剩下的其他字符可以是字母、下劃線、美元符號或數(shù)字。
標(biāo)識符中的字母可以是擴(kuò)展ASCII(Extended ASCII)中的字母,也可以是Unicode的字母字符,如à和?(但不推薦使用)。
按照慣例,ECMAScript標(biāo)識符使用駝峰大小寫形式,即第一個(gè)單詞的首字母小寫,后面每個(gè)單詞的首字母大寫
3-3、嚴(yán)格模式
ECMAScript 5增加了嚴(yán)格模式(strict mode)的概念。嚴(yán)格模式是一種不同的JavaScript解析和執(zhí)行模型,ECMAScript 3的一些不規(guī)范寫法在這種模式下會被處理,對于不安全的活動將拋出錯(cuò)誤
3-4、關(guān)鍵字與保留字
ECMA-262描述了一組保留的關(guān)鍵字,這些關(guān)鍵字有特殊用途,比如表示控制語句的開始和結(jié)束,或者執(zhí)行特定的操作
ECMA-262第6版規(guī)定的所有關(guān)鍵字:
break do in typeof case else instanceof var catch export new void class extends return while const finally super with continue for switch yield debugger function this default if throw delete import try
規(guī)范中也描述了一組未來的保留字,同樣不能用作標(biāo)識符或?qū)傩悦?。雖然保留字在語言中沒有特定用途,但它們是保留給將來做關(guān)鍵字用的
3-5、變量
ECMAScript變量是松散類型的,意思是變量可以用于保存任何類型的數(shù)據(jù)。每個(gè)變量只不過是一個(gè)用于保存任意值的命名占位符。有3個(gè)關(guān)鍵字可以聲明變量: var 、 const 和 let 。其中, var 在CMAScript的所有版本中都可以使用,而 const 和 let 只能在ECMAScript 6及更晚的版本中使用
3-6、var關(guān)鍵字
var聲明作用域
關(guān)鍵的問題在于,使用 var 操作符定義的變量會成為包含它的函數(shù)的局部變量。比如,使用 var 在一個(gè)函數(shù)內(nèi)部定義一個(gè)變量,就意味著該變量將在函數(shù)退出時(shí)被銷毀
var 聲明提升
使用 var 時(shí),下面的代碼不會報(bào)錯(cuò)。這是因?yàn)槭褂眠@個(gè)關(guān)鍵字聲明的變量會自動提升到函數(shù)作用域頂部
3-7、let 聲明
let 跟 var 的作用差不多,但有著非常重要的區(qū)別。最明顯的區(qū)別是, let 聲明的范圍是塊作用域,而 var 聲明的范圍是函數(shù)作用域。
暫時(shí)性死區(qū)
let 與 var 的另一個(gè)重要的區(qū)別,就是 let 聲明的變量不會在作用域中被提升。
全局聲明
與 var 關(guān)鍵字不同,使用 let 在全局作用域中聲明的變量不會成為 window 對象的屬性( var 聲明的變量則會)
條件聲明
在使用 var 聲明變量時(shí),由于聲明會被提升,JavaScript引擎會自動將多余的聲明在作用域頂部合并為一個(gè)聲明。因?yàn)?let 的作用域是塊,所以不可能檢查前面是否已經(jīng)使用 let 聲明過同名變量,同時(shí)也就不可能在沒有聲明的情況下聲明它
for 循環(huán)中的 let 聲明
在 let 出現(xiàn)之前, for 循環(huán)定義的迭代變量會滲透到循環(huán)體外部
const 聲明
const 的行為與 let 基本相同,唯一一個(gè)重要的區(qū)別是用它聲明變量時(shí)必須同時(shí)初始化變量,且嘗試修改 const 聲明的變量會導(dǎo)致運(yùn)行時(shí)錯(cuò)誤。
3-8、聲明風(fēng)格及最佳實(shí)踐
ECMAScript 6增加 let 和 const 從客觀上為這門語言更精確地聲明作用域和語義提供了更好的支持。行為怪異的 var 所造成的各種問題,已經(jīng)讓JavaScript社區(qū)為之苦惱了很多年。隨著這兩個(gè)新關(guān)鍵字的出現(xiàn),新的有助于提升代碼質(zhì)量的最佳實(shí)踐也逐漸顯現(xiàn)。
不使用 var
有了 let 和 const ,大多數(shù)開發(fā)者會發(fā)現(xiàn)自己不再需要 var了。限制自己只使用 let 和 const 有助于提升代碼質(zhì)量,因?yàn)樽兞坑辛嗣鞔_的作用域、聲明位置,以及不變的值。
const 優(yōu)先, let 次之
使用 const 聲明可以讓瀏覽器運(yùn)行時(shí)強(qiáng)制保持變量不變,也可以讓靜態(tài)代碼分析工具提前發(fā)現(xiàn)不合法的賦值操作。因此,很多開發(fā)者認(rèn)為應(yīng)該優(yōu)先使用 const 來聲明變量,只在提前知道未來會有修改時(shí),再使用 let 。這樣可以讓開發(fā)者更有信心地推斷某些變量的值永遠(yuǎn)不會變,同時(shí)也能迅速發(fā)現(xiàn)因意外賦值導(dǎo)致的非預(yù)期行為。
四、數(shù)據(jù)類型
ECMAScript有6種簡單數(shù)據(jù)類型(也稱為原始類型):Undefined 、 Null 、 Boolean 、 Number 、 String 和Symbol 。 Symbol (符號)是ECMAScript 6新增的。還有一種復(fù)雜數(shù)據(jù)類型叫 Object (對象)。 Object 是一種無序名值對的集合。因?yàn)樵贓CMAScript中不能定義自己的數(shù)據(jù)類型,所有值都可以用上述7種數(shù)據(jù)類型之一來表示。只有7種數(shù)據(jù)類型似乎不足以表示全部數(shù)據(jù)。但ECMAScript的數(shù)據(jù)類型很靈活,一種數(shù)據(jù)類型可以當(dāng)作多種數(shù)據(jù)類型來使用
4-1、typeof 操作符
因?yàn)镋CMAScript的類型系統(tǒng)是松散的,所以需要一種手段來確定任意變量的數(shù)據(jù)類型。 typeof 操作符就是為此而生的。對一個(gè)值使用 typeof 操作符會返回下列字符串之一:
“undefined” 表示值未定義;
“boolean” 表示值為布爾值;
“string” 表示值為字符串;
“number” 表示值為數(shù)值;
“object” 表示值為對象(而不是函數(shù))或 null ;
“function” 表示值為函數(shù);
“symbol” 表示值為符號。
4-2、Undefined 類型
Undefined 類型只有一個(gè)值,就是特殊值 undefined 。當(dāng)使用 var 或 let 聲明了變量但沒有初始化時(shí),就相當(dāng)于給變量賦予了 undefined 值
即使未初始化的變量會被自動賦予 undefined 值,但我們?nèi)匀唤ㄗh在聲明變量的同時(shí)進(jìn)行初始化。這樣,當(dāng) typeof 返回 “undefined” 時(shí),你就會知道那是因?yàn)榻o定的變量尚未聲明,而不是聲明了但未初始化。
4-3、Null 類型
Null 類型同樣只有一個(gè)值,即特殊值 null 。邏輯上講,null 值表示一個(gè)空對象指針,這也是給 typeof 傳一個(gè) null 會返回 “object” 的原因
在定義將來要保存對象值的變量時(shí),建議使用 null 來初始化,不要使用其他值。這樣,只要檢查這個(gè)變量的值是不是 null 就可以知道這個(gè)變量是否在后來被重新賦予了一個(gè)對象的引用
用等于操作符( == )比較 null 和 undefined 始終返回true 。但要注意,這個(gè)操作符會為了比較而轉(zhuǎn)換它的操作數(shù)。
即使 null 和 undefined 有關(guān)系,它們的用途也是完全不一樣的。如前所述,永遠(yuǎn)不必顯式地將變量值設(shè)置為 undefined 。但null 不是這樣的。任何時(shí)候,只要變量要保存對象,而當(dāng)時(shí)又沒有那個(gè)對象可保存,就要用 null 來填充該變量。這樣就可以保持null 是空對象指針的語義,并進(jìn)一步將其與 undefined 區(qū)分開來。
null 是一個(gè)假值。因此,如果需要,可以用更簡潔的方式檢測它。不過要記住,也有很多其他可能的值同樣是假值。所以一定要明確自己想檢測的就是 null 這個(gè)字面值,而不僅僅是假值
4-4、Boolean 類型
Boolean (布爾值)類型是ECMAScript中使用最頻繁的類型之一,有兩個(gè)字面值: true 和 false 。這兩個(gè)布爾值不同于數(shù)值,因此 true 不等于1, false 不等于0
注意:布爾值字面量 true 和 false 是區(qū)分大小寫的,因此True 和 False (及其他大小混寫形式)是有效的標(biāo)識符,但不是布爾值。
4-5、Number 類型
ECMAScript中最有意思的數(shù)據(jù)類型或許就是 Number 了。Number 類型使用IEEE 754格式表示整數(shù)和浮點(diǎn)值(在某些語言中也叫雙精度值)。不同的數(shù)值類型相應(yīng)地也有不同的數(shù)值字面量格式
浮點(diǎn)值
要定義浮點(diǎn)值,數(shù)值中必須包含小數(shù)點(diǎn),而且小數(shù)點(diǎn)后面必須至
少有一個(gè)數(shù)字。雖然小數(shù)點(diǎn)前面不是必須有整數(shù),但推薦加上。
值的范圍
由于內(nèi)存的限制,ECMAScript并不支持表示這個(gè)世界上的所有數(shù)值。ECMAScript可以表示的最小數(shù)值保存在Number.MIN_VALUE 中,這個(gè)值在多數(shù)瀏覽器中是5e-324;可以表示的最大數(shù)值保存在 Number.MAX_VALUE 中,這個(gè)值在多數(shù)瀏覽器中是1.797 693 134 862 315 7e+308。如果某個(gè)計(jì)算得到的數(shù)值結(jié)果超出了JavaScript可以表示的范圍,那么這個(gè)數(shù)值會被自動轉(zhuǎn)換為一個(gè)特殊的 Infinity (無窮)值。任何無法表示的負(fù)數(shù)以 -Infinity (負(fù)無窮大)表示,任何無法表示的正數(shù)以 Infinity (正無窮大)表示。如果計(jì)算返回正 Infinity 或負(fù) Infinity ,則該值將不能再進(jìn)一步用于任何計(jì)算。這是因?yàn)?Infinity 沒有可用于計(jì)算的數(shù)值表示形式。要確定一個(gè)值是不是有限大(即介于JavaScript能表示的最小值和最大值之間),可以使用 isFinite() 函數(shù)
NaN
有一個(gè)特殊的數(shù)值叫 NaN ,意思是“不是數(shù)值”(Not a Number),用于表示本來要返回?cái)?shù)值的操作失敗了(而不是拋出錯(cuò)誤)。比如,用0除任意數(shù)值在其他語言中通常都會導(dǎo)致錯(cuò)誤,從而中止代碼執(zhí)行。但在ECMAScript中,0、+0或-0相除會返回NaN
數(shù)值轉(zhuǎn)換
有3個(gè)函數(shù)可以將非數(shù)值轉(zhuǎn)換為數(shù)值: Number() 、parseInt() 和 parseFloat() 。 Number() 是轉(zhuǎn)型函數(shù),可用于任何數(shù)據(jù)類型。后兩個(gè)函數(shù)主要用于將字符串轉(zhuǎn)換為數(shù)值。對于同樣的參數(shù),這3個(gè)函數(shù)執(zhí)行的操作也不同。
4-6、 NaN
有一個(gè)特殊的數(shù)值叫 NaN ,意思是“不是數(shù)值”(Not aNumber),用于表示本來要返回?cái)?shù)值的操作失敗了(而不是拋出錯(cuò)誤)。
4-7、數(shù)值轉(zhuǎn)換
有3個(gè)函數(shù)可以將非數(shù)值轉(zhuǎn)換為數(shù)值: Number() 、 parseInt() 和 parseFloat() 。 Number() 是轉(zhuǎn)型函數(shù),可用于任何數(shù)據(jù)類型。后兩個(gè)函數(shù)主要用于將字符串轉(zhuǎn)換為數(shù)值。對于同樣的參數(shù),這3個(gè)函數(shù)執(zhí)行的操作也不同。Number() 函數(shù)基于如下規(guī)則執(zhí)行轉(zhuǎn)換。布爾值, true 轉(zhuǎn)換為1, false 轉(zhuǎn)換為0。
數(shù)值,直接返回。null ,返回0。 undefined ,返回 NaN 。
4-8、String 類型
String (字符串)數(shù)據(jù)類型表示零或多個(gè)16位Unicode字符序列。字符串可以使用雙引號(")、單引號(’)或反引號(`)標(biāo)示,
字符字面量
字符串?dāng)?shù)據(jù)類型包含一些字符字面量,用于表示非打印字符或有其他用途的字符
字符串的特點(diǎn)
ECMAScript中的字符串是不可變的(immutable),意思是一旦創(chuàng)建,它們的值就不能變了。要修改某個(gè)變量中的字符串值,必須先銷毀原始的字符串,然后將包含新值的另一個(gè)字符串保存到該變量
轉(zhuǎn)換為字符串
有兩種方式把一個(gè)值轉(zhuǎn)換為字符串。首先是使用幾乎所有值都有的 toString() 方法。這個(gè)方法唯一的用途就是返回當(dāng)前值的字符串等價(jià)物
模板字面量
ECMAScript 6新增了使用模板字面量定義字符串的能力。與使用單引號或雙引號不同,模板字面量保留換行字符,可以跨行定義字符串
字符串插值
模板字面量最常用的一個(gè)特性是支持字符串插值,也就是可以在一個(gè)連續(xù)定義中插入一個(gè)或多個(gè)值。技術(shù)上講,模板字面量不是字符串,而是一種特殊的JavaScript句法表達(dá)式,只不過求值后得到的是字符串。模板字面量在定義時(shí)立即求值并轉(zhuǎn)換為字符串實(shí)例,任何插入的變量也會從它們最接近的作用域中取值
模板字面量標(biāo)簽函數(shù)
模板字面量也支持定義標(biāo)簽函數(shù)(tag function),而通過標(biāo)簽函數(shù)可以自定義插值行為。標(biāo)簽函數(shù)會接收被插值記號分隔后的模板和對每個(gè)表達(dá)式求值的結(jié)果。標(biāo)簽函數(shù)本身是一個(gè)常規(guī)函數(shù),通過前綴到模板字面量來應(yīng)用自定義行為,
原始字符串
使用模板字面量也可以直接獲取原始的模板字面量內(nèi)容(如換行符或Unicode字符),而不是被轉(zhuǎn)換后的字符表示。為此,可以使用默認(rèn)的 String.raw 標(biāo)簽函數(shù)
五、操作符
ECMA-262描述了一組可用于操作數(shù)據(jù)值的操作符,包括數(shù)學(xué)操作符(如加、減)、位操作符、關(guān)系操作符和相等操作符等。ECMAScript中的操作符是獨(dú)特的,因?yàn)樗鼈兛捎糜诟鞣N值,包括字符串、數(shù)值、布爾值,甚至還有對象。在應(yīng)用給對象時(shí),操作符通常會調(diào)用 valueOf() 和 / 或 toString() 方法來取得可以計(jì)算的值。3.5.1 一元操作符只操作一個(gè)值的操作符叫一元操作符(unary operator)。一元操作符是ECMAScript中最簡單的操作符。
5-1、一元操作符
遞增 / 遞減操作符
遞增和遞減操作符直接照搬自C語言,但有兩個(gè)版本:前綴版和后綴版。顧名思義,前綴版就是位于要操作的變量前頭,后綴版就是位于要操作的變量后頭。前綴遞增操作符會給數(shù)值加1,把兩個(gè)加號( ++ )放到變量前頭即可
2.一元加和減
一元加和減操作符對大多數(shù)開發(fā)者來說并不陌生,它們在ECMAScript中跟在高中數(shù)學(xué)中的用途一樣。一元加由一個(gè)加號( + )表示,放在變量前頭,對數(shù)值沒有任何影響
5-2、位操作符
按位非
按位非操作符用波浪符( ~ )表示,它的作用是返回?cái)?shù)值的一補(bǔ)數(shù)。按位非是ECMAScript中為數(shù)不多的幾個(gè)二進(jìn)制數(shù)學(xué)操作符之一
按位與
按位與操作符用和號( & )表示,有兩個(gè)操作數(shù)。本質(zhì)上,按位與就是將兩個(gè)數(shù)的每一個(gè)位對齊,然后基于真值表中的規(guī)則,對每一位執(zhí)行相應(yīng)的與操作。
按位或
按位或操作符用管道符( | )表示,同樣有兩個(gè)操作數(shù)。
按位異或
按位異或用脫字符( ^ )表示,同樣有兩個(gè)操作數(shù)
左移
左移操作符用兩個(gè)小于號( << )表示,會按照指定的位數(shù)將數(shù)值的所有位向左移動。比如,如果數(shù)值2(二進(jìn)制10)向左移5位,就會得到64(二進(jìn)制1000000)
有符號右移
有符號右移由兩個(gè)大于號( >> )表示,會將數(shù)值的所有32位都向右移,同時(shí)保留符號(正或負(fù))。有符號右移實(shí)際上是左移的逆運(yùn)算
無符號右移
無符號右移用3個(gè)大于號表示( >>> ),會將數(shù)值的所有32位都向右移。對于正數(shù),無符號右移與有符號右移結(jié)果相同
5-3、布爾操作符
邏輯非
邏輯非操作符由一個(gè)嘆號( ! )表示,可應(yīng)用給ECMAScript中的任何值。這個(gè)操作符始終返回布爾值,無論應(yīng)用到的是什么數(shù)據(jù)類型。邏輯非操作符首先將操作數(shù)轉(zhuǎn)換為布爾值,然后再對其取反
邏輯與
邏輯與操作符由兩個(gè)和號( && )表示,應(yīng)用到兩個(gè)值
邏輯或
邏輯或操作符由兩個(gè)管道符( || )表示
5-4、乘性操作符
乘法操作符
乘法操作符由一個(gè)星號( * )表示,可以用于計(jì)算兩個(gè)數(shù)值的乘積。
除法操作符
除法操作符由一個(gè)斜杠( / )表示,用于計(jì)算第一個(gè)操作數(shù)除以第二個(gè)操作數(shù)的商
取模操作符
取模(余數(shù))操作符由一個(gè)百分比符號( % )表示
如果操作數(shù)是數(shù)值,則執(zhí)行常規(guī)除法運(yùn)算,返回余數(shù)。
如果被除數(shù)是無限值,除數(shù)是有限值,則返回 NaN 。
如果被除數(shù)是有限值,除數(shù)是0,則返回 NaN 。
如果是 Infinity 除以 Infinity ,則返回 NaN 。
如果被除數(shù)是有限值,除數(shù)是無限值,則返回被除數(shù)。
如果被除數(shù)是0,除數(shù)不是0,則返回0。
如果有不是數(shù)值的操作數(shù),則先在后臺用 Number() 函數(shù)將其轉(zhuǎn)換為數(shù)值,然后再應(yīng)用上述規(guī)則。
六、語句
ECMA-262描述了一些語句(也稱為流控制語句),而ECMAScript中的大部分語法都體現(xiàn)在語句中。語句通常使用一或多個(gè)關(guān)鍵字完成既定的任務(wù)。語句可以簡單,也可以復(fù)雜。簡單的如告訴函數(shù)退出,復(fù)雜的如列出一堆要重復(fù)執(zhí)行的指令。
6-1、do-while 語句
do-while 語句是一種后測試循環(huán)語句,即循環(huán)體中的代碼執(zhí)
行后才會對退出條件進(jìn)行求值。換句話說,循環(huán)體內(nèi)的代碼至少執(zhí)行
一次
6-2、while 語句
while 語句是一種先測試循環(huán)語句,即先檢測退出條件,再執(zhí)行循環(huán)體內(nèi)的代碼。因此, while 循環(huán)體內(nèi)的代碼有可能不會執(zhí)行
七、函數(shù)
函數(shù)對任何語言來說都是核心組件,因?yàn)樗鼈兛梢苑庋b語句,然后在任何地方、任何時(shí)間執(zhí)行。ECMAScript中的函數(shù)使用function 關(guān)鍵字聲明,后跟一組參數(shù),然后是函數(shù)體。
ECMAScript中的函數(shù)不需要指定是否返回值。任何函數(shù)在任何時(shí)間都可以使用 return 語句來返回函數(shù)的值,用法是后跟要返回的值
函數(shù) sum() 會將兩個(gè)值相加并返回結(jié)果。注意,除了 return語句之外沒有任何特殊聲明表明該函數(shù)有返回值
嚴(yán)格模式對函數(shù)也有一些限制:
函數(shù)不能以 eval 或 arguments 作為名稱;
函數(shù)的參數(shù)不能叫 eval 或 arguments ;
兩個(gè)函數(shù)的參數(shù)不能叫同一個(gè)名稱。
八、變量,作用域與內(nèi)存
4-1、原始值與引用值
ECMAScript變量可以包含兩種不同類型的數(shù)據(jù):原始值和引用值。原始值(primitive value)就是最簡單的數(shù)據(jù),引用值(referencevalue)則是由多個(gè)值構(gòu)成的對象。
在把一個(gè)值賦給變量時(shí),JavaScript引擎必須確定這個(gè)值是原始值還是引用值。上一章討論了6種原始值: Undefined 、 Null 、Boolean 、 Number 、 String 和 Symbol 。保存原始值的變量是按值(by value)訪問的,因?yàn)槲覀儾僮鞯木褪谴鎯υ谧兞恐械膶?shí)際值。
引用值是保存在內(nèi)存中的對象。與其他語言不同,JavaScript不允許直接訪問內(nèi)存位置,因此也就不能直接操作對象所在的內(nèi)存空間。在操作對象時(shí),實(shí)際上操作的是對該對象的引用(reference)而非實(shí)
際的對象本身。為此,保存引用值的變量是按引用(by reference)訪問的
注意:在很多語言中,字符串是使用對象表示的,因此被認(rèn)為是引用類型。ECMAScript打破了這個(gè)慣例。
動態(tài)屬性
原始值和引用值的定義方式很類似,都是創(chuàng)建一個(gè)變量,然后給它賦一個(gè)值。不過,在變量保存了這個(gè)值之后,可以對這個(gè)值做什么,則大有不同。對于引用值而言,可以隨時(shí)添加、修改和刪除其屬性和方法
復(fù)制值
除了存儲方式不同,原始值和引用值在通過變量復(fù)制時(shí)也有所不同。在通過變量把一個(gè)原始值賦值到另一個(gè)變量時(shí),原始值會被復(fù)制到新變量的位置。
在把引用值從一個(gè)變量賦給另一個(gè)變量時(shí),存儲在變量中的值也會被復(fù)制到新變量所在的位置。區(qū)別在于,這里復(fù)制的值實(shí)際上是一個(gè)指針,它指向存儲在堆內(nèi)存中的對象。操作完成后,兩個(gè)變量實(shí)際上指向同一個(gè)對象,因此一個(gè)對象上面的變化會在另一個(gè)對象上反映出來
傳遞參數(shù)
ECMAScript中所有函數(shù)的參數(shù)都是按值傳遞的。這意味著函數(shù)外的值會被復(fù)制到函數(shù)內(nèi)部的參數(shù)中,就像從一個(gè)變量復(fù)制到另一個(gè)變量一樣。如果是原始值,那么就跟原始值變量的復(fù)制一樣,如果是引用值,那么就跟引用值變量的復(fù)制一樣。對很多開發(fā)者來說,這一塊可能會不好理解,畢竟變量有按值和按引用訪問,而傳參則只有按值傳遞
在按值傳遞參數(shù)時(shí),值會被復(fù)制到一個(gè)局部變量(即一個(gè)命名參數(shù),或者用ECMAScript的話說,就是 arguments 對象中的一個(gè)槽位)。在按引用傳遞參數(shù)時(shí),值在內(nèi)存中的位置會被保存在一個(gè)局部變量,這意味著對本地變量的修改會反映到函數(shù)外部
確定類型
前一章提到的 typeof 操作符最適合用來判斷一個(gè)變量是否為原始類型。更確切地說,它是判斷一個(gè)變量是否為字符串、數(shù)值、布爾值或 undefined 的最好方式。如果值是對象或 null ,那么typeof 返回 “object”
按照定義,所有引用值都是 Object 的實(shí)例,因此通過instanceof 操作符檢測任何引用值和 Object 構(gòu)造函數(shù)都會返回 true 。類似地,如果用 instanceof 檢測原始值,則始終會返回 false ,因?yàn)樵贾挡皇菍ο蟆?/p>
注意 typeof 操作符在用于檢測函數(shù)時(shí)也會返回 “function” 。當(dāng)在Safari(直到Safari 5)和Chrome(直到Chrome 7)中用于檢測正則表達(dá)式時(shí),由于實(shí)現(xiàn)細(xì)節(jié)的原因,typeof 也會返回 “function” 。ECMA-262規(guī)定,任何實(shí)現(xiàn)內(nèi)部 [[Call]] 方法的對象都應(yīng)該在 typeof 檢測時(shí)返回 “function” 。因?yàn)樯鲜鰹g覽器中的正則表達(dá)式實(shí)現(xiàn)了這個(gè)方法,所以 typeof 對正則表達(dá)式也返回 “function” 。在IE和Firefox中, typeof 對正則表達(dá)式返回 “object” 。
4-2、執(zhí)行上下文與作用域
執(zhí)行上下文(以上簡稱“上下文”)的概念在JavaScript中是頗為重要的。變量或函數(shù)的上下文決定了它們可以訪問哪些數(shù)據(jù),以及它們的行為。每個(gè)上下文都有一個(gè)關(guān)聯(lián)的變量對象(variable object),而
這個(gè)上下文中定義的所有變量和函數(shù)都存在于這個(gè)對象上。雖然無法通過代碼訪問變量對象,但后臺處理數(shù)據(jù)會用到它。
全局上下文是最外層的上下文。根據(jù)ECMAScript實(shí)現(xiàn)的宿主環(huán)境,表示全局上下文的對象可能不一樣。在瀏覽器中,全局上下文就是我們常說的 window 對象(第12章會詳細(xì)介紹),因此所有通過
var 定義的全局變量和函數(shù)都會成為 window 對象的屬性和方法。使用 let 和 const 的頂級聲明不會定義在全局上下文中,但在作用域鏈解析上效果是一樣的。上下文在其所有代碼都執(zhí)行完畢后會被銷毀,包括定義在它上面的所有變量和函數(shù)(全局上下文在應(yīng)用程序退出前才會被銷毀,比如關(guān)閉網(wǎng)頁或退出瀏覽器)。
每個(gè)函數(shù)調(diào)用都有自己的上下文。當(dāng)代碼執(zhí)行流進(jìn)入函數(shù)時(shí),函數(shù)的上下文被推到一個(gè)上下文棧上。在函數(shù)執(zhí)行完之后,上下文棧會彈出該函數(shù)上下文,將控制權(quán)返還給之前的執(zhí)行上下文。ECMAScript
程序的執(zhí)行流就是通過這個(gè)上下文棧進(jìn)行控制的。上下文中的代碼在執(zhí)行的時(shí)候,會創(chuàng)建變量對象的一個(gè)作用域鏈(scope chain)。這個(gè)作用域鏈決定了各級上下文中的代碼在訪問變量和函數(shù)時(shí)的順序。代碼正在執(zhí)行的上下文的變量對象始終位于作用域鏈的最前端。如果上下文是函數(shù),則其活動對象(activationobject)用作變量對象?;顒訉ο笞畛踔挥幸粋€(gè)定義變量:arguments 。(全局上下文中沒有這個(gè)變量。)作用域鏈中的下一個(gè)變量對象來自包含上下文,再下一個(gè)對象來自再下一個(gè)包含上下文。以此類推直至全局上下文;全局上下文的變量對象始終是作用域鏈的最后一個(gè)變量對象
作用域鏈增強(qiáng)
雖然執(zhí)行上下文主要有全局上下文和函數(shù)上下文兩種( eval()調(diào)用內(nèi)部存在第三種上下文),但有其他方式來增強(qiáng)作用域鏈。某些語句會導(dǎo)致在作用域鏈前端臨時(shí)添加一個(gè)上下文,這個(gè)上下文在代碼
執(zhí)行后會被刪除。
變量聲明
ES6之后,JavaScript的變量聲明經(jīng)歷了翻天覆地的變化。直到
ECMAScript 5.1, var 都是聲明變量的唯一關(guān)鍵字。ES6不僅增加了
let 和 const 兩個(gè)關(guān)鍵字,而且還讓這兩個(gè)關(guān)鍵字壓倒性地超越
var 成為首選。
使用 var 的函數(shù)作用域聲明
在使用 var 聲明變量時(shí),變量會被自動添加到最接近的上下文。在函數(shù)中,最接近的上下文就是函數(shù)的局部上下文。在with 語句中,最接近的上下文也是函數(shù)上下文。如果變量未經(jīng)聲明就被初始化了,那么它就會自動被添加到全局上下文注意:未經(jīng)聲明而初始化變量是JavaScript編程中一個(gè)非常常見的錯(cuò)誤,會導(dǎo)致很多問題。為此,讀者在初始化變量之前一定要先聲明變量。在嚴(yán)格模式下,未經(jīng)聲明就初始化變量會報(bào)錯(cuò)
var 聲明會被拿到函數(shù)或全局作用域的頂部,位于作用域中所有代碼之前。這個(gè)現(xiàn)象叫作“提升”(hoisting)。提升讓同一作用域中的代碼不必考慮變量是否已經(jīng)聲明就可以直接使用。可是在實(shí)踐中,提升也會導(dǎo)致合法卻奇怪的現(xiàn)象,即在變量聲明之前使用變量。
使用 let 的塊級作用域聲明
ES6新增的 let 關(guān)鍵字跟 var 很相似,但它的作用域是塊級的,這也是JavaScript中的新概念。塊級作用域由最近的一對包含花括號 {} 界定。換句話說, if 塊、 while 塊、 function塊,甚至連單獨(dú)的塊也是 let 聲明變量的作用域。
使用 const 的常量聲明
除了 let ,ES6同時(shí)還增加了 const 關(guān)鍵字。使用 const 聲明的變量必須同時(shí)初始化為某個(gè)值。一經(jīng)聲明,在其生命周期的任何時(shí)候都不能再重新賦予新值
注意 開發(fā)實(shí)踐表明,如果開發(fā)流程并不會因此而受很大影響,就應(yīng)該盡可能地多使用 const 聲明,除非確實(shí)需要一個(gè)將來會重新賦值的變量。這樣可以從根本上保證提前發(fā)現(xiàn)重新賦值導(dǎo)致的bug
4-3、垃圾回收
JavaScript是使用垃圾回收的語言,也就是說執(zhí)行環(huán)境負(fù)責(zé)在代碼執(zhí)行時(shí)管理內(nèi)存。在C和C++等語言中,跟蹤內(nèi)存使用對開發(fā)者來說是個(gè)很大的負(fù)擔(dān),也是很多問題的來源。JavaScript為開發(fā)者卸下了這個(gè)負(fù)擔(dān),通過自動內(nèi)存管理實(shí)現(xiàn)內(nèi)存分配和閑置資源回收。基本思路很簡單:確定哪個(gè)變量不會再使用,然后釋放它占用的內(nèi)存。這個(gè)過程是周期性的,即垃圾回收程序每隔一定時(shí)間(或者說在代碼執(zhí)行過程中某個(gè)預(yù)定的收集時(shí)間)就會自動運(yùn)行。垃圾回收過程是一個(gè)近似且不完美的方案,因?yàn)槟硥K內(nèi)存是否還有用,屬于“不可判定的”問題,意味著靠算法是解決不了的。
我們以函數(shù)中局部變量的正常生命周期為例。函數(shù)中的局部變量會在函數(shù)執(zhí)行時(shí)存在。此時(shí),棧(或堆)內(nèi)存會分配空間以保存相應(yīng)的值。函數(shù)在內(nèi)部使用了變量,然后退出。此時(shí),就不再需要那個(gè)局部變量了,它占用的內(nèi)存可以釋放,供后面使用。這種情況下顯然不再需要局部變量了,但并不是所有時(shí)候都會這么明顯。垃圾回收程序必須跟蹤記錄哪個(gè)變量還會使用,以及哪個(gè)變量不會再使用,以便回收內(nèi)存。如何標(biāo)記未使用的變量也許有不同的實(shí)現(xiàn)方式。不過,在瀏覽器的發(fā)展史上,用到過兩種主要的標(biāo)記策略:標(biāo)記清理和引用計(jì)數(shù)。
標(biāo)記清理
JavaScript最常用的垃圾回收策略是標(biāo)記清理(mark-and-sweep)。當(dāng)變量進(jìn)入上下文,比如在函數(shù)內(nèi)部聲明一個(gè)變量時(shí),這個(gè)變量會被加上存在于上下文中的標(biāo)記。而不在上下文中的變量,邏輯上講,永遠(yuǎn)不應(yīng)該釋放它們的內(nèi)存,因?yàn)橹灰舷挛闹械拇a在運(yùn)行,就有可能用到它們。當(dāng)變量離開上下文時(shí),也會被加上離開上下文的標(biāo)記。
給變量加標(biāo)記的方式有很多種。比如,當(dāng)變量進(jìn)入上下文時(shí),反轉(zhuǎn)某一位;或者可以維護(hù)“在上下文中”和“不在上下文中”兩個(gè)變量列表,可以把變量從一個(gè)列表轉(zhuǎn)移到另一個(gè)列表。標(biāo)記過程的實(shí)現(xiàn)并不重要,關(guān)鍵是策略。
垃圾回收程序運(yùn)行的時(shí)候,會標(biāo)記內(nèi)存中存儲的所有變量(記住,標(biāo)記方法有很多種)。然后,它會將所有在上下文中的變量,以及被在上下文中的變量引用的變量的標(biāo)記去掉。在此之后再被加上標(biāo)記的變量就是待刪除的了,原因是任何在上下文中的變量都訪問不到它們了。隨后垃圾回收程序做一次內(nèi)存清理,銷毀帶標(biāo)記的所有值并收回它們的內(nèi)存。
到了2008年,IE、Firefox、Opera、Chrome和Safari都在自己的JavaScript實(shí)現(xiàn)中采用標(biāo)記清理(或其變體),只是在運(yùn)行垃圾回收的頻率上有所差異。
引用計(jì)數(shù)
另一種沒那么常用的垃圾回收策略是引用計(jì)數(shù)(referencecounting)。其思路是對每個(gè)值都記錄它被引用的次數(shù)。聲明變量并給它賦一個(gè)引用值時(shí),這個(gè)值的引用數(shù)為1。如果同一個(gè)值又被賦給另一個(gè)變量,那么引用數(shù)加1。類似地,如果保存對該值引用的變量被其他值給覆蓋了,那么引用數(shù)減1。當(dāng)一個(gè)值的引用數(shù)為0時(shí),就說明沒辦法再訪問到這個(gè)值了,因此可以安全地收回其內(nèi)存了。垃圾回收程序
下次運(yùn)行的時(shí)候就會釋放引用數(shù)為0的值的內(nèi)存。引用計(jì)數(shù)最早由Netscape Navigator 3.0采用,但很快就遇到了嚴(yán)重的問題:循環(huán)引用。所謂循環(huán)引用,就是對象A有一個(gè)指針指向?qū)ο驜,而對象B也引用了對象A。
把變量設(shè)置為 null 實(shí)際上會切斷變量與其之前引用值之間的關(guān)系。當(dāng)下次垃圾回收程序運(yùn)行時(shí),這些值就會被刪除,內(nèi)存也會被回收。
為了補(bǔ)救這一點(diǎn),IE9把BOM和DOM對象都改成了JavaScript對象,這同時(shí)也避免了由于存在兩套垃圾回收算法而導(dǎo)致的問題,還消除了常見的內(nèi)存泄漏現(xiàn)象。
內(nèi)存泄漏
寫得不好的JavaScript可能出現(xiàn)難以察覺且有害的內(nèi)存泄漏問題。在內(nèi)存有限的設(shè)備上,或者在函數(shù)會被調(diào)用很多次的情況下,內(nèi)存泄漏可能是個(gè)大問題。JavaScript中的內(nèi)存泄漏大部分是由不合理的引用導(dǎo)致的
以上是“JavaScript的基礎(chǔ)知識有哪些”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。