Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
與智能手機(jī)剛發(fā)布時(shí)相比,現(xiàn)如今的手機(jī)已經(jīng)獲得長(zhǎng)足的發(fā)展,無論是功能、操作方式都大大豐富。但隨之而來的問題是面對(duì)時(shí)時(shí)更新的功能,如何才能有效讓用戶及時(shí)了解?因此為了更好地宣傳手機(jī)/系統(tǒng)的特色功能,給用戶提供一個(gè)了解手機(jī)和品牌的窗口,用戶手冊(cè)(玩機(jī)技巧、使用技巧等)APP才會(huì)被預(yù)裝在我們的新手機(jī)上。
在設(shè)計(jì)第一版用戶手冊(cè)討論實(shí)現(xiàn)方式時(shí),開發(fā)建議html套殼的方式,這種方式的優(yōu)勢(shì):只需要開發(fā)一個(gè)后臺(tái)管理系統(tǒng),即可對(duì)內(nèi)容進(jìn)行管理,并且可在不同版本上使用。而如果開發(fā)原生APP,就需要不同版本系統(tǒng)獨(dú)立維護(hù),同時(shí)更新需要發(fā)布新版本。這么看來確實(shí)是使用html套殼的方式更好。
但是后面開發(fā)出來以后發(fā)現(xiàn),html套殼實(shí)現(xiàn)的用戶手冊(cè)體驗(yàn)完全無法與原生APP相比。具體體現(xiàn)在:1、對(duì)網(wǎng)絡(luò)依賴強(qiáng),每次打開都需要重新加載整個(gè)頁(yè)面;2、和手機(jī)很難保持視覺和操作的統(tǒng)一,最明顯的就是在使用h5組件開發(fā)出來的toast很難和系統(tǒng)規(guī)范保持一致;3、無法與手機(jī)系統(tǒng)交互,競(jìng)品通過點(diǎn)擊按鈕可以輕松調(diào)起系統(tǒng)設(shè)置,但是h5很難實(shí)現(xiàn);綜上,webapp體驗(yàn)無法與原生相比。
由于APP本身的屬性,用戶手冊(cè)整體的調(diào)性可以更前衛(wèi)、概念,就好比車廠會(huì)把最新、最炫酷的技術(shù)都應(yīng)用在概念車上。因此用戶手冊(cè)首頁(yè)也跟著品牌調(diào)性走。例如華為的首頁(yè)更傳統(tǒng)、嚴(yán)謹(jǐn);VIVO傳達(dá)的是年輕、探索,因此風(fēng)格上更多彩、靈活;OPPO沒有獨(dú)立的應(yīng)用,使用技巧集成在OPPO社區(qū)中,因此這一模塊帶有較重的社交屬性,短視頻、圖文內(nèi)容等主流媒介輔助用戶了解手機(jī)新功能。
華為采用列表導(dǎo)航的入口方式,算是比較穩(wěn)妥、傳統(tǒng)的布局,既兼顧效率,又方便對(duì)比,是一種比較高效的布局;VIVO整體更加年輕,頂部使用的是通欄banner,搜索功能被弱化,同時(shí)采用雙列的宮格式入口方式,這樣雖然犧牲了閱讀的效率,但整體更加美觀、統(tǒng)一。另外,VIVO入口的文章計(jì)數(shù)方式使用了兩種標(biāo)準(zhǔn),一種是絕對(duì)數(shù)值,即內(nèi)含多少文章,一種是相對(duì)數(shù)值,即更新數(shù)量,但在樣式上兩種數(shù)值沒有區(qū)分。
功能介紹詳情頁(yè)可以大致分為五個(gè)區(qū)域,分別是標(biāo)題欄、圖像區(qū)、文字區(qū)、功能區(qū)以及頁(yè)面導(dǎo)航。各個(gè)競(jìng)品可實(shí)現(xiàn)的功能大同小異,不同點(diǎn)有:
競(jìng)品分析過程中我們發(fā)現(xiàn),三家競(jìng)品都使用了同樣的操作路徑,即首頁(yè)>詳情頁(yè)>折疊菜單,但為什么不是首頁(yè)>折疊菜單>詳情頁(yè)呢?我的思考是,從用戶角度出發(fā),兩種操作路徑背后是兩類目標(biāo)不同的用戶。路徑二更像一條查找路徑,適合帶有強(qiáng)烈目的性的用戶,路徑二則更符合閱讀的場(chǎng)景,沉浸感更強(qiáng)。拿市面上的小說APP或者漫畫APP舉例,在2G、3G網(wǎng)絡(luò)時(shí)代,打開一個(gè)頁(yè)面需要流量,前進(jìn)后退需要大量加載時(shí)間,看小說都是得從目錄中選擇章節(jié)才能看到內(nèi)容。但是如今網(wǎng)速和硬件都大幅提升,基本上所有的閱讀產(chǎn)品都是點(diǎn)擊馬上進(jìn)入到內(nèi)容中去了,因此以最快速度加載內(nèi)容并呈現(xiàn)到用戶眼前才是最優(yōu)解。
avaScript 是世界上最流行的編程語(yǔ)言之一。
我相信這是您第一個(gè)絕佳選擇的編程語(yǔ)言。
我們主要使用JavaScript來創(chuàng)建:
我們的網(wǎng)站:https://www.icoderoad.com
但 JavaScript 不限于這些東西,它還可以用于:
它基本上可以做任何事情。它非常流行,以至于出現(xiàn)的所有新事物都會(huì)在某個(gè)時(shí)候能集成某種 JavaScript。
JavaScript 是一種編程語(yǔ)言,它是:
如您所知,JavaScript 與 Java 無關(guān),這是一個(gè)糟糕的名稱選擇,但我們必須忍受它。
手冊(cè)摘要
歷史
JavaScript 創(chuàng)建于 1995 年,自其不起眼的開始以來已經(jīng)走過了很長(zhǎng)的路。
它是 Web 瀏覽器原生支持的第一種腳本語(yǔ)言,因此它獲得了優(yōu)于任何其他語(yǔ)言的競(jìng)爭(zhēng)優(yōu)勢(shì),今天它仍然是我們可以用來構(gòu)建 Web 應(yīng)用程序的唯一腳本語(yǔ)言。
也存在其他語(yǔ)言,但都必須編譯為 JavaScript - 或者最近編譯為 WebAssembly,但這是另一回事。
最初 JavaScript 還沒有今天那么強(qiáng)大,它主要用于花哨的動(dòng)畫和當(dāng)時(shí)被稱為動(dòng)態(tài) HTML奇跡。
隨著 Web 平臺(tái)(并且繼續(xù)要求)不斷增長(zhǎng)的需求,JavaScript也有責(zé)任發(fā)展,以適應(yīng)世界上使用最廣泛的生態(tài)系統(tǒng)之一的需求。
JavaScript 現(xiàn)在也在瀏覽器之外廣泛使用。Node.js 在過去幾年的興起開啟了后端開發(fā)的大門,曾經(jīng)是 Java、Ruby、Python、PHP 和更傳統(tǒng)的服務(wù)器端語(yǔ)言的領(lǐng)域。
JavaScript 現(xiàn)在也是支持?jǐn)?shù)據(jù)庫(kù)和更多應(yīng)用程序的語(yǔ)言,甚至可以開發(fā)嵌入式應(yīng)用程序、移動(dòng)應(yīng)用程序、電視應(yīng)用程序等等。最初是瀏覽器中的一種小語(yǔ)言,現(xiàn)在是世界上最流行的語(yǔ)言。
JavaScript
有時(shí)很難將 JavaScript 與使用它的環(huán)境的特性區(qū)分開來。
例如,console.log()您可以在許多代碼示例中找到的那行代碼不是 JavaScript。相反,它是瀏覽器中提供給我們的龐大 API 庫(kù)的一部分。
同樣,在服務(wù)器上,有時(shí)很難將 JavaScript 語(yǔ)言功能與 Node.js 提供的 API 分開。
React 或 Vue 是否提供特定功能?還是通常所說的“普通 JavaScript”?
在本手冊(cè)中,我將討論 JavaScript 這種語(yǔ)言。
不會(huì)因外部生態(tài)系統(tǒng)提供的事物而使您的學(xué)習(xí)過程復(fù)雜化。
JavaScript 語(yǔ)法簡(jiǎn)介
在這個(gè)簡(jiǎn)短的介紹中,我想告訴大家 5 個(gè)概念:
空白空間
JavaScript 不認(rèn)為空白是有意義的。至少在理論上,可以以您可能喜歡的任何方式添加空格和換行符。
在實(shí)踐中,您很可能會(huì)保持明確定義的樣式并遵守人們常用的樣式,并使用 linter 或Prettier等樣式工具強(qiáng)制執(zhí)行此操作。
例如,我總是為每個(gè)縮進(jìn)使用 2 個(gè)空格字符。
區(qū)分大小寫
JavaScript 區(qū)分大小寫。一個(gè)名為something的變量不同于Something.
其它標(biāo)識(shí)符也是如此。
字面量
我們將字面量定義為在源代碼中寫入的值,例如,數(shù)字、字符串、布爾值或更高級(jí)的構(gòu)造,如 Object 字面量 或 Array 字面量:
5
'Test'
true
['a', 'b']
{color: 'red', shape: 'Rectangle'}
標(biāo)識(shí)符
標(biāo)識(shí)符是可用于標(biāo)識(shí)變量、函數(shù)或?qū)ο蟮淖址蛄小K梢砸宰帜浮⒚涝?hào)$或下劃線開頭_,并且可以包含數(shù)字。使用 Unicode,字母可以是任何允許的字符,例如,表情符號(hào) ?。
Test
test
TEST
_test
Test1
$test
美元符號(hào)通常用于引用 DOM 元素。
有些名稱是為 JavaScript 內(nèi)部使用而保留的關(guān)鍵字,我們不能將它們用作標(biāo)識(shí)符。
注釋
注釋是任何編程語(yǔ)言中最重要的部分之一。它們很重要,因?yàn)樗鼈冏屛覀兛梢宰⑨尨a并添加重要信息,否則其他人(或我們自己)閱讀代碼時(shí)無法獲得這些信息。
在 JavaScript 中,我們可以使用//進(jìn)行注釋. JavaScript 解釋器不會(huì)將//之后的所有內(nèi)容視為代碼。
像這樣:
// a comment
true //another comment
另一種類型的注釋是多行注釋。它以 /*開頭和*/結(jié)尾。
兩者之間的所有內(nèi)容均被認(rèn)為注釋:
/* some kind
of
comment
*/
分號(hào)
JavaScript 程序中的每一行都可選地使用分號(hào)終止。
我說可選,因?yàn)?JavaScript 解釋器足夠聰明,可以為您引入分號(hào)。
在大多數(shù)情況下,您可以在程序中完全省略分號(hào),甚至無需考慮它。
這個(gè)事實(shí)是非常有爭(zhēng)議的。一些開發(fā)人員將始終使用分號(hào),而另一些開發(fā)人員則從不使用分號(hào),并且您總是會(huì)發(fā)現(xiàn)使用分號(hào)的代碼和不使用分號(hào)的代碼。
我個(gè)人的偏好是避免使用分號(hào),所以我在書中的示例不會(huì)包含它們。
值類型
字符串hello是一個(gè)值。像一個(gè)數(shù)字12是一個(gè)值。
hello和12是值。string 和 number是這些值的類型。
類型是值的種類,它的類別。JavaScript 中有許多不同的類型,稍后我們將詳細(xì)討論它們。每種類型都有自己的特點(diǎn)。
當(dāng)我們需要一個(gè)值的引用時(shí),我們將它分配給一個(gè)變量。變量可以有一個(gè)名稱,而值是存儲(chǔ)在變量中的內(nèi)容,因此我們稍后可以通過變量名稱訪問該值。
變量
變量是分配給標(biāo)識(shí)符的值,因此您可以稍后在程序中引用和使用它。
這是因?yàn)?JavaScript 是弱類型的,這是您經(jīng)常聽到的概念。
必須先聲明變量,然后才能使用它。
我們有兩種主要的方式來聲明變量。首先是使用const:
const a = 0
第二種方法是使用let:
let a = 0
有什么不同?
const定義對(duì)值的常量引用。這意味著不能更改引用。不能為其重新分配新值。
使用letp聲明的變量可以為其分配一個(gè)新值。
例如,不能這樣做:
const a = 0
a = 1
因?yàn)闀?huì)得到一個(gè)錯(cuò)誤:TypeError: Assignment to constant variable..
另一方面,可以使用letp聲明變量:
let a = 0
a = 1
const并不像 C 等其他語(yǔ)言那樣表示“常量”。特別是,這并不意味著該值不能改變 - 這意味著它不能被重新分配。如果變量指向一個(gè)對(duì)象或數(shù)組(我們稍后會(huì)看到更多關(guān)于對(duì)象和數(shù)組的內(nèi)容),那么對(duì)象或數(shù)組的內(nèi)容可以自由改變。
const變量必須在聲明時(shí)初始化:
const a = 0
但let值可以稍后初始化:
let a
a = 0
可以在同一語(yǔ)句中一次聲明多個(gè)變量:
const a = 1, b = 2
let c = 1, d = 2
但是不能多次重新聲明同一個(gè)變量:
let a = 1
let a = 2
否則會(huì)收到“重復(fù)聲明”錯(cuò)誤。
我的建議是始終使用const聲明產(chǎn)量,僅在您知道需要為該變量重新分配值時(shí)使用let。為什么?因?yàn)槲覀兊拇a的功能越少越好。如果我們知道一個(gè)值不能被重新分配,那么它就少了一個(gè)錯(cuò)誤來源。
既然我們已經(jīng)了解了如何使用const和 let,我想提一下var。
直到 2015 年,var這是我們?cè)?JavaScript 中聲明變量的唯一方法。今天,現(xiàn)代代碼庫(kù)很可能只使用const和 letp聲明變量。我在這篇文章中詳細(xì)介紹了一些基本差異,但如果你剛剛開始學(xué)習(xí)JavaScript ,可能不會(huì)關(guān)心它們。只需使用const和letp聲明變量即可。
類型
JavaScript 中的變量沒有附加任何類型。
它們是無類型的。
將具有某種類型的值分配給變量后,可以稍后重新分配該變量以承載任何其他類型的值,而不會(huì)出現(xiàn)任何問題。
在 JavaScript 中,我們有 2 種主要類型:原始類型和對(duì)象類型。
原始類型
原始類型是
還有兩種特殊類型:null和undefined。
對(duì)象類型
任何不是原始類型(字符串、數(shù)字、布爾值、null 或未定義)的值都是對(duì)象。
對(duì)象類型有屬性,也有可以作用于這些屬性的方法。
稍后我們將更多地討論對(duì)象。
表達(dá)式
表達(dá)式是 JavaScript 引擎可以評(píng)估并返回值的單個(gè) JavaScript 代碼單元。
表達(dá)式的復(fù)雜性可能會(huì)有所不同。
我們從非常簡(jiǎn)單的開始,稱為初級(jí)表達(dá)式:
2
0.02
'something'
true
false
this //the current scope
undefined
i //where i is a variable or a constant
算術(shù)表達(dá)式是接受一個(gè)變量和一個(gè)運(yùn)算符的表達(dá)式(稍后將詳細(xì)介紹運(yùn)算符),并產(chǎn)生一個(gè)數(shù)字:
1 / 2
i++
i -= 2
i * 2
字符串表達(dá)式是產(chǎn)生字符串的表達(dá)式:
'A ' + 'string'
邏輯表達(dá)式使用邏輯運(yùn)算符并解析為布爾值:
a && b
a || b
!a
更高級(jí)的表達(dá)式涉及對(duì)象、函數(shù)和數(shù)組,我稍后會(huì)介紹它們。
運(yùn)算符
運(yùn)算符允許獲得兩個(gè)簡(jiǎn)單的表達(dá)式并將它們組合成一個(gè)更復(fù)雜的表達(dá)式。
我們可以根據(jù)它們使用的操作數(shù)對(duì)運(yùn)算符進(jìn)行分類。一些運(yùn)算符使用 1 個(gè)操作數(shù)。大多數(shù)使用 2 個(gè)操作數(shù)。只有一個(gè)運(yùn)算符可以處理 3 個(gè)操作數(shù)。
在對(duì)運(yùn)算符的第一次介紹中,我們將介紹您最可能熟悉的運(yùn)算符:具有 2 個(gè)操作數(shù)的運(yùn)算符。
我在談?wù)撟兞繒r(shí)已經(jīng)介紹了一個(gè):賦值運(yùn)算符=。您用=為變量賦值:
let b = 2
現(xiàn)在讓我們介紹另一組在基礎(chǔ)數(shù)學(xué)中已經(jīng)熟悉的二元運(yùn)算符。
加法運(yùn)算符 (+)
const three = 1 + 2
const four = three + 1
如果使用字符串,+運(yùn)算符也會(huì)進(jìn)行字符串連接,因此請(qǐng)注意:
const three = 1 + 2
three + 1 // 4
'three' + 1 // three1
減法運(yùn)算符 (-)
const two = 4 - 2
除法運(yùn)算符 (/)
返回第一個(gè)運(yùn)算符和第二個(gè)運(yùn)算符的商:
const result = 20 / 5 //result === 4
const result = 20 / 7 //result === 2.857142857142857
如果除以零,JavaScript 不會(huì)引發(fā)任何錯(cuò)誤,但會(huì)返回該Infinity值(或者-Infinity如果該值為負(fù)數(shù))。
1 / 0 //Infinity
-1 / 0 //-Infinity
余數(shù)運(yùn)算符 (%)
在許多用例中,余數(shù)是非常有用的計(jì)算:
const result = 20 % 5 //result === 0
const result = 20 % 7 //result === 6
NaN余數(shù)總是為零,這是一個(gè)表示“非數(shù)字”的特殊值:
1 % 0 //NaN
-1 % 0 //NaN
乘法運(yùn)算符 (*)
將兩個(gè)數(shù)字相乘
1 * 2 //2
-1 * 2 //-2
冪運(yùn)算符 (**)
將第一個(gè)操作數(shù)提高到第二個(gè)操作數(shù)的冪
1 ** 2 //1
2 ** 1 //2
2 ** 2 //4
2 ** 8 //256
8 ** 2 //64
優(yōu)先規(guī)則
在同一行中包含多個(gè)運(yùn)算符的每個(gè)復(fù)雜語(yǔ)句都會(huì)引入優(yōu)先級(jí)問題。
舉個(gè)例子:
let a = 1 * 2 + 5 / 2 % 2
結(jié)果是 2.5,但為什么呢?
哪些操作先執(zhí)行,哪些需要等待?
某些操作比其他操作具有更高的優(yōu)先級(jí)。下表列出了優(yōu)先規(guī)則:
操作員 | 描述 |
同一級(jí)別的操作(如+和-)按照它們被發(fā)現(xiàn)的順序從左到右執(zhí)行。
按照這些規(guī)則,上面的操作可以這樣解決:
let a = 1 * 2 + 5 / 2 % 2
let a = 2 + 5 / 2 % 2
let a = 2 + 2.5 % 2
let a = 2 + 0.5
let a = 2.5
比較運(yùn)算符
在賦值和數(shù)學(xué)運(yùn)算符之后,我要介紹的第三組運(yùn)算符是條件運(yùn)算符。
可以使用以下運(yùn)算符來比較兩個(gè)數(shù)字或兩個(gè)字符串。
比較運(yùn)算符總是返回一個(gè)布爾值,即true或false)。
這些是不等式比較運(yùn)算符:
例子:
let a = 2
a >= 1 //true
除此之外,我們還有 4 個(gè)相等運(yùn)算符。它們接受兩個(gè)值,并返回一個(gè)布爾值:
請(qǐng)注意,我們?cè)?JavaScript 中也有==和 !=,但我強(qiáng)烈建議只使用===和!==,因?yàn)樗鼈兛梢苑乐挂恍┪⒚畹膯栴}。
條件語(yǔ)句
有了比較運(yùn)算符,我們就可以討論條件語(yǔ)句了。
if語(yǔ)句用于使程序根據(jù)表達(dá)式求值的結(jié)果選擇一條路徑或另一條路徑。
這是最簡(jiǎn)單的例子,它總是執(zhí)行:
if (true) {
//do something
}
相反,這將永遠(yuǎn)不會(huì)執(zhí)行:
if (false) {
//do something (? never ?)
}
條件檢查傳遞給它的表達(dá)式的真值或假值。如果傳遞一個(gè)數(shù)字,除非它是 0,否則它總是計(jì)算為真。如果傳遞一個(gè)字符串,它總是計(jì)算為真,除非它是一個(gè)空字符串。這些是將類型轉(zhuǎn)換為布爾值的一般規(guī)則。
注意到花括號(hào)了嗎?這稱為塊,它用于對(duì)不同語(yǔ)句的列表進(jìn)行分組。
塊可以放在任何可以有單個(gè)語(yǔ)句的地方。如果在條件句之后有一條語(yǔ)句要執(zhí)行,可以省略該塊,只寫語(yǔ)句:
if (true) doSomething()
但我總是喜歡用花括號(hào),這樣的語(yǔ)句更清楚。
else可以為if語(yǔ)句提供第二部分。
if如果條件為假,則附加將要執(zhí)行的語(yǔ)句:
if (true) {
//do something
} else {
//do something else
}
由于else接受一個(gè)語(yǔ)句,可以在其中嵌套另一個(gè) if/else 語(yǔ)句:
if (a === true) {
//do something
} else if (b === true) {
//do something else
} else {
//fallback
}
數(shù)組
數(shù)組是元素的集合。
JavaScript 中的數(shù)組本身并不是一種類型。
數(shù)組是對(duì)象。
我們可以通過以下兩種不同的方式初始化一個(gè)空數(shù)組:
const a = []
const a = Array()
第一種是使用數(shù)組文字語(yǔ)法。第二個(gè)使用 Array 內(nèi)置函數(shù)。
您可以使用以下語(yǔ)法預(yù)填充數(shù)組:
const a = [1, 2, 3]
const a = Array.of(1, 2, 3)
數(shù)組可以保存任何值,甚至是不同類型的值:
const a = [1, 'Flavio', ['a', 'b']]
由于我們可以將數(shù)組添加到數(shù)組中,因此我們可以創(chuàng)建多維數(shù)組,這些數(shù)組有非常有用的應(yīng)用(例如矩陣):
const matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
]
matrix[0][0] //1
matrix[2][0] //7
可以通過引用從零開始的索引來訪問數(shù)組的任何元素:
a[0] //1
a[1] //2
a[2] //3
可以使用以下語(yǔ)法使用一組值初始化一個(gè)新數(shù)組,該語(yǔ)法首先初始化一個(gè)由 12 個(gè)元素組成的數(shù)組,并用數(shù)字0填充每個(gè)元素:
Array(12).fill(0)
可以通過檢查其length屬性來獲取數(shù)組中元素的數(shù)量:
const a = [1, 2, 3]
a.length //3
請(qǐng)注意,可以設(shè)置數(shù)組的長(zhǎng)度。如果分配的數(shù)字大于陣列當(dāng)前容量,則不會(huì)發(fā)生任何事情。如果分配較小的數(shù)字,則在該位置切割數(shù)組:
const a = [1, 2, 3]
a //[ 1, 2, 3 ]
a.length = 2
a //[ 1, 2 ]
如何將項(xiàng)目添加到數(shù)組
我們可以使用push()方法在數(shù)組末尾添加一個(gè)元素:
a.push(4)
我們可以使用unshift()方法在數(shù)組的開頭添加一個(gè)元素:
a.unshift(0)
a.unshift(-2, -1)
如何從數(shù)組中刪除一個(gè)項(xiàng)目
我們可以使用pop()方法從數(shù)組末尾刪除一個(gè)項(xiàng)目:
a.pop()
我們可以使用shift()方法從數(shù)組的開頭刪除一個(gè)項(xiàng)目:
a.shift()
如何連接兩個(gè)或多個(gè)數(shù)組
可以使用concat()方法連接多個(gè)數(shù)組:
const a = [1, 2]
const b = [3, 4]
const c = a.concat(b) //[1,2,3,4]
a //[1,2]
b //[3,4]
還可以通過使用擴(kuò)展運(yùn)算符 ( ...):
const a = [1, 2]
const b = [3, 4]
const c = [...a, ...b]
c //[1,2,3,4]
如何在數(shù)組中查找特定項(xiàng)
可以使用數(shù)組的find()方法:
a.find((element, index, array) => {
//return true or false
})
返回第一個(gè)返回 true 的項(xiàng)目,如果未找到該元素則返回undefined。
一個(gè)常用的語(yǔ)法是:
a.find(x => x.id === my_id)
上面的行將返回?cái)?shù)組中id === my_id的第一個(gè)元素。
findIndex()與 find()類似,但返回第一個(gè)為true 的項(xiàng)目的索引,如果未找到,則返回undefined:
a.findIndex((element, index, array) => {
//return true or false
})
另一種方法是includes():
a.includes(value)
a如果包含則返回真value。
a.includes(value, i)
如果在 position 之后包含value,則返回 true 。
字符串
字符串是一個(gè)字符序列。
它也可以定義為字符串文字,用引號(hào)或雙引號(hào)括起來:
'A string'
"Another string"
我個(gè)人一直更喜歡單引號(hào),只在 HTML 中使用雙引號(hào)來定義屬性。
將字符串值分配給如下變量:
const name = 'Flavio'
length可以使用它的屬性來確定字符串的長(zhǎng)度:
'Flavio'.length //6
const name = 'Flavio'
name.length //6
''這是一個(gè)空字符串. 它的長(zhǎng)度屬性為 0:
''.length //0
可以使用+運(yùn)算符連接兩個(gè)字符串:
"A " + "string"
可以使用+運(yùn)算符來插入變量:
const name = 'Flavio'
"My name is " + name //My name is Flavio
定義字符串的另一種方法是使用在反引號(hào)內(nèi)定義的模板文字。它們對(duì)于使多行字符串更簡(jiǎn)單特別有用。使用單引號(hào)或雙引號(hào),您無法輕松定義多行字符串 - 您需要使用轉(zhuǎn)義字符。
使用反引號(hào)打開模板文字后,只需按 Enter 鍵即可創(chuàng)建一個(gè)新行,沒有特殊字符,并且按原樣呈現(xiàn):
const string = `Hey
this
string
is awesome!`
模板文字也很棒,因?yàn)樗鼈兲峁┝艘环N將變量和表達(dá)式插入字符串的簡(jiǎn)單方法。
您可以使用以下${...}語(yǔ)法來執(zhí)行此操作:
const var = 'test'
const string = `something ${var}`
//something test
在${}里面可以添加任何東西,甚至是表達(dá)式:
const string = `something ${1 + 2 + 3}`
const string2 = `something
${foo() ? 'x' : 'y'}`
循環(huán)
循環(huán)是 JavaScript 的主要控制結(jié)構(gòu)之一。
使用循環(huán),我們可以自動(dòng)化并重復(fù)一段代碼,無論我們希望它運(yùn)行多少次,甚至無限期地運(yùn)行。
JavaScript 提供了許多迭代循環(huán)的方法。
我想專注于3種方式:
while
while 循環(huán)是 JavaScript 提供給我們的最簡(jiǎn)單的循環(huán)結(jié)構(gòu)。
我們?cè)陉P(guān)鍵字之后添加一個(gè)條件while,并提供一個(gè)運(yùn)行塊,直到條件評(píng)估為true。
例子:
const list = ['a', 'b', 'c']
let i = 0
while (i < list.length) {
console.log(list[i]) //value
console.log(i) //index
i = i + 1
}
您可以使用關(guān)鍵字中斷while循環(huán),如下所示:break
while (true) {
if (somethingIsTrue) break
}
如果您決定在循環(huán)中間跳過當(dāng)前迭代,則可以使用以下命令跳轉(zhuǎn)到下一個(gè)迭代continue:
while (true) {
if (somethingIsTrue) continue
//do something else
}
非常類似于while,我們有do..while循環(huán)。它與 基本相同while,只是在執(zhí)行代碼塊之后評(píng)估條件。
這意味著塊總是至少執(zhí)行一次。
例子:
const list = ['a', 'b', 'c']
let i = 0
do {
console.log(list[i]) //value
console.log(i) //index
i = i + 1
} while (i < list.length)
for
JavaScript 中第二個(gè)非常重要的循環(huán)結(jié)構(gòu)是for 循環(huán)。
我們使用for關(guān)鍵字并傳遞一組 3 條指令:初始化、條件和增量部分。
例子:
const list = ['a', 'b', 'c']
for (let i = 0; i < list.length; i++) {
console.log(list[i]) //value
console.log(i) //index
}
就像while循環(huán)一樣,您可以使用 中斷for循環(huán),并且可以使用 快進(jìn)到循環(huán)break的下一次迭代。forcontinue
for...of
這個(gè)循環(huán)是相對(duì)較新的(2015 年引入),它是for循環(huán)的簡(jiǎn)化版本:
const list = ['a', 'b', 'c']
for (const value of list) {
console.log(value) //value
}
函數(shù)
在任何中等復(fù)雜的 JavaScript 程序中,一切都發(fā)生在函數(shù)內(nèi)部。
函數(shù)是 JavaScript 的核心,必不可少的部分。
什么是函數(shù)?
函數(shù)是一個(gè)自包含的代碼塊。
這是一個(gè)函數(shù)聲明:
function getData() {
// do something
}
一個(gè)函數(shù)可以通過調(diào)用它隨時(shí)運(yùn)行,如下所示:
getData()
一個(gè)函數(shù)可以有一個(gè)或多個(gè)參數(shù):
function getData() {
//do something
}
function getData(color) {
//do something
}
function getData(color, age) {
//do something
}
當(dāng)我們可以傳遞參數(shù)時(shí),我們調(diào)用傳遞參數(shù)的函數(shù):
function getData(color, age) {
//do something
}
getData('green', 24)
getData('black')
請(qǐng)注意,在第二次調(diào)用中,我將black字符串參數(shù)作為color參數(shù)傳遞,但沒有傳遞age. 在這種情況下,age函數(shù)內(nèi)部是undefined.
我們可以使用以下條件檢查值是否未定義:
function getData(color, age) {
//do something
if (typeof age !== 'undefined') {
//...
}
}
typeof是一個(gè)一元運(yùn)算符,它允許我們檢查變量的類型。
您也可以通過以下方式檢查:
function getData(color, age) {
//do something
if (age) {
//...
}
}
雖然如果ageis或空字符串null,條件也將為真。0
您可以為參數(shù)設(shè)置默認(rèn)值,以防它們未傳遞:
function getData(color = 'black', age = 25) {
//do something
}
您可以將任何值作為參數(shù)傳遞:數(shù)字、字符串、布爾值、數(shù)組、對(duì)象以及函數(shù)。
一個(gè)函數(shù)有一個(gè)返回值。默認(rèn)情況下,函數(shù)返回undefined,除非您添加return帶有值的關(guān)鍵字:
function getData() {
// do something
return 'hi!'
}
我們可以在調(diào)用函數(shù)時(shí)將此返回值分配給變量:
function getData() {
// do something
return 'hi!'
}
let result = getData()
result現(xiàn)在保存一個(gè)帶有hi!值的字符串。
您只能返回一個(gè)值。
要返回多個(gè)值,您可以返回一個(gè)對(duì)象或數(shù)組,如下所示:
function getData() {
return ['Flavio', 37]
}
let [name, age] = getData()
函數(shù)可以在其他函數(shù)中定義:
const getData = () => {
const dosomething = () => {}
dosomething()
return 'test'
}
嵌套函數(shù)不能從封閉函數(shù)的外部調(diào)用。
你也可以從一個(gè)函數(shù)中返回一個(gè)函數(shù)。
箭頭函數(shù)
箭頭函數(shù)是最近對(duì) JavaScript 的介紹。
它們經(jīng)常被用來代替我在前一章中描述的“常規(guī)”函數(shù)。您會(huì)發(fā)現(xiàn)這兩種形式隨處可見。
從視覺上看,它們?cè)试S您使用更短的語(yǔ)法編寫函數(shù),來自:
function getData() {
//...
}
到
() => {
//...
}
但是..注意我們這里沒有名字。
箭頭函數(shù)是匿名的。我們必須將它們分配給一個(gè)變量。
我們可以將常規(guī)函數(shù)分配給變量,如下所示:
let getData = function getData() {
//...
}
當(dāng)我們這樣做時(shí),我們可以從函數(shù)中刪除名稱:
let getData = function() {
//...
}
并使用變量名調(diào)用函數(shù):
let getData = function() {
//...
}
getData()
這與我們對(duì)箭頭函數(shù)所做的事情相同:
let getData = () => {
//...
}
getData()
如果函數(shù)體只包含一條語(yǔ)句,則可以省略括號(hào)并將所有內(nèi)容寫在一行上:
const getData = () => console.log('hi!')
參數(shù)在括號(hào)中傳遞:
const getData = (param1, param2) =>
console.log(param1, param2)
如果您有一個(gè)(并且只有一個(gè))參數(shù),則可以完全省略括號(hào):
const getData = param => console.log(param)
箭頭函數(shù)允許您有一個(gè)隱式返回 - 無需使用return關(guān)鍵字即可返回值。
它在函數(shù)體中有一行語(yǔ)句時(shí)起作用:
const getData = () => 'test'
getData() //'test'
與常規(guī)函數(shù)一樣,我們可以為參數(shù)設(shè)置默認(rèn)值,以防它們未傳遞:
const getData = (color = 'black',
age = 2) => {
//do something
}
和常規(guī)函數(shù)一樣,我們只能返回一個(gè)值。
箭頭函數(shù)還可以包含其他箭頭函數(shù),甚至是常規(guī)函數(shù)。
這兩種函數(shù)非常相似,所以你可能會(huì)問為什么要引入箭頭函數(shù)。與常規(guī)函數(shù)的最大區(qū)別在于它們用作對(duì)象方法時(shí)。這是我們將很快研究的事情。
對(duì)象
任何不是原始類型(字符串、數(shù)字、布爾值、符號(hào)、null 或未定義)的值都是對(duì)象。
下面是我們定義對(duì)象的方式:
const car = {
}
這是對(duì)象字面量語(yǔ)法,它是 JavaScript 中最好的東西之一。
您還可以使用以下new Object語(yǔ)法:
const car = new Object()
另一種語(yǔ)法是使用Object.create():
const car = Object.create()
new您還可以在帶有大寫字母的函數(shù)之前使用關(guān)鍵字初始化對(duì)象。此函數(shù)用作該對(duì)象的構(gòu)造函數(shù)。在那里,我們可以初始化我們作為參數(shù)接收的參數(shù),以設(shè)置對(duì)象的初始狀態(tài):
function Car(brand, model) {
this.brand = brand
this.model = model
}
我們使用以下方法初始化一個(gè)新對(duì)象:
const myCar = new Car('Ford', 'Fiesta')
myCar.brand //'Ford'
myCar.model //'Fiesta'
對(duì)象總是通過引用傳遞。
如果您為一個(gè)變量分配與另一個(gè)變量相同的值,如果它是像數(shù)字或字符串這樣的原始類型,則它們是按值傳遞的:
舉個(gè)例子:
let age = 36
let myAge = age
myAge = 37
age //36
const car = {
color: 'blue'
}
const anotherCar = car
anotherCar.color = 'yellow'
car.color //'yellow'
即使是數(shù)組或函數(shù),在底層也是對(duì)象,因此了解它們的工作原理非常重要。
對(duì)象屬性
對(duì)象具有屬性,這些屬性由與值關(guān)聯(lián)的標(biāo)簽組成。
屬性的值可以是任何類型,這意味著它可以是數(shù)組、函數(shù),甚至可以是對(duì)象,因?yàn)閷?duì)象可以嵌套其他對(duì)象。
這是我們?cè)谏弦徽驴吹降膶?duì)象字面量語(yǔ)法:
const car = {
}
我們可以color這樣定義一個(gè)屬性:
const car = {
color: 'blue'
}
在這里,我們有一個(gè)car對(duì)象,其屬性名為color,其值為blue。
標(biāo)簽可以是任何字符串,但要注意特殊字符 - 如果我想在屬性名稱中包含一個(gè)無效的字符作為變量名,我將不得不在它周圍使用引號(hào):
const car = {
color: 'blue',
'the color': 'blue'
}
無效的變量名字符包括空格、連字符和其他特殊字符。
如您所見,當(dāng)我們有多個(gè)屬性時(shí),我們用逗號(hào)分隔每個(gè)屬性。
我們可以使用 2 種不同的語(yǔ)法來檢索屬性的值。
第一個(gè)是點(diǎn)符號(hào):
car.color //'blue'
第二個(gè)(這是我們唯一可以用于名稱無效的屬性)是使用方括號(hào):
car['the color'] //'blue'
如果您訪問不存在的屬性,您將獲得以下undefined值:
car.brand //undefined
如前所述,對(duì)象可以具有嵌套對(duì)象作為屬性:
const car = {
brand: {
name: 'Ford'
},
color: 'blue'
}
在此示例中,您可以使用訪問品牌名稱
car.brand.name
或者
car['brand']['name']
您可以在定義對(duì)象時(shí)設(shè)置屬性的值。
但是您以后可以隨時(shí)更新它:
const car = {
color: 'blue'
}
car.color = 'yellow'
car['color'] = 'red'
您還可以向?qū)ο筇砑有聦傩裕?/span>
car.model = 'Fiesta'
car.model //'Fiesta'
給定對(duì)象
const car = {
color: 'blue',
brand: 'Ford'
}
您可以使用從該對(duì)象中刪除一個(gè)屬性
delete car.brand
對(duì)象方法
我在前一章中談到了函數(shù)。
可以將函數(shù)分配給函數(shù)屬性,在這種情況下,它們稱為方法。
在這個(gè)例子中,start屬性分配了一個(gè)函數(shù),我們可以使用我們用于屬性的點(diǎn)語(yǔ)法來調(diào)用它,括號(hào)在末尾:
const car = {
brand: 'Ford',
model: 'Fiesta',
start: function() {
console.log('Started')
}
}
car.start()
在使用function() {}語(yǔ)法定義的方法中,我們可以通過引用來訪問對(duì)象實(shí)例this。
在以下示例中,我們可以使用and訪問brand和model屬性值:this.brandthis.model
const car = {
brand: 'Ford',
model: 'Fiesta',
start: function() {
console.log(`Started
${this.brand} ${this.model}`)
}
}
car.start()
重要的是要注意常規(guī)函數(shù)和箭頭函數(shù)之間的這種區(qū)別——this如果我們使用箭頭函數(shù),我們就無法訪問:
const car = {
brand: 'Ford',
model: 'Fiesta',
start: () => {
console.log(`Started
${this.brand} ${this.model}`) //not going to work
}
}
car.start()
這是因?yàn)?/span>箭頭函數(shù)沒有綁定到對(duì)象。
這就是為什么經(jīng)常將常規(guī)函數(shù)用作對(duì)象方法的原因。
方法可以接受參數(shù),如常規(guī)函數(shù):
const car = {
brand: 'Ford',
model: 'Fiesta',
goTo: function(destination) {
console.log(`Going to ${destination}`)
}
}
car.goTo('Rome')
類
我們討論了對(duì)象,這是 JavaScript 中最有趣的部分之一。
在本章中,我們將通過介紹類來提升一個(gè)層次。
什么是類?它們是一種為多個(gè)對(duì)象定義通用模式的方法。
讓我們看一個(gè)人對(duì)象:
const person = {
name: 'Flavio'
}
我們可以創(chuàng)建一個(gè)名為Person(注意大寫P,使用類時(shí)的約定)的類,它有一個(gè)name屬性:
class Person {
name
}
現(xiàn)在從這個(gè)類中,我們像這樣初始化一個(gè)flavio對(duì)象:
const flavio = new Person()
flavio稱為 Person 類的實(shí)例。
我們可以設(shè)置name屬性的值:
flavio.name = 'Flavio'
我們可以使用
flavio.name
就像我們對(duì)對(duì)象屬性所做的那樣。
類可以保存屬性,例如name和方法。
方法是這樣定義的:
class Person {
hello() {
return 'Hello, I am Flavio'
}
}
我們可以在類的實(shí)例上調(diào)用方法:
class Person {
hello() {
return 'Hello, I am Flavio'
}
}
const flavio = new Person()
flavio.hello()
當(dāng)我們創(chuàng)建一個(gè)新的對(duì)象實(shí)例時(shí),我們可以使用一個(gè)特殊的方法 constructor()來初始化類屬性。
它是這樣工作的:
class Person {
constructor(name) {
this.name = name
}
hello() {
return 'Hello, I am ' + this.name + '.'
}
}
注意我們?nèi)绾问褂?/span>this來訪問對(duì)象實(shí)例。
現(xiàn)在我們可以從類中實(shí)例化一個(gè)新對(duì)象,傳入一個(gè)字符串,當(dāng)我們調(diào)用時(shí),hello我們會(huì)得到一條個(gè)性化的消息:
const flavio = new Person('flavio')
flavio.hello() //'Hello, I am flavio.'
初始化對(duì)象時(shí),將constructor使用傳遞的任何參數(shù)調(diào)用該方法。
通常方法是在對(duì)象實(shí)例上定義的,而不是在類上。
可以定義一個(gè) static 方法以允許它在類上執(zhí)行:
class Person {
static genericHello() {
return 'Hello'
}
}
Person.genericHello() //Hello
這有時(shí)非常有用。
繼承
一個(gè)類可以擴(kuò)展另一個(gè)類,使用該類初始化的對(duì)象繼承這兩個(gè)類的所有方法。
假設(shè)我們有一個(gè)類Person:
class Person {
hello() {
return 'Hello, I am a Person'
}
}
我們可以定義一個(gè)新類,Programmer擴(kuò)展Person:
class Programmer extends Person {
}
現(xiàn)在,如果我們用 class 實(shí)例化一個(gè)新對(duì)象Programmer,它就可以訪問該hello()方法:
const flavio = new Programmer()
flavio.hello() //'你好, 我是一個(gè)人。'
在子類中,可以通過調(diào)用 super() 來引用父類方法:
class Programmer extends Person {
hello() {
return super.hello() +
'我也是一名程序員。'
}
}
const flavio = new Programmer()
flavio.hello()
上面的程序打印你好,我是一個(gè)人。我也是一名程序員。
異步編程和回調(diào)
大多數(shù)時(shí)候,JavaScript 代碼是同步運(yùn)行的。
這意味著執(zhí)行一行代碼,然后執(zhí)行下一個(gè)代碼,以此類推。
一切都如您所愿,這是它在大多數(shù)編程語(yǔ)言中的工作方式。
但是,有時(shí)不能只等待一行代碼執(zhí)行。
不能只等待 2 秒鐘來加載一個(gè)大文件,然后完全停止程序。
不能只等待下載網(wǎng)絡(luò)資源后再做其他事情。
JavaScript 通過使用回調(diào)解決了這個(gè)問題。
如何使用回調(diào)的最簡(jiǎn)單示例之一是使用計(jì)時(shí)器。計(jì)時(shí)器不是 JavaScript 的一部分,但它們由瀏覽器和 Node.js 提供。讓我談?wù)勎覀儞碛械囊粋€(gè)計(jì)時(shí)器:setTimeout()函數(shù)。
該setTimeout()函數(shù)接受 2 個(gè)參數(shù):一個(gè)函數(shù)和一個(gè)數(shù)字。該數(shù)字是在函數(shù)運(yùn)行之前必須經(jīng)過的毫秒數(shù)。
例子:
setTimeout(() => {
// 2秒以后執(zhí)行
console.log('inside the function')
}, 2000)
包含該console.log('inside the function')行的函數(shù)將在 2 秒后執(zhí)行。
如果在函數(shù)之前添加一個(gè) console.log('before') 日志,函數(shù)之后添加一個(gè)console.log('after')日志:
console.log('before')
setTimeout(() => {
// runs after 2 seconds
console.log('inside the function')
}, 2000)
console.log('after')
將在控制臺(tái)中看到這種情況:
before
after
inside the function
回調(diào)函數(shù)是異步執(zhí)行的。
當(dāng)在瀏覽器中使用文件系統(tǒng)、網(wǎng)絡(luò)、事件或 DOM 時(shí),這是一種非常常見的模式。
我提到的所有東西都不是“核心”JavaScript,因此本手冊(cè)中沒有解釋它們,但會(huì)在https://flaviocopes.com上的其他手冊(cè)中找到很多示例。
以下是我們?nèi)绾卧诖a中實(shí)現(xiàn)回調(diào)。
我們定義一個(gè)接受callback參數(shù)的函數(shù),它是一個(gè)函數(shù)。
當(dāng)代碼準(zhǔn)備好調(diào)用回調(diào)時(shí),我們通過傳遞結(jié)果來調(diào)用它:
const doSomething = callback => {
//do things
//do things
const result = /* .. */
callback(result)
}
使用此函數(shù)的代碼將像這樣使用它:
doSomething(result => {
console.log(result)
})
Promise
Promise 是處理異步代碼的另一種方法。
正如我們?cè)谇耙徽轮锌吹降模ㄟ^回調(diào)我們將一個(gè)函數(shù)傳遞給另一個(gè)函數(shù)調(diào)用,該函數(shù)將在函數(shù)完成處理時(shí)調(diào)用。
像這樣:
doSomething(result => {
console.log(result)
})
當(dāng)doSomething()代碼結(jié)束時(shí),它調(diào)用作為參數(shù)接收的函數(shù):
const doSomething = callback => {
//do things
//do things
const result = /* .. */
callback(result)
}
這種方法的主要問題是,如果我們需要在其余代碼中使用這個(gè)函數(shù)的結(jié)果,我們所有的代碼都必須嵌套在回調(diào)中,如果我們必須進(jìn)行 2-3 次回調(diào),我們輸入的是通常定義“回調(diào)地獄”,將許多級(jí)別的函數(shù)縮進(jìn)到其他函數(shù)中:
doSomething(result => {
doSomethingElse(anotherResult => {
doSomethingElseAgain(yetAnotherResult => {
console.log(result)
})
})
})
Promise 是處理這個(gè)問題的一種方法。
而不是這樣做:
doSomething(result => {
console.log(result)
})
我們以這種方式調(diào)用基于 Promise 的函數(shù):
doSomething()
.then(result => {
console.log(result)
})
我們首先調(diào)用函數(shù),然后我們有一個(gè)在函數(shù)結(jié)束時(shí)調(diào)用的then()方法。
縮進(jìn)無關(guān)緊要,但為了清晰起見,通常會(huì)使用這種樣式。
使用以下catch()方法檢測(cè)錯(cuò)誤很常見:
doSomething()
.then(result => {
console.log(result)
})
.catch(error => {
console.log(error)
})
現(xiàn)在,為了能夠使用這種語(yǔ)法,doSomething()函數(shù)實(shí)現(xiàn)必須有點(diǎn)特殊。它必須使用 Promises API。
而不是將其聲明為普通函數(shù):
const doSomething = () => {
}
我們將它聲明為一個(gè) Promise 對(duì)象:
const doSomething = new Promise()
我們?cè)?Promise 構(gòu)造函數(shù)中傳遞一個(gè)函數(shù):
const doSomething = new Promise(() => {
})
該函數(shù)接收 2 個(gè)參數(shù)。第一個(gè)是我們調(diào)用來解析Promise 的函數(shù),第二個(gè)是我們調(diào)用來拒絕 Promise 的函數(shù)。
const doSomething = new Promise(
(resolve, reject) => {
})
解決一個(gè) Promise 意味著成功完成它(這導(dǎo)致then()在任何使用它的地方調(diào)用該方法)。
拒絕一個(gè) Promise 味著以一個(gè)錯(cuò)誤結(jié)束它(這導(dǎo)致catch()在任何使用它的地方調(diào)用該方法)。
就是這樣:
const doSomething = new Promise(
(resolve, reject) => {
//some code
const success = /* ... */
if (success) {
resolve('ok')
} else {
reject('this error occurred')
}
}
)
我們可以將參數(shù)傳遞給我們想要的任何類型的解析和拒絕函數(shù)。
異步和等待
異步函數(shù)是 Promise 的更高層次的抽象。
一個(gè)異步函數(shù)返回一個(gè) Promise,如下例所示:
const getData = () => {
return new Promise((resolve, reject) => {
setTimeout(() =>
resolve('some data'), 2000)
})
}
任何想要使用此函數(shù)的代碼都將在函數(shù)之前使用 await 關(guān)鍵字:
const data = await getData()
這樣做,Promise返回的任何數(shù)據(jù)都將被分配給data變量。
在我們的例子中,數(shù)據(jù)是“一些數(shù)據(jù)”字符串。
有一個(gè)特別的警告:每當(dāng)我們使用await關(guān)鍵字時(shí),我們必須在定義為 async 的函數(shù)中這樣做。
像這樣:
const doSomething = async () => {
const data = await getData()
console.log(data)
}
async/await 讓我們擁有更簡(jiǎn)潔的代碼和簡(jiǎn)單的思維模型來處理異步代碼。
正如在上面的示例中看到的,我們的代碼看起來非常簡(jiǎn)單。將其與使用Promise或回調(diào)函數(shù)的代碼進(jìn)行比較。
這是一個(gè)非常簡(jiǎn)單的例子,當(dāng)代碼復(fù)雜得多時(shí),主要的好處就會(huì)出現(xiàn)。
例如,以下是使用 Fetch API 獲取 JSON 資源并使用 Promise 解析它的方法:
const getFirstUserData = () => {
// get users list
return fetch('/users.json')
// parse JSON
.then(response => response.json())
// pick first user
.then(users => users[0])
// get user data
.then(user =>
fetch(`/users/${user.name}`))
// parse JSON
.then(userResponse => response.json())
}
getFirstUserData()
這是使用 await/async 提供的相同功能:
const getFirstUserData = async () => {
// get users list
const response = await fetch('/users.json')
// parse JSON
const users = await response.json()
// pick first user
const user = users[0]
// get user data
const userResponse =
await fetch(`/users/${user.name}`)
// parse JSON
const userData = await user.json()
return userData
}
getFirstUserData()
變量范圍
當(dāng)我介紹變量時(shí),我談到了使用const、let和var。
范圍是對(duì)程序的一部分可見的變量集。
在 JavaScript 中,我們有全局作用域、塊作用域和函數(shù)作用域。
如果變量是在函數(shù)或塊之外定義的,它會(huì)附加到全局對(duì)象并且它具有全局范圍,這意味著它可以在程序的每個(gè)部分中使用。
let 、const 和var聲明變量之間有一個(gè)非常重要的區(qū)別。
在函數(shù)內(nèi)部定義的變量var僅在該函數(shù)內(nèi)部可見,類似于函數(shù)的參數(shù)。
另一方面,定義為const或 let 的變量?jī)H在定義它的塊內(nèi)可見。
塊是組合成一對(duì)花括號(hào)的一組指令,就像我們可以在if語(yǔ)句、for循環(huán)或函數(shù)中找到的指令一樣。
重要的是要理解一個(gè)塊沒有為 定義一個(gè)新的范圍var,但它為let和 const 定義了一個(gè)新的范圍。
這具有非常實(shí)際的意義。
假設(shè)在函數(shù)的 if 條件內(nèi)定義了一個(gè) var 變量
function getData() {
if (true) {
var data = 'some data'
console.log(data)
}
}
如果調(diào)用此函數(shù),ome data打印到控制臺(tái)。
如果嘗試將 console.log(data) 移動(dòng)到if語(yǔ)句之后,它仍然有效:
function getData() {
if (true) {
var data = 'some data'
}
console.log(data)
}
但是如果切換var data到let data:
function getData() {
if (true) {
let data = 'some data'
}
console.log(data)
}
會(huì)得到一個(gè)錯(cuò)誤:ReferenceError: data is not defined。
這是因?yàn)?/span>var是函數(shù)作用域,這里發(fā)生了一種特殊的事情,稱為提升。簡(jiǎn)而言之,JavaScript 在運(yùn)行代碼之前將聲明var移動(dòng)到最近的函數(shù)的頂部。這或多或少是這個(gè)函數(shù)在 JS 內(nèi)部的樣子:
function getData() {
var data
if (true) {
data = 'some data'
}
console.log(data)
}
這就是為什么也可以console.log(data)在函數(shù)的頂部,甚至在它被聲明之前,會(huì)得到undefined該變量的值:
function getData() {
console.log(data)
if (true) {
var data = 'some data'
}
}
但是如果切換到let,會(huì)得到一個(gè)錯(cuò)誤ReferenceError: data is not defined,因?yàn)?let 聲明不會(huì)發(fā)生提升。
const和let 遵循相同的規(guī)則:它們是塊范圍的。
一開始可能會(huì)很棘手,但一旦你意識(shí)到這種差異,你就會(huì)明白為什么var現(xiàn)在被認(rèn)為是一種不好的做法——它們的活動(dòng)部件更少,而且它們的范圍僅限于塊,這也使它們非常好作為循環(huán)變量,因?yàn)樗鼈冊(cè)谘h(huán)結(jié)束后不再存在:
function doLoop() {
for (var i = 0; i < 10; i++) {
console.log(i)
}
console.log(i)
}
doLoop()
當(dāng)您退出循環(huán)時(shí),i將是一個(gè)值為 10 的有效變量。
如果切換到let,當(dāng)你嘗試切換到時(shí)console.log(i)會(huì)導(dǎo)致錯(cuò)誤ReferenceError: i is not defined。
結(jié)論
非常感謝您閱讀完本手冊(cè)。
我希望它能激發(fā)您更多地了解 JavaScript。
本文主要記錄常用的html標(biāo)簽使用說明,用起來的時(shí)候偶爾查查。
標(biāo)簽 | 英文全拼 | 作用 | 特點(diǎn) |
?<html></html>?? | html | 網(wǎng)頁(yè)的根標(biāo)簽 | 所有的標(biāo)簽都要寫在這一對(duì)根標(biāo)簽里面 |
??<head></head>?? | head | 網(wǎng)頁(yè)的頭標(biāo)簽 | 包括完檔的屬性和信息 |
??<body></body>?? | body | 網(wǎng)頁(yè)的主題 | 包含文檔的所有內(nèi)容 |
??<div></div>?? | division | 定義一個(gè)區(qū)域 | 瀏覽器通常會(huì)在??<div>??前后放置一個(gè)換行符 |
??<!-- 注釋 -->?? | - | 注釋 | 單標(biāo)簽 |
??<br>或<br/>?? | break | 換行 | 單標(biāo)簽,不會(huì)在其前后創(chuàng)建空白行 |
??<hr>或<hr/>?? | horizontal rule | 添加水平線 | 單標(biāo)簽 |
??<img src="">?? | image | 添加圖片 | 單標(biāo)簽 |
??<embed src="">?? | embed | 嵌入外部應(yīng)用 | 單標(biāo)簽 |
??<meta>?? | meta | 提供有關(guān)頁(yè)面的元信息 | 單標(biāo)簽,??<meta>???標(biāo)簽通常位于??<head>??區(qū)域內(nèi) |
??<link>?? | link | 定義文檔與外部資源的關(guān)系 | 單標(biāo)簽,??<link>???標(biāo)簽只能存在于??<head>??區(qū)域內(nèi),不過它可出現(xiàn)任何次數(shù)。 |
??<p></p>?? | paragraph | 定義段落 | 自動(dòng)在其前后創(chuàng)建空白行 |
??<h1> to <h6>?? | Header 1 to Header 6 | 定義標(biāo)題 | h1在一個(gè)頁(yè)面里只能出現(xiàn)一次 |
??<strong></strong>?? | strong | 文本加粗 | 加粗標(biāo)記該文本 |
??<b></b>?? | bold | 文本加粗 | 加粗顯示文本,不推薦使用 |
??<em></em>?? | emphasize | 文本傾斜 | 傾斜標(biāo)記文本 |
??<i></i>?? | italic | 文本傾斜 | 傾斜顯示文本,不推薦使用 |
??<del></del>?? | delete | 文本添加刪除線 | - |
??<s></s>?? | strike | 文本添加刪除線 | 不推薦使用 |
??<ins></ins>?? | insert | 文本添加下劃線 | - |
??<u></u>?? | underline | 文本添加下劃線 | 不推薦使用 |
??<a href="">填寫內(nèi)容</a>?? | anchor | 添加超鏈接 | 最好使用CSS來改變鏈接的樣式 |
??<ul></ul>?? | unordered list | 定義無序列表 | 通常與??<li>??標(biāo)簽一起使用 |
??<ol></ol>?? | ordered list | 定義有序列表 | 通常與??<li>??標(biāo)簽一起使用 |
??<li></li>?? | list item | 創(chuàng)建列表項(xiàng) | 可與各種列表定義標(biāo)簽一起使用 |
??<dl></dl>?? | definition list | 定義描述列表 | 通常與??<dt>???和??<dd>??一起使用 |
??<dt></dt>?? | definition term | 定義條目 | 定義描述列表的項(xiàng)目 |
??<dd></dd>?? | definition description | 定義描述 | 對(duì)描述列表中的項(xiàng)目進(jìn)行描述 |
??<table></table>?? | table | 定義HTML表格 | 盡可能通過樣式改變表格外觀 |
??<tr></tr>?? | table row | 定義表格的行 | 一個(gè)??<tr>???標(biāo)簽包含一個(gè)或多個(gè)??<th>???或??<td>??標(biāo)簽 |
??<th></th>?? | table headline | 定義表格每一列的標(biāo)題 | 該標(biāo)簽的文本通常呈現(xiàn)為粗體且居中 |
??<td></td>?? | table data | 定義表格中的單元格數(shù)據(jù) | 該標(biāo)簽的文本呈現(xiàn)為普通且左對(duì)齊 |
??<caption>表格標(biāo)題</caption>?? | caption | 定義整個(gè)表格的標(biāo)題 | ??<caption>???標(biāo)簽必須直接放在??<table>??標(biāo)簽后 |
??<input type="">?? | input | 定義輸入控件 | 輸入字段可通過多種方式改變,取決于type屬性 |
??select?? | select | 定義下拉列表 | ??<select>???中的??<option>??標(biāo)簽定義了列表中的可用選項(xiàng) |
??<option></option>?? | option | 定義下拉列表中的可用項(xiàng) | ??<option>??標(biāo)簽不可自由定義寬高 |
??<optgroup></optgroup>?? | options group | 定義選項(xiàng)組 | ??<optgroup>??標(biāo)簽用于把相關(guān)的選項(xiàng)組合在一起 |
??<textarea></textarea>?? | textarea | 定義多行的文本輸入控件 | 文本的默認(rèn)字體是等寬字體 |
??<form></form>?? | form | 定義表單 | ??<form>??可以包含多個(gè)元素 |
??<fieldset></fieldset>?? | field set | 定義圍繞表單中元素的邊框 | ??<legend>???為??<fieldset>??定義標(biāo)題 |
??<legend></legend>?? | legend | 為??<fieldset>??定義標(biāo)題 | ??<legend>??通過css設(shè)定樣式 |
??<progress></progress>?? | progress | 定義運(yùn)行中的任務(wù)進(jìn)度 | ??<progress>???是HTML5中的新標(biāo)簽,??<progress>??標(biāo)簽不適合用來表示度量衡 |
??<meter></meter>?? | meter | 度量衡 | ??<meter>???是HTML5的新標(biāo)簽,??<meter>??標(biāo)簽不適合用來表示進(jìn)度條 |
??<audio></audio>?? | audio | 添加音頻 | ??<audio>??標(biāo)簽是HTML5的新標(biāo)簽 |
??<video></video>?? | video | 添加視頻 | ??<video>??標(biāo)簽是HTML5的新標(biāo)簽 |
??<source>?? | source | 定義媒介資源 | ??<source>??標(biāo)簽是HTML5中的新標(biāo)簽 |
普通用法
錨點(diǎn)鏈接
錨點(diǎn)鏈接通過點(diǎn)擊超鏈接,自動(dòng)跳轉(zhuǎn)到我們?cè)O(shè)置錨點(diǎn)的位置,類似于word的目錄導(dǎo)航。建立錨點(diǎn)的元素必須要有id或name屬性,最好兩個(gè)都有。這里只跳轉(zhuǎn)本頁(yè)面元素,其他頁(yè)面跳轉(zhuǎn)自行搜索。
具體做法如下:
示例如下。為了顯示效果,通過使用lorem自動(dòng)生成隨機(jī)文本(具體使用方法搜索,一般直接輸入就行),lorem*50表示重復(fù)lorem15次。
<a href="#id2">a</a>
<p id="id1">
(lorem*15)
</p>
(lorem*15)
<p id="id2">
(lorem*15)
</p>
超鏈接全局設(shè)置
在頁(yè)面head中寫入代碼可以設(shè)置超鏈接的全局跳轉(zhuǎn)設(shè)置
<head>
<!-- 讓頁(yè)面所有的超鏈接新頁(yè)面打開 -->
<base target="_blank">
</head>
charset編碼
name
網(wǎng)頁(yè)自動(dòng)跳轉(zhuǎn)
無序列表
無序列表使用粗體圓點(diǎn)進(jìn)行標(biāo)記。簡(jiǎn)單示例如下。
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
...
</ul>
有序列表
有序列表使用數(shù)字進(jìn)行標(biāo)記,我們可以通過整數(shù)值start指定列表編號(hào)的起始值。簡(jiǎn)單示例如下。
<ol start="2">
<li>a</li>
<li>b</li>
<li>c</li>
...
</ol>
描述列表
通過描述列表自定義列表,列表項(xiàng)內(nèi)部可以使用段落、換行符、圖片、鏈接以及其他列表等等。簡(jiǎn)單示例如下。
<dl>
<dt>A</dt> <!-- 小標(biāo)題 -->
<dd>A1</dd> <!-- 解釋標(biāo)題 -->
<dd>A2</dd> <!-- 解釋標(biāo)題 -->
<dt>B</dt> <!-- 小標(biāo)題 -->
<dd>B1</dd> <!-- 解釋標(biāo)題 -->
<dd>B2</dd> <!-- 解釋標(biāo)題 -->
</dl>
基礎(chǔ)表格
簡(jiǎn)單示例如下。
<table width="300px" height="100px" border="2" cellspacing="5px" cellpadding="0">
<caption>表格標(biāo)題</caption> <!-- 定義表格標(biāo)題 -->
<tr>
<!-- 定義表格的行 -->
<td>A1</td> <!-- 定義表格該行第一列中的數(shù)據(jù) -->
<td>B1</td>
<td>C1</td>
</tr>
<tr>
<!-- 定義表格的行 -->
<th>A</th> <!-- 定義表格每一列的標(biāo)題 -->
<th>B</th>
<th>C</th>
</tr>
<tr>
<td>A2</td>
<td>B2</td>
<td>C2</td>
</tr>
</table>
單元格合并
簡(jiǎn)單示例如下。
<table border="2" cellspacing="1px" width="400px" height="100px">
<caption><strong>表格標(biāo)題</strong></caption> <!-- 定義表格標(biāo)題 -->
<tr height="100">
<!-- 定義表格的行 -->
<td colspan="2">A1</td> <!-- 定義該行可以橫跨兩列 -->
<td>B1</td>
</tr>
<tr height="100">
<td>A2</td>
<td>B2</td>
<td rowspan="2">C</td> <!-- 定義該行可以橫跨兩行 -->
</tr>
<tr height="100">
<td>A3</td>
<td>B3</td>
</tr>
</table>
對(duì)于??<input>??不同的type屬性值,輸入字段擁有很多種形式。輸入字段可以是文本字段、復(fù)選框、掩碼后的文本控件、單選按鈕、按鈕等等。
文本輸入框
簡(jiǎn)單示例如下。
<input type="text" name="username" maxlength="6" readonly="readonly" disabled="disabled" value="用戶名">
密碼輸入框
簡(jiǎn)單示例如下。
<input type="password" name="pwd" maxlength="6" readonly="readonly" disabled="disabled" value="密碼">
單選框
示例一,兩個(gè)單選框都可以被選中
<div>
<input type="radio" name="man" checked="checked">男
</div>
<div>
<input type="radio" name="woman">女
</div>
示例二,兩個(gè)單選框只能有一個(gè)被選中
<div>
<input type="radio" name="gender" checked="checked">男
</div>
<div>
<input type="radio" name="gender">女
</div>
下拉列表
??<select>??
??<optgroup>??
??<option>??
示例一,單選下拉列表
<select>
<option value="a">a</option>
<option value="b">b</option>
<option value="c" selected='selected'>c</option> <!-- 默認(rèn)選中 -->
</select>
示例二,帶組合的單選下拉列表
<select>
<optgroup label="A">
<option value="a1">a1</option>
<option value="a2" selected='selected'>a2</option>
</optgroup>
<optgroup label="B">
<option value="b1">b1</option>
<option value="b2">b2</option>
</optgroup>
</select>
示例三,帶組合的多選下拉列表
<select multiple=”multiple”>
<optgroup label="A">
<option value="a1">a1</option>
<option value="a2" selected='selected'>a2</option>
</optgroup>
<optgroup label="B">
<option value="b1" selected='selected'>b1</option>
<option value="b2">b2</option>
</optgroup>
</select>
多選框
簡(jiǎn)單示例如下。
<input type="checkbox" checked="checked">A
<input type="checkbox">B
文本框
簡(jiǎn)單示例如下。
<textarea cols="5" rows="2" placeholder="text"></textarea>
文本上傳控件
簡(jiǎn)單示例如下。
<input type="file" accept="image/gif, image/jpeg"/>
其他類型按鈕
<input type="submit">文件提交按鈕
<input type="button" value="">普通按鈕
<input type="image" src="">圖片按鈕
<input type="reset">重置按鈕
<input type="url">網(wǎng)址控件
<input type="date">日期控件
<input type="time">時(shí)間控件
<!--email提供了郵箱的完整驗(yàn)證,必須包含@和后綴,如果不滿足驗(yàn)證,會(huì)阻止表單提交-->
<input type="email">郵件控件
<input type="number" step="3">數(shù)字控件
<input type="range" step="100">滑塊控件
<input type="color">顏色控件
表單
示例一,普通表單
<form>
First name: <input type="text" name="fname"><br>
Last name: <input type="text" name="lname"><br>
<input type="submit" value="提交">
</form>
示例二,帶分組信息表單
<form>
<fieldset>
<legend>Personalia:</legend>
First name: <input type="text" name="fname"><br>
Last name: <input type="text" name="lname"><br>
<input type="submit" value="提交">
</fieldset>
First nameA: <input type="text" name="fname"><br>
Last nameB: <input type="text" name="lname"><br>
</form>
??<progress>???與??<meter>??主要區(qū)別和用法見??HTML5 progress和meter控件??
??<progress>??
簡(jiǎn)單示例如下。
<progress value="60" max="100"></progress>
??<meter>??
簡(jiǎn)單示例如下
<meter min="0" low="40" high="90" max="100" value="91"></meter>
<meter min="0" low="40" high="90" max="100" value="90"></meter>
??<audio>??
簡(jiǎn)單示例如下
<audio src="demo.mp3" controls autoplay></audio>
??<video>??
簡(jiǎn)單示例如下
<video src="demo.mp4" controls autoplay height="500px" poster="0.jpg"></video>
??<source>??
簡(jiǎn)單示例如下
<video controls>
<source src="demo.mp3" type="audio/mp3">
<source src="demo.mp4" type="video/mp4">
您的瀏覽器不支持video元素。
</video>
??HTML特殊字符編碼對(duì)照表??
*請(qǐng)認(rèn)真填寫需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。