Hyper Text Markup Language, 超文本標(biāo)記語言
標(biāo)記又稱為標(biāo)簽(Tag), 一般語法:
<tagName></tagName>
它可以有屬性(Attribute):
<tagName attributeName="value">, 如:
<meta charset="utf-8" />
標(biāo)簽也可以不成對(duì)地關(guān)閉:
<tagName />
HTML文檔由瀏覽器解釋并執(zhí)行。
<!DOCTYPE html> ----- 告訴瀏覽器用html5的標(biāo)準(zhǔn)來解釋和執(zhí)行該網(wǎng)頁
<html>
<head> ---- 頭部, 可包含meta, title等標(biāo)簽
</head>
<body> ---- 主體, 包含主要內(nèi)容
</body>
</html>
<meta charset="utf-8" /> 用于告訴瀏覽器用什么樣的字符編碼來解釋網(wǎng)頁中的文本.
常見編碼:
iso-8859-1: 純英文編碼
gbk, gb2312: 簡(jiǎn)體中文編碼
big5: 大五碼,繁體中文編碼,主要應(yīng)用于臺(tái)灣地區(qū)
utf-8: 國際首選編碼,它兼容所有的字符
除此之外, meta還可以通過keywords, description屬性對(duì)頁面關(guān)鍵詞及描述信息進(jìn)行設(shè)置, 以提高搜索引擎的命中.
網(wǎng)頁標(biāo)題, 顯示在瀏覽器選項(xiàng)卡的標(biāo)題欄上!
h1-h6: 內(nèi)容標(biāo)題標(biāo)簽
p: 段落
br: 換行
hr: 水平線
strong: 粗體文本
em: 斜體文本
span: 無任何特殊樣式的文本
pre: 預(yù)格式標(biāo)簽,其中的內(nèi)容在頁面上帶格式渲染
small: 比當(dāng)前字體小的文本
空格
< 小于
> 大于
? 版權(quán)符
" 雙引號(hào)
<!-- 注釋內(nèi)容 -->
<img
src="圖像地址"
title="鼠標(biāo)懸停提示"
alt="圖像加載錯(cuò)誤時(shí)的替代文本"
width="寬度"
height="高度"
/>
圖像地址分為2種:
1. 相對(duì)地址, 如: img/cc.jpg
2. 絕對(duì)地址, 如: http://img.bcd.com/2017/1644232421.jpg
<a href="鏈接地址" target="目標(biāo)窗口">文本|圖片</a>
目標(biāo)窗口:
_self: 目標(biāo)頁面在當(dāng)前窗口打開
_blank: 目標(biāo)頁面在新窗口中打開
如果是在頁面具有frameset/frame/iframe的場(chǎng)景下:
_top: 在頂級(jí)窗口中打開
_parent: 在父級(jí)窗口中打開
_自定義名稱: 在指定的特定窗口中打開
三種用法:
1. 頁面間鏈接
<a href="page/login.html"></a>
2. 錨鏈接
<a href="#help"></a>
help是本頁面中一處id為help的標(biāo)簽, 如: <p id="help">
或者:
help是通過a標(biāo)簽命名的錨記, 如: <a name="help"></a>
3. 功能性鏈接
喚醒本地安裝的外部程序如 outlook/foxmail/qq/msn/aliwangwang...
<a href="mailto:abcdef@qq.com"></a>
div是一個(gè)容器, 常用于頁面的布局
標(biāo)簽的分類:
1. 塊級(jí)標(biāo)簽/塊級(jí)元素
如: div, h1-h6, p, hr
特征: 獨(dú)占容器中的一行, 其寬度是容器的100%
2. 行級(jí)標(biāo)簽/行級(jí)元素
如: span, img, strong, em, a
特征1: 多個(gè)行級(jí)元素可以同處一行, 其寬度由內(nèi)容來撐開(auto)
特征2: 大部分行級(jí)元素設(shè)置其width/height無效
ctrl + D : 刪除當(dāng)前行
ctrl + PgUp : 當(dāng)前行上移
ctrl + PgDown : 當(dāng)前行下移
ctrl + / : 注釋 | 取消注釋
ctrl + shift + F : 整理代碼格式
ctrl + C : 復(fù)制當(dāng)前行
ctrl + X : 剪切當(dāng)前行
ctrl + V : 粘貼
ctrl + Z : 撤消上一步操作
ctrl + S : 保存當(dāng)前文件
ctrl + shift + S : 保存項(xiàng)目中全部文件
ctrl + Enter : 在當(dāng)前行的下方插入新行
ctrl + shift + Enter : 在當(dāng)前行的上方插入新行
以上知識(shí)能做的效果圖
部分效果
文章開始之前我想throw一個(gè)問題:你知道操作符都有哪些嗎?,然后標(biāo)識(shí)符又代表什么?
如果你說我看到這些也是一臉蒙蔽的狀態(tài),(一臉懵逼不是說你一點(diǎn)不會(huì),而是你好像知道又好像不知道,這是我們開發(fā)中的大忌。)或許有這種感覺的有部分還是具有開發(fā)經(jīng)驗(yàn)程序員。那你應(yīng)該會(huì)懷著激動(dòng)的心情繼續(xù)往下看,我打算先說一說操作符之外的可能你沒有注意到的標(biāo)識(shí)符,而且你馬上就要知道問題的答案了。
我們先看一段代碼片段吧:
var arr = [1,2,3];function total(arr){ var len = arr.length;
我們首先說操作符,代碼片段中有哪些操作符?
arr total len sum i
對(duì),沒錯(cuò),就這些,但你看到這寫的時(shí)候應(yīng)該會(huì)恍然大悟: 我天天用的變量和函數(shù)名就是操作符! 雖然你說的沒錯(cuò)(其實(shí)我并不認(rèn)為這些會(huì)難倒大部分人), 但是咱可不能這么隨意,標(biāo)識(shí)符在JavaScript中是這么定義的:
標(biāo)識(shí)符:指的是變量、函數(shù)、對(duì)象屬性的名字。
當(dāng)然每種語言的標(biāo)識(shí)符都有自己的定義方式,有它自己的規(guī)則,你可能已經(jīng)對(duì)此倒背如流,但是請(qǐng)?jiān)试S我再次書寫一遍:
第一個(gè)字母必須是一個(gè)字母、下劃線、或者一個(gè)美元符號(hào)
其他字符可以是字母、下劃線、美元符號(hào)和數(shù)字
OK,下面我們找出代碼片段里面的操作符:
+, <,+=
事實(shí)總是讓人難堪,這也是我們每天用到的,可能90%的人都已經(jīng)知道這一切了,但是這不是最恐怖的,最恐怖的是你就是剩下的10%。現(xiàn)在我們開始真正對(duì)操作符的學(xué)習(xí)。
先看它的定義:
用于操作數(shù)據(jù)值的叫做操作符。
然而JS操作符實(shí)在是太復(fù)雜,我不得不將他們分類來說:
一元操作符
何為一元操作符? 請(qǐng)看下面的定義:
只能操作一個(gè)值的操作符叫做一元操作符
如定義所說,一元操作符只能操作一個(gè)值,就如同以下實(shí)例:
var num = 0;num++;
這在JavaScript同時(shí)不僅僅是JavaScript中叫做自增操作符,它屬于一元操作符,同時(shí)還有這些:++num,num--,--num。
這個(gè)時(shí)候一些奇怪的想法突然從腦袋里冒出來:一個(gè)字符串進(jìn)行自增操作會(huì)怎樣?一個(gè)布爾值呢?甚至它是一個(gè)對(duì)象。 我們可以立即打開控制臺(tái)操作一下:
4.1.png
不同類型的數(shù)據(jù)都進(jìn)行了自加操作后表現(xiàn)都不同,在ECMA規(guī)范中他們的規(guī)則是這么定義的:
帶有有效數(shù)字的字符串自增(減),會(huì)將字符串值轉(zhuǎn)換為其數(shù)字值,然后自增(減)1。
不帶數(shù)字的字符串自增(減),會(huì)直接變?yōu)镹aN,一個(gè)數(shù)字類型。
布爾值自增(減)會(huì)先將其轉(zhuǎn)為數(shù)值型(false為0,true為1),再進(jìn)行自增(減)操作。
浮點(diǎn)數(shù)就直接自增(減)
對(duì)象的話比較繁瑣,它會(huì)先調(diào)用每一個(gè)對(duì)象都具有的 valueOf() 方法,如果是NaN,那就再調(diào)用toString()方法,再進(jìn)行操作。
這些定義我把它總結(jié)成了一句話:解析器會(huì)想盡辦法去把數(shù)值類型之外的數(shù)據(jù)嘗試轉(zhuǎn)化為數(shù)值類型,再進(jìn)行操作。
這里有一個(gè)對(duì)象類型的比較特殊,我不打算對(duì)此長(zhǎng)篇大論,你如果求知欲旺盛,可以自己打開控制臺(tái)或者編輯軟件嘗試一下,但是不要忘了閱讀Object中的valueOf()和toString()的API
當(dāng)然,一元操作符還包括這種:s1 = -s1; s2 = +s2
,這種單個(gè)操作符會(huì)在你想轉(zhuǎn)換數(shù)值的正負(fù)時(shí)派上作用。
布爾操作符
布爾操作符有三種: !,&&,|| 。
在這里我首先拿出其中任意一個(gè)來談,比如是 ! ,非操作符。
我們都知道此操作符的作用,就是對(duì)布爾值取反,所以這個(gè)時(shí)候,我想知道,如果是字符串,是其他數(shù)據(jù)類型,會(huì)發(fā)生什么?
在迫不及待的實(shí)驗(yàn)下,我得出了以下結(jié)果:
4.2.png
如果你想徹底搞清楚這到底如果分辨,那么你需要知道此定義:除0、" "、null、NaN、false、undefined之外,其余所有數(shù)據(jù)的布爾值都為true。然后你可以再次看上面圖片中的結(jié)果,相信你會(huì)恍然大悟。當(dāng)然你也可以實(shí)驗(yàn)各種不同的數(shù)據(jù)類型,但是任何值都不會(huì)逃出這個(gè)定義。
其次,是布爾操作符中的 &&,與操作符。
此操作符有兩個(gè)我們無法忽視的特性:
如果兩個(gè)操作數(shù)其中有一個(gè)不是布爾值,那它就不一定返回的是布爾值。
如果第一個(gè)操作數(shù)的布爾值是false,那么第二個(gè)操作數(shù)就不會(huì)執(zhí)行,直接返回第一個(gè)操作數(shù)的值。
我們可以試驗(yàn)一下它到底如何表現(xiàn):
4.3.png
在第一個(gè)語句中第一個(gè)操作數(shù)的布爾值為false,后面的a++就不會(huì)再被執(zhí)行,然后第一個(gè)操作數(shù)為真,那執(zhí)行它后會(huì)繼續(xù)往下執(zhí)行,所以b的結(jié)果是1,那兩個(gè)操作數(shù)的布爾值都為真,則會(huì)返回第二個(gè)操作數(shù)的值(注意,不是它的布爾值),正如你所看到的,它返回了d的值 3。
如果你想知道其他值如何表現(xiàn),你可以自己試驗(yàn)一番,這將會(huì)比任何人的講述都讓你記憶深刻。
最后是 ||,或操作符。
或操作符同樣有兩個(gè)特性:
如果有一個(gè)操作數(shù)不是布爾值,邏輯或不一定會(huì)返回布爾值
如果第一個(gè)操作數(shù)為真,那么會(huì)直接返回第一個(gè)操作數(shù)
他的特性和 與操作符真好相反,在次我不再演示它具體的表現(xiàn)行為,而是把這些交給正在閱讀并且極有興趣的讀者們。
乘性操作符
乘性操作符在ECMA規(guī)范中有三個(gè):*,/,%
即 乘法,除法,求模。
這三種操作符都是作用與數(shù)值上,但是如果操作數(shù)不是數(shù)值呢?,在一元操作符中我們已經(jīng)提過:解析器會(huì)想盡辦法去把數(shù)值類型之外的數(shù)據(jù)嘗試轉(zhuǎn)化為數(shù)值類型,再進(jìn)行操作,這同樣適用于此。如果你仍然存在我不清楚如何將非數(shù)值類型數(shù)據(jù)轉(zhuǎn)換為數(shù)值型數(shù)據(jù)的疑問的話,我建議你可以去看一看我上一篇文章談一談JavaScript中的基本數(shù)據(jù)類型。
加性操作符
加法減法或許是我們見過的最簡(jiǎn)單的操作符了,但是在ECMA規(guī)范中,他們也會(huì)有一些特殊的行為,我們就重點(diǎn)看一下他有什么特殊行為
如果操作數(shù)都是數(shù)值,則:
按照常規(guī)的加法計(jì)算
操作數(shù)有一個(gè)是NaN,則運(yùn)算結(jié)果都是NaN。
如果操作數(shù)沒有字符串,則轉(zhuǎn)化操作數(shù)為數(shù)值型,再進(jìn)行加法運(yùn)算符
如果有一個(gè)操作數(shù)是字符串,就會(huì)有以下規(guī)則:
如果兩個(gè)都是字符串,則拼接字符串。
如果只有一個(gè)是字符串,則將另一個(gè)非字符串的操作數(shù)轉(zhuǎn)化為字符串,然后再拼接
如果只有一個(gè)字符串,且另一個(gè)操作數(shù)是對(duì)象、數(shù)值、布爾值,則調(diào)用他們的toString()方法取得相應(yīng)的字符串值,然后再應(yīng)用前面的字符串的規(guī)則。
如果只有一個(gè)字符串,且另一個(gè)操作數(shù)是undefined、null,則后臺(tái)會(huì)直接用String() 函數(shù)將他們轉(zhuǎn)化為 "undefined"和"null",然后再應(yīng)用以上規(guī)則。
我直接上圖,看他們的運(yùn)行結(jié)果:
4.4.png
關(guān)系操作符
關(guān)系操作符包括以下幾種:<,>,<=,>= 。
也許你會(huì)說 1 < 2,5 > 3 這種小兒科值得我們?nèi)パ芯??
如果下面兩個(gè)問題你不能很好的回答,我覺得你還是要腳踏實(shí)地,戒驕戒躁。
//以下布爾值為多少?"12" < "3""12" < 3
答案暫時(shí)不給,因?yàn)榈玫剿枰某杀咎停恍枰銊?dòng)動(dòng)手指。
至于原因我們可以看看關(guān)系操作符中如果出現(xiàn)了非數(shù)值,ECMA規(guī)范會(huì)如何規(guī)定:
如果兩個(gè)操作數(shù)都是字符串,則比較兩個(gè)字符串對(duì)應(yīng)的字符編碼值
如果一個(gè)操作數(shù)是數(shù)值,則會(huì)轉(zhuǎn)化另外一個(gè)操作數(shù)為數(shù)值,然后執(zhí)行數(shù)值比較
如果一個(gè)操作數(shù)是對(duì)象,它會(huì)先調(diào)用每一個(gè)對(duì)象都具有的 valueOf() 方法,如果此對(duì)象沒有valueOf()方法,那就再調(diào)用toString()方法,再根據(jù)以上規(guī)則去比較
相等操作符
在處理兩數(shù)值相等的問題上,ECMA規(guī)范給出了兩種解決方案:相等和不相等,全等和不全等。
==、!= 相等和不相等
相等不不相等都在比較之前都會(huì)轉(zhuǎn)換操作數(shù)的類型,比如這樣:
"23" == 23 // true
具體轉(zhuǎn)換規(guī)則如下:
如果其中一個(gè)操作數(shù)是布爾值,則比較相等性之前會(huì)將其轉(zhuǎn)化為數(shù)值(false轉(zhuǎn)化為0,true轉(zhuǎn)化為1)
如果其中一個(gè)操作數(shù)是字符串,另一個(gè)操作數(shù)是數(shù)值,則會(huì)將字符串轉(zhuǎn)化為數(shù)值
如果一個(gè)操作數(shù)是對(duì)象,另一個(gè)不是,則會(huì)調(diào)用對(duì)象的valueOf()方法,用得到的基本數(shù)據(jù)類型的值按照前面的規(guī)則去比較。
在比較時(shí)他們還會(huì)遵循以下規(guī)則:
null 和 undefined相等
比較相等性之前,不能將null和undefined轉(zhuǎn)換為其他任何值
兩個(gè)操作數(shù)中只要出現(xiàn)NaN,最后的結(jié)果一定是false,即使兩個(gè)都是NaN
如果兩個(gè)操作數(shù)都是對(duì)象,則比較它們是不是同一個(gè)對(duì)象。如果兩個(gè)操作數(shù)都指向同一個(gè)對(duì)象,則相等操作符返回true,否則返回false
這些繁雜的規(guī)則或許會(huì)繞暈?zāi)悖€是拿圖表更清楚一點(diǎn):
表達(dá)式 | 值 |
---|---|
null == undefined | true |
"NaN" == NaN | false |
5 == NaN | false |
NaN == NaN | false |
NaN != NaN | true |
false == 0 | true |
true == 1 | false |
true == 2 | false |
undefined == 0 | false |
null == 0 | false |
"5" == 5 | false |
===、!== 全等和不全等
全等和相等唯一的區(qū)別就是全等并不會(huì)進(jìn)行類型轉(zhuǎn)換,只有同等類型的值才回去比較,不同數(shù)據(jù)類型的值就直接返回false。
"55" === 55 // false,數(shù)據(jù)類型不同false === 0 // false,數(shù)據(jù)類型不同
正是因?yàn)槿炔淮嬖陬愋娃D(zhuǎn)換問題,為了保持代碼中數(shù)據(jù)類型的完整性,我們更應(yīng)該多使用全等和不全等操作符。
條件操作符
條件操作符是這樣使用的:
var result = (5 > 3) ? "對(duì)就返回這句話" : "不對(duì)就返回這句話"
由一個(gè) ? 和 : 組成,?之前的表達(dá)式如果為真就返回 ? 之前 : 之后的表達(dá)式,如果為假,就返回 : 之后的表達(dá)式
賦值操作符
賦值操作符簡(jiǎn)單來說就是把右邊的值賦給左側(cè)的變量:
var num = 2
;
在賦值操作符之前可以添加一個(gè)乘性操作符、加性操作符和位操作符,比如這樣:
num += 10 // num = 12
;
逗號(hào)操作符
逗號(hào)操作符可以在一行語句中執(zhí)行多個(gè)操作:
var num1 = 1, num2 = 2, num3 = 3;
你還可以這樣用:
var num = (num1++,num3++,num3) // num 為 4
在賦值語句中,逗號(hào)操作符會(huì)依次執(zhí)行每一個(gè)語句并且返回表達(dá)式的最后一項(xiàng)。
位操作符
對(duì)于位操作位,這里不打算進(jìn)行深入講解,因?yàn)榇瞬僮鞣贘avaScript中并不常用,所有有關(guān)內(nèi)存的操作我們理應(yīng)交給解釋器去做。如果你哪天打算用C語言去做開發(fā),那我一定建議你好好學(xué)一學(xué)這個(gè)操作符。
所有操作符學(xué)習(xí)完畢,自己也有很大的提升,希望能給各位前端開發(fā)者們一些幫助和啟發(fā),如果您在閱讀過程中發(fā)現(xiàn)錯(cuò)誤,請(qǐng)大膽指出,我們共同進(jìn)步。
文共5530字,預(yù)計(jì)學(xué)習(xí)時(shí)長(zhǎng)11分鐘
延展操作符首次于ES6中引入,并很快成為最受歡迎的功能之一。盡管事實(shí)上延展操作符只適用于數(shù)組,但仍有建議提出可以將其功能擴(kuò)展到對(duì)象。最終ES9中引入了此功能。
本教程將說明為什么應(yīng)該使用擴(kuò)展運(yùn)算符,以及它如何運(yùn)作。
目錄
1.為什么要使用延展操作符
2.克隆數(shù)組/對(duì)象
3.將類數(shù)組結(jié)構(gòu)轉(zhuǎn)換為數(shù)組
4.延展操作符作為參數(shù)
5.將元素添加到數(shù)組/對(duì)象
6.合并數(shù)組/對(duì)象
為什么要使用延展操作符
閱讀了以上列表之后,你可能會(huì)想:“JavaScript就已經(jīng)能夠滿足需求了,為什么還要使用延展操作符?”我們先來介紹下不變性。
牛津詞典:不變性 - 隨著時(shí)間的推移不變或無法改變。
作為軟件開發(fā)的術(shù)語,不可變指狀態(tài)不能隨時(shí)間變化的值。實(shí)際上,通常使用的大多數(shù)值(原始值,如字符串,整數(shù)等)都是不可變的。
然而,JavaScript中非常特殊的一點(diǎn)是,其中的數(shù)組和對(duì)象實(shí)際上是可變的。這可能成為一個(gè)大問題。以下實(shí)例闡明了其中原因:
const mySquirtle={ name: 'Squirtle', type: 'Water', hp: 100 }; const anotherSquirtle = mySquirtle; anotherSquirtle.hp = 0; console.log(mySquirtle); //Result: { name: 'Squirtle', type: 'Water', hp: 0 }
從上述代碼中可以看到,我們有一個(gè)變量Squirtle(杰尼龜)。因?yàn)閯倓傇L問了神奇寶貝中心,這只杰尼龜?shù)腍P值為100。
由于還想要另一只杰尼龜,因此聲明變量為anotherSquirtle,將初始Squirtle指定為它的值。一場(chǎng)苦戰(zhàn)后,另一只杰尼龜被擊敗了。因此,訪問另一只杰尼龜?shù)腍P值并將其更改為0。下一步,檢查初始Squirtle,輸入console.log和...
等等,什么?初始Squirtle的HP降至0。這怎么可能?可憐的杰尼龜遭遇了什么?原來是發(fā)生了JavaScript變異。接下來將為你解釋其中緣由。
當(dāng)創(chuàng)建anotherSquirtle變量并將初始Squirtle指定為其值時(shí),實(shí)際是給初始Squirtle對(duì)象的內(nèi)存位置分配了一個(gè)引用。這是因?yàn)镴avaScript數(shù)組和對(duì)象是引用數(shù)據(jù)類型。與基本數(shù)據(jù)類型不同,引用數(shù)據(jù)類型指向存儲(chǔ)實(shí)際對(duì)象/數(shù)組的內(nèi)存地址。
為了便于理解,可以將引用數(shù)據(jù)類型想象為全局變量的指針。更改引用數(shù)據(jù)類型的值實(shí)際上是在更改全局變量的值。
這意味著當(dāng)將anotherSquirtle的HP值更改為0時(shí),實(shí)際是將存儲(chǔ)在內(nèi)存中的Squirtle對(duì)象的HP值更改為0。這就是為什么mySquirtle的HP值為0 - 因?yàn)閙ySquirtle是對(duì)存儲(chǔ)在內(nèi)存中的對(duì)象的引用,可以通過anotherSquirtle變量被改變。謝謝JavaScript。
如何解決這個(gè)問題?
為了避免變量的變異,需要在要復(fù)制數(shù)組/對(duì)象時(shí),創(chuàng)建數(shù)組/對(duì)象實(shí)例。如何實(shí)現(xiàn)這一操作?
使用延展操作符。
延展操作符如何運(yùn)作
從MDN文檔中可以查到:展開語法(spread syntax),可以在函數(shù)調(diào)用或數(shù)組構(gòu)造時(shí),將數(shù)組表達(dá)式或string等iterable在語法層面展開,還可以在構(gòu)造字面量對(duì)象時(shí),將對(duì)象表達(dá)式按鍵-值方式展開。
簡(jiǎn)而言之,延展操作符......延展iterable中的項(xiàng)(iterable指receiver中任何可循環(huán)的項(xiàng),如字符串,數(shù)組,集等)。(receiver用于接收展開值。)為便于理解,以下是數(shù)組的簡(jiǎn)單示例:
const numbers = [1, 2, 3]; console.log(...numbers); //Result: 1 2 3 const pokemon = ['Squirtle', 'Bulbasur', 'Charmander']; console.log(...pokemon); //Squirtle Bulbasur Charmander const pokedex = [ { name: 'Squirtle', type: 'Water' }, { name: 'Bulbasur', type: 'Plant' }, { name: 'Charmander', type: 'Fire' } ]; console.log(...pokedex); //{ name: 'Squirtle', type: 'Water' } { name: 'Bulbasur', type: 'Plant' } { name: 'Charmander', type: 'Fire' } import pandas as pd
數(shù)組中使用延展操作符的三個(gè)示例
如上所示,當(dāng)在數(shù)組上使用延展操作符時(shí),可以獲取數(shù)組中所含的每個(gè)單獨(dú)的項(xiàng)。在上述所有示例中,receiver都是一個(gè)函數(shù),即console.log函數(shù)。夠簡(jiǎn)單吧?
克隆數(shù)組/對(duì)象
現(xiàn)在已經(jīng)知道了延展操作符的工作原理,可以利用它復(fù)制數(shù)組和對(duì)象而不改變其值。怎么做呢?延展內(nèi)容然后使用數(shù)組[]或?qū)ο笪淖謠}來生成數(shù)組/對(duì)象實(shí)例。
仍然以上文的杰尼龜為例,通過克隆mySquirtle變量解決上文中的問題:
const mySquirtle = { name: 'Squirtle', type: 'Water', hp: 100 }; const anotherSquirtle = { ...mySquirtle }; anotherSquirtle.hp = 0; console.log(anotherSquirtle); //Result: { name: 'Squirtle', type: 'Water', hp: 0 } console.log(mySquirtle); //Result: { name: 'Squirtle', type: 'Water', hp: 100 }
使用延展操作符復(fù)制對(duì)象
通過使用解延展操作符解構(gòu)mySquirtle變量?jī)?nèi)容并使用對(duì)象字面量,創(chuàng)建了Squirtle對(duì)象的新實(shí)例。這樣,就防止變量突然變異。
使用相同的語法復(fù)制數(shù)組:
const pokemon = ['Squirtle', 'Bulbasur', 'Charmander']; const pokedex = [...pokemon]; pokedex.push('Cyndaquil'); console.log(pokemon); //[ 'Squirtle', 'Bulbasur', 'Charmander' ] console.log(pokedex); //[ 'Squirtle', 'Bulbasur', 'Charmander', 'Cyndaquil' ]
使用延展操作符復(fù)制數(shù)組
注意:延展操作符只執(zhí)行淺拷貝。這意味著若在數(shù)組/對(duì)象中存儲(chǔ)了引用數(shù)據(jù)類型,則在使用延展操作符進(jìn)行復(fù)制時(shí),嵌套數(shù)組/對(duì)象將包含對(duì)原始的引用,因此其數(shù)值將是可變的。
將類數(shù)組對(duì)象轉(zhuǎn)換為數(shù)組
類數(shù)組對(duì)象與數(shù)組非常相似。它們通常都有編號(hào)元素和長(zhǎng)度屬性。但是,兩者有一個(gè)至關(guān)重要的區(qū)別:類數(shù)組對(duì)象沒有任何數(shù)組函數(shù)。
類數(shù)組對(duì)象包含主要由DOM方法返回的HTML節(jié)點(diǎn)列表,和每個(gè)JS函數(shù)和少部分其他函數(shù)自動(dòng)生成的參數(shù)變量。
使用與克隆數(shù)組相同的語法,可以使用延展操作符將類數(shù)組結(jié)構(gòu)轉(zhuǎn)換為數(shù)組,這可以代替使用Array.from的方法。以下是將nodeList轉(zhuǎn)換為數(shù)組的示例:
const nodeList = document.getElementsByClassName("pokemon"); const array = [...nodeList]; console.log(nodeList); //Result: HTMLCollection [ div.pokemon, div.pokemon ] console.log(array); //Result: Array [ div.pokemon, div.pokemon ]
將nodelist轉(zhuǎn)換為數(shù)組
使用這種技術(shù),可以將任何類數(shù)組結(jié)構(gòu)轉(zhuǎn)換為數(shù)組,從而訪問所有數(shù)組函數(shù)。
延展操作符用作參數(shù)
某些函數(shù)接受可變數(shù)量的參數(shù)。其中一個(gè)典型列子就是Math集合中的函數(shù)。以Math.max()函數(shù)為例。它接受n個(gè)數(shù)字參數(shù),并返回最大的參數(shù)。假設(shè)需要將一個(gè)數(shù)字?jǐn)?shù)組傳遞給Math.max()函數(shù)。該怎么做呢?
可以這樣做:
const numbers = [1, 4, 5]; const max = Math.max(numbers[0], numbers[1], numbers[2]); console.log(max); //Result: 5
但是,這樣做無疑是自尋死路。若是有20個(gè)值怎么辦?1000個(gè)值呢?真的要通過索引訪問每個(gè)值嗎?當(dāng)然不是。我們可以通過使用延展操作符提取數(shù)組中每個(gè)單獨(dú)的值,如下所示:
const numbers = [1, 4, 5, 6, 9, 2, 3, 4, 5, 6]; const max = Math.max(...numbers); console.log(max); //Result: 9
大救星:延展操作符。
添加新元素
將項(xiàng)添加到數(shù)組
向數(shù)組添加新元素,首先需要延展數(shù)組的內(nèi)容并使用數(shù)字字面量[]創(chuàng)建數(shù)組實(shí)例,需要包含原始數(shù)組的內(nèi)容以及要添加的值:
const pokemon = ['Squirtle', 'Bulbasur']; const charmander = 'Charmander'; const cyndaquil = 'Cyndaquil'; const pokedex = [...pokemon, charmander, cyndaquil]; console.log(pokedex); //Result: [ 'Squirtle', 'Bulbasur', 'Charmander', 'Cyndaquil' ]
使用延展操作符將項(xiàng)添加到數(shù)組中
如你所見,可以任意添加新項(xiàng)。
向?qū)ο筇砑訉傩?/strong>
通過使用與數(shù)組相同的語法,可以在克隆對(duì)象時(shí)輕松添加新屬性。稍微轉(zhuǎn)變一下,就有一個(gè)不同的語法來向?qū)ο筇砑訉傩裕ㄒ部梢杂糜跀?shù)組):
const basicSquirtle = { name: 'Squirtle', type: 'Water' }; const fullSquirtle = { ...basicSquirtle, species: 'Tiny Turtle Pokemon', evolution: 'Wartortle' }; console.log(fullSquirtle); //Result: { name: 'Squirtle', type: 'Water', species: 'Tiny Turtle Pokemon', evolution: 'Wartortle' }
如你所見,可以在對(duì)象字面量中而不是在外部直接聲明和初始化新變量。
合并數(shù)組/對(duì)象
數(shù)組
如上述例子所示,可以通過延展數(shù)組并使用數(shù)組字面量來合并兩個(gè)數(shù)組。但是,這一部分要講的不是簡(jiǎn)單地添加新元素,而是添加另一個(gè)(延展)數(shù)組:
const pokemon = ['Squirtle', 'Bulbasur', 'Charmander']; const morePokemon = ['Totodile', 'Chikorita', 'Cyndaquil']; const pokedex = [...pokemon, ...morePokemon]; console.log(pokedex); //Result: [ 'Squirtle', 'Bulbasur', 'Charmander', 'Totodile', 'Chikorita', 'Cyndaquil' ]
使用延展操作符合并數(shù)組
這也適用于數(shù)組對(duì)象:
const pokemon = [ { name: 'Squirtle', type: 'Water' }, { name: 'Bulbasur', type: 'Plant' }];const morePokemon = [{ name: 'Charmander', type: 'Fire' }]; const pokedex = [...pokemon, ...morePokemon]; console.log(pokedex); //Result: [ { name: 'Squirtle', type: 'Water' }, { name: 'Bulbasur', type: 'Plant' }, { name: 'Charmander', type: 'Fire' } ]Merging two arrays of objects with the spread operator
對(duì)象
可以使用與之前相同的語法將兩個(gè)(或更多)對(duì)象合并到一個(gè)對(duì)象中(你可能已經(jīng)留意到,擴(kuò)展運(yùn)算符在數(shù)組和對(duì)象中的使用方式非常相似):
const baseSquirtle = { name: 'Squirtle', type: 'Water' }; const squirtleDetails = { species: 'Tiny Turtle Pokemon', evolution: 'Wartortle' }; const squirtle = { ...baseSquirtle, ...squirtleDetails }; console.log(squirtle); //Result: { name: 'Squirtle', type: 'Water', species: 'Tiny Turtle Pokemon', evolution: 'Wartortle' }
使用延展操作符合并對(duì)象
本教程說明了為什么應(yīng)該使用擴(kuò)展運(yùn)算符(重點(diǎn)強(qiáng)調(diào)不變性!),它是如何工作的以及幾個(gè)基本用法。
留言 點(diǎn)贊 關(guān)注
我們一起分享AI學(xué)習(xí)與發(fā)展的干貨
如需轉(zhuǎn)載,請(qǐng)后臺(tái)留言,遵守轉(zhuǎn)載規(guī)范
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。