NSI(Windows-1252)
ANSI 是 Windows 95 及其之前的 Windows 系統(tǒng)中默認(rèn)的字符集。
ANSI 也稱為 Windows-1252。
重要提示
ANSI 和 ISO-8859-1 非常相似,唯一的不同是在 32 個字符上。
在 ANSI 中,從 128 到 159 的字符用于一些有用的字符,比如歐元符號。
在 ISO-8859-1 中,這些字符映射為在 HTML 中不起作用的控制字符。
許多 Web 開發(fā)者聲明 ISO-8859-1,并使用這 32 個值,就像它們使用的是 Windows-1252。
由于這種常見的誤解,當(dāng) ISO-8859-1 被聲明時,瀏覽器將更改為 Windows-1252。這對以下文檔類型都適用:HTML4、HTML5 和 XHTML。
ANSI 和 ASCII
ANSI 的第一部分(實體編號 0-127)是原來的 ASCII 字符集。它包含數(shù)字、大小寫英文字母和一些特殊字符。
如需深入了解 ASCII,請查看完整的 ASCII 參考手冊。
ANSI 字符集
字符 | 編號 | 實體名稱 | 描述 |
---|---|---|---|
32 | 空格(space) | ||
! | 33 | 感嘆號(exclamation mark) | |
" | 34 | " | 引號(quotation mark) |
# | 35 | 數(shù)字符號(number sign) | |
$ | 36 | 美元符號(dollar sign) | |
% | 37 | 百分比符號(percent sign) | |
& | 38 | & | & 符號(ampersand) |
' | 39 | 撇號(apostrophe) | |
( | 40 | 左括號(left parenthesis) | |
) | 41 | 右括號(right parenthesis) | |
* | 42 | 星號(asterisk) | |
+ | 43 | 加號(plus sign) | |
, | 44 | 逗號(comma) | |
- | 45 | 連字符(hyphen-minus) | |
. | 46 | 句號(full stop) | |
/ | 47 | 斜線(solidus) | |
0 | 48 | 數(shù)字 0(digit zero) | |
1 | 49 | 數(shù)字 1(digit one) | |
2 | 50 | 數(shù)字 2(digit two) | |
3 | 51 | 數(shù)字 3(digit three) | |
4 | 52 | 數(shù)字 4(digit four) | |
5 | 53 | 數(shù)字 5(digit five) | |
6 | 54 | 數(shù)字 6(digit six) | |
7 | 55 | 數(shù)字 7(digit seven) | |
8 | 56 | 數(shù)字 8(digit eight) | |
9 | 57 | 數(shù)字 9(digit nine) | |
: | 58 | 冒號(colon) | |
; | 59 | 分號(semicolon) | |
< | 60 | < | 小于號(less-than sign) |
= | 61 | 等于號(equals sign) | |
> | 62 | > | 大于號(greater-than sign) |
? | 63 | 問號(question mark) | |
@ | 64 | @ 符號(commercial at) | |
A | 65 | 拉丁文大寫字母 A | |
B | 66 | 拉丁文大寫字母 B | |
C | 67 | 拉丁文大寫字母 C | |
D | 68 | 拉丁文大寫字母 D | |
E | 69 | 拉丁文大寫字母 E | |
F | 70 | 拉丁文大寫字母 F | |
G | 71 | 拉丁文大寫字母 G | |
H | 72 | 拉丁文大寫字母 H | |
I | 73 | 拉丁文大寫字母 I | |
J | 74 | 拉丁文大寫字母 J | |
K | 75 | 拉丁文大寫字母 K | |
L | 76 | 拉丁文大寫字母 L | |
M | 77 | 拉丁文大寫字母 M | |
N | 78 | 拉丁文大寫字母 N | |
O | 79 | 拉丁文大寫字母 O | |
P | 80 | 拉丁文大寫字母 P | |
Q | 81 | 拉丁文大寫字母 Q | |
R | 82 | 拉丁文大寫字母 R | |
S | 83 | 拉丁文大寫字母 S | |
T | 84 | 拉丁文大寫字母 T | |
U | 85 | 拉丁文大寫字母 U | |
V | 86 | 拉丁文大寫字母 V | |
W | 87 | 拉丁文大寫字母 W | |
X | 88 | 拉丁文大寫字母 X | |
Y | 89 | 拉丁文大寫字母 Y | |
Z | 90 | 拉丁文大寫字母 Z | |
[ | 91 | 左方括號(left square bracket) | |
\ | 92 | 反斜線(reverse solidus) | |
] | 93 | 右方括號(right square bracket) | |
^ | 94 | 插入符號(circumflex accent) | |
_ | 95 | 下劃線(low line) | |
` | 96 | 重音符(grave accent) | |
a | 97 | 拉丁文小寫字母 a | |
b | 98 | 拉丁文小寫字母 b | |
c | 99 | 拉丁文小寫字母 c | |
d | 100 | 拉丁文小寫字母 d | |
e | 101 | 拉丁文小寫字母 e | |
f | 102 | 拉丁文小寫字母 f | |
g | 103 | 拉丁文小寫字母 g | |
h | 104 | 拉丁文小寫字母 h | |
i | 105 | 拉丁文小寫字母 i | |
j | 106 | 拉丁文小寫字母 j | |
k | 107 | 拉丁文小寫字母 k | |
l | 108 | 拉丁文小寫字母 l | |
m | 109 | 拉丁文小寫字母 m | |
n | 110 | 拉丁文小寫字母 n | |
o | 111 | 拉丁文小寫字母 o | |
p | 112 | 拉丁文小寫字母 p | |
q | 113 | 拉丁文小寫字母 q | |
r | 114 | 拉丁文小寫字母 r | |
s | 115 | 拉丁文小寫字母 s | |
t | 116 | 拉丁文小寫字母 t | |
u | 117 | 拉丁文小寫字母 u | |
v | 118 | 拉丁文小寫字母 v | |
w | 119 | 拉丁文小寫字母 w | |
x | 120 | 拉丁文小寫字母 x | |
y | 121 | 拉丁文小寫字母 y | |
z | 122 | 拉丁文小寫字母 z | |
{ | 123 | 左花括號(left curly bracket) | |
| | 124 | 豎線(vertical line) | |
} | 125 | 右花括號(right curly bracket) | |
~ | 126 | 波浪線(tilde) | |
127 | 未使用(NOT USED) | ||
€ | 128 | € | 歐元符號(euro sign) |
129 | 未使用(NOT USED) | ||
? | 130 | ‚ | 下單引號(single low-9 quotation mark) |
? | 131 | ƒ | 帶鉤的拉丁文小寫字母 f |
? | 132 | „ | 下雙引號(double low-9 quotation mark) |
… | 133 | … | 水平省略號(horizontal ellipsis) |
? | 134 | † | 劍號(dagger) |
? | 135 | ‡ | 雙劍號(double dagger) |
? | 136 | ˆ | 修飾字母抑揚音(modifier letter circumflex accent) |
‰ | 137 | ‰ | 千分比符號(per mille sign) |
? | 138 | Š | 帶有 caron 的拉丁文大寫字母 S |
? | 139 | ‹ | 左單角引號(single left-pointing angle quotation mark) |
? | 140 | Œ | 拉丁文大寫連字 OE |
141 | 未使用(NOT USED) | ||
? | 142 | Ž | 帶有 caron 的拉丁文大寫字母 Z |
143 | 未使用(NOT USED) | ||
144 | 未使用(NOT USED) | ||
' | 145 | ‘ | 左單引號(left single quotation mark) |
' | 146 | ’ | 右單引號(right single quotation mark) |
" | 147 | “ | 左雙引號(left double quotation mark) |
" | 148 | ” | 右雙引號(right double quotation mark) |
? | 149 | • | 著重號(bullet) |
– | 150 | – | 短破折號/連字符(en dash) |
— | 151 | — | 長破折號(em dash) |
? | 152 | ˜ | 小波浪線(small tilde) |
? | 153 | ™ | 貿(mào)易標(biāo)記符號(trade mark sign) |
? | 154 | š | 帶有 caron 的拉丁文小寫字母 s |
? | 155 | › | 右單角引號(single right-pointing angle quotation mark) |
? | 156 | œ | 拉丁文小寫連字 oe |
157 | 未使用(NOT USED) | ||
? | 158 | ž | 帶有 caron 的拉丁文小寫字母 z |
? | 159 | Ÿ | 帶有分音符(diaeresis)的拉丁文大寫字母 Y |
160 | | 不換行空格(no-break space) | |
? | 161 | ¡ | 倒置感嘆號(inverted exclamation mark) |
¢ | 162 | ¢ | 美分符號(cent sign) |
£ | 163 | £ | 英鎊符號(pound sign) |
¤ | 164 | ¤ | 貨幣符號(currency sign) |
¥ | 165 | ¥ | 日元符號(yen sign) |
| | 166 | ¦ | 間斷的豎杠(broken bar) |
§ | 167 | § | 小節(jié)號(section sign) |
¨ | 168 | ¨ | 分音符號(diaeresis) |
? | 169 | © | 版權(quán)所有(copyright sign) |
a | 170 | ª | 陰性序數(shù)記號(feminine ordinal indicator) |
? | 171 | « | 左雙角引號(left-pointing double angle quotation mark) |
? | 172 | ¬ | 否定符號(not sign) |
173 | ­ | 軟連字符(soft hyphen) | |
? | 174 | ® | 注冊商標(biāo)(registered sign) |
ˉ | 175 | ¯ | 長音符號(macron) |
° | 176 | ° | 度符號(degree sign) |
± | 177 | ± | 加減號/正負(fù)號(plus-minus sign) |
2 | 178 | ² | 上標(biāo) 2(superscript two) |
3 | 179 | ³ | 上標(biāo) 3(superscript three) |
′ | 180 | ´ | 尖音符號(acute accent) |
μ | 181 | µ | 微米符號(micro sign) |
? | 182 | ¶ | 段落符號(pilcrow sign) |
· | 183 | · | 中間點(middle dot) |
? | 184 | ¸ | 變音符號(cedilla) |
1 | 185 | ¹ | 上標(biāo) 1(superscript one) |
o | 186 | º | 陽性序數(shù)記號(masculine ordinal indicator) |
? | 187 | » | 右雙角引號(right-pointing double angle quotation mark) |
? | 188 | ¼ | 1/4 分?jǐn)?shù)(vulgar fraction one quarter) |
? | 189 | ½ | 1/2 分?jǐn)?shù)(vulgar fraction one half) |
? | 190 | ¾ | 3/4 分?jǐn)?shù)(vulgar fraction three quarters) |
? | 191 | ¿ | 倒置問號(inverted question mark) |
à | 192 | À | 帶有重音符號(grave)的拉丁文大寫字母 A |
á | 193 | Á | 帶有尖音符號(acute)的拉丁文大寫字母 A |
? | 194 | Â | 帶有抑揚音符號(circumflex)的拉丁文大寫字母 A |
? | 195 | Ã | 帶有波浪線的拉丁文大寫字母 A |
? | 196 | Ä | 帶有分音符(diaeresis)的拉丁文大寫字母 A |
? | 197 | Å | 帶有上圓圈的拉丁文大寫字母 A |
? | 198 | Æ | 拉丁文大寫字母 AE |
? | 199 | Ç | 帶有變音符號(cedilla)的拉丁文大寫字母 C |
è | 200 | È | 帶有重音符號(grave)的拉丁文大寫字母 E |
é | 201 | É | 帶有尖音符號(acute)的拉丁文大寫字母 E |
ê | 202 | Ê | 帶有抑揚符號(circumflex)的拉丁文大寫字母 E |
? | 203 | Ë | 帶有分音符(diaeresis)的拉丁文大寫字母 E |
ì | 204 | Ì | 帶有重音符號(grave)的拉丁文大寫字母 I |
í | 205 | Í | 帶有尖音符號(acute)的拉丁文大寫字母 I |
? | 206 | Î | 帶有抑揚音符號(circumflex)的拉丁文大寫字母 I |
? | 207 | Ï | 帶有分音符(diaeresis)的拉丁文大寫字母 I |
D | 208 | Ð | 拉丁文大寫字母 Eth |
? | 209 | Ñ | 帶有波浪線的拉丁文大寫字母 N |
ò | 210 | Ò | 帶有重音符號(grave)的拉丁文大寫字母 O |
ó | 211 | Ó | 帶有尖音符號(acute)的拉丁文大寫字母 O |
? | 212 | Ô | 帶有抑揚音符號(circumflex)的拉丁文大寫字母 O |
? | 213 | Õ | 帶有波浪線的拉丁文大寫字母 O |
? | 214 | Ö | 帶有分音符(diaeresis)的拉丁文大寫字母 O |
× | 215 | × | 乘號(multiplication sign) |
? | 216 | Ø | 帶有刪除線的拉丁文大寫字母 O |
ù | 217 | Ù | 帶有重音符號(grave)的拉丁文大寫字母 U |
ú | 218 | Ú | 帶有尖音符號(acute)的拉丁文大寫字母 U |
? | 219 | Û | 帶有抑揚音符號(circumflex)的拉丁文大寫字母 U |
ü | 220 | Ü | 帶有分音符(diaeresis)的拉丁文大寫字母 U |
Y | 221 | Ý | 帶有尖音符號(acute)的拉丁文大寫字母 Y |
T | 222 | Þ | 拉丁文大寫字母 Thorn |
? | 223 | ß | 拉丁文小寫字母 sharp s |
à | 224 | à | 帶有重音符號(grave)的拉丁文小寫字母 a |
á | 225 | á | 帶有尖音符號(acute)的拉丁文小寫字母 a |
a | 226 | â | 帶有抑揚音符號(circumflex)的拉丁文小寫字母 a |
? | 227 | ã | 帶有波浪線的拉丁文小寫字母 a |
? | 228 | ä | 帶有分音符(diaeresis)的拉丁文小寫字母 a |
? | 229 | å | 帶有上圓圈的拉丁文小寫字母 a |
? | 230 | æ | 拉丁文小寫字母 ae |
? | 231 | ç | 帶有變音符號(cedilla)的拉丁文小寫字母 c |
è | 232 | è | 帶有重音符號(grave)的拉丁文小寫字母 e |
é | 233 | é | 帶有尖音符號(acute)的拉丁文小寫字母 e |
ê | 234 | ê | 帶有抑揚音符號(circumflex)的拉丁文小寫字母 e |
? | 235 | ë | 帶有分音符(diaeresis)的拉丁文小寫字母 e |
ì | 236 | ì | 帶有重音符號(grave)的拉丁文小寫字母 i |
í | 237 | í | 帶有尖音符號(acute)的拉丁文小寫字母 i |
? | 238 | î | 帶有抑揚音符號(circumflex)的拉丁文小寫字母 i |
? | 239 | ï | 帶有分音符(diaeresis)的拉丁文小寫字母 i |
e | 240 | ð | 拉丁文小寫字母 eth |
? | 241 | ñ | 帶有波浪線的拉丁文小寫字母 n |
ò | 242 | ò | 帶有重音符號(grave)的拉丁文小寫字母 o |
ó | 243 | ó | 帶有尖音符號(acute)的拉丁文小寫字母 o |
? | 244 | ô | 帶有抑揚音符號(circumflex)的拉丁文小寫字母 o |
? | 245 | õ | 帶有波浪線的拉丁文小寫字母 o |
? | 246 | ö | 帶有分音符(diaeresis)的拉丁文小寫字母 o |
÷ | 247 | ÷ | 除號(division sign) |
? | 248 | ø | 帶有刪除線的拉丁文小寫字母 o |
ù | 249 | ù | 帶有重音符號(grave)的拉丁文小寫字母 u |
ú | 250 | ú | 帶有尖音符號(acute)的拉丁文小寫字母 u |
? | 251 | û | 帶有抑揚音符號(circumflex)的拉丁文小寫字母 u |
ü | 252 | ü | 帶有分音符(diaeresis)的拉丁文小寫字母 u |
y | 253 | ý | 帶有尖音符號(acute)的拉丁文小寫字母 y |
t | 254 | þ | 拉丁文小寫字母 thorn |
? | 255 | ÿ | 帶有分音符(diaeresis)的拉丁文小寫字母 y |
ANSI 控制字符
ANSI 控制字符(00-31,加上 127)最初被設(shè)計用來控制諸如打印機和磁帶驅(qū)動器之類的硬件設(shè)備。
控制字符(除了水平制表符、換行、回車之外)在 HTML 文檔中不起任何作用。
字符 | 編號 | 描述 |
---|---|---|
NUL | 00 | 空字符(null character) |
SOH | 01 | 標(biāo)題開始(start of header) |
STX | 02 | 正文開始(start of text) |
ETX | 03 | 正文結(jié)束(end of text) |
EOT | 04 | 傳輸結(jié)束(end of transmission) |
ENQ | 05 | 請求(enquiry) |
ACK | 06 | 收到通知/響應(yīng)(acknowledge) |
BEL | 07 | 響鈴(bell) |
BS | 08 | 退格(backspace) |
HT | 09 | 水平制表符(horizontal tab) |
LF | 10 | 換行(line feed) |
VT | 11 | 垂直制表符(vertical tab) |
FF | 12 | 換頁(form feed) |
CR | 13 | 回車(carriage return) |
SO | 14 | 不用切換(shift out) |
SI | 15 | 啟用切換(shift in) |
DLE | 16 | 數(shù)據(jù)鏈路轉(zhuǎn)義(data link escape) |
DC1 | 17 | 設(shè)備控制 1(device control 1) |
DC2 | 18 | 設(shè)備控制 2(device control 2) |
DC3 | 19 | 設(shè)備控制 3(device control 3) |
DC4 | 20 | 設(shè)備控制 4(device control 4) |
NAK | 21 | 拒絕接收/無響應(yīng)(negative acknowledge) |
SYN | 22 | 同步空閑(synchronize) |
ETB | 23 | 傳輸塊結(jié)束(end transmission block) |
CAN | 24 | 取消(cancel) |
EM | 25 | 已到介質(zhì)末端/介質(zhì)存儲已滿(end of medium) |
SUB | 26 | 替補/替換(substitute) |
ESC | 27 | 溢出/逃離/取消(escape) |
FS | 28 | 文件分隔符(file separator) |
GS | 29 | 組分隔符(group separator) |
RS | 30 | 記錄分隔符(record separator) |
US | 31 | 單元分隔符(unit separator) |
DEL | 127 | 刪除(delete) |
如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!
得小時候剛學(xué)電腦時還是使用MS-DOS作業(yè)系統(tǒng),家人幫我買了一本厚重的參考書,里頭收錄所有DOS指令,非常詳盡,而這本書也對我產(chǎn)生不小影響,我知道學(xué)習(xí)任何東西都必須要有正確的參考手冊,才能夠讓學(xué)習(xí)過程更全面扎實。雖然網(wǎng)路上有許多教學(xué)文件,但礙于篇幅都只能夠以最短捷徑來幫你達到目的,對于一些較為復(fù)雜的內(nèi)容來說,這些快速教學(xué)并不能讓你「真正」學(xué)會,因此最好還是準(zhǔn)備參考手冊。
本文要推薦的「HTML Reference」網(wǎng)站很不一樣,這個線上參考手冊收錄完整HTML語法教學(xué),依照英文字母順序排列,使用者可以很在這里檢索某個HTML標(biāo)簽詳細(xì)使用方法,很多可能不在我們平常會經(jīng)常使用的范圍(例如一些語法設(shè)定方式),但如果你想知道語法要怎么寫才正確,或者想從基礎(chǔ)開始學(xué)習(xí)HTML程式碼,請記得將這網(wǎng)站加入書簽。
我記得早先在學(xué)習(xí)制作HTML網(wǎng)頁時也有「首頁制作百寶箱」可以參考,HTML Reference大概就是比較進階、內(nèi)容較新較全面的首頁百寶箱吧!不僅如此,網(wǎng)站還提供實際范例供使用者參考,也能一鍵點擊快速復(fù)制語法,對學(xué)習(xí)來說絕對大有幫助。雖然HTML語法不是每個人都會碰到,但書到用時方恨少,假如你的工作與它相關(guān),不妨找時間惡補一下。
網(wǎng)站名稱:HTML Reference
網(wǎng)站鏈結(jié):http://htmlreference.io/
使用教學(xué)
第一步
HTMLReference.io網(wǎng)站分成幾個部分,最上方Collections收錄一些主題,包括常用的基本元素、表單、列表、HTML5語意標(biāo)簽(Semantic)和表格,中間有個搜尋功能可快速查詢你要找的語法,最重要的就是底下依照英文開頭排序的所有HTML語法,點擊可開啟詳細(xì)介紹。
第二步
Collection 會依照語法類別個別匯整,例如說到表單就會用到form、input、textarea、button 這些標(biāo)簽語法,相信大家不陌生,但你可能不知道每個語法有這么多種數(shù)值可以設(shè)定,這個網(wǎng)站最好的地方就在于它會把所有可以使用的設(shè)定參數(shù)列出來,并提供你實際使用范例和說明。
如果你已經(jīng)開始使用HTML5,對于一些語意標(biāo)簽應(yīng)該不陌生,HTML Reference 也將這些標(biāo)簽說明及范例列在 Semantic Collection。
第三步
回到HTML Reference 首頁,前面有提到首頁列出所有HTML 語法標(biāo)簽,依照字母排列,當(dāng)然使用者也能透過搜尋功能來快速查找,例如下圖是a 也就是超鏈結(jié)語法的使用教學(xué),可以看到目標(biāo)鏈結(jié)(href)參數(shù)是必須,網(wǎng)站還列出幾種不同的寫法和用法。
比較可惜的是網(wǎng)站目前只有提供英文版,可能要有一些基礎(chǔ)的英文能力才能比較容易理解,但按照網(wǎng)站編排方式,就算沒有看說明應(yīng)該也能從范例略知一二。
第四步
HTML Reference網(wǎng)站提供的范例、語法都能快速一鍵復(fù)制,只要把滑鼠游標(biāo)移動上去,點選后就能自動復(fù)制,非常方便!記得以前在學(xué)習(xí)寫網(wǎng)頁時都要去手動復(fù)制參考資料上的范例或語法教學(xué),不但很浪費時間,還必須注意有沒有弄錯段落,在這里就不會遇到相同問題。
avaScript 是世界上最流行的編程語言之一。
我相信這是您第一個絕佳選擇的編程語言。
我們主要使用JavaScript來創(chuàng)建:
我們的網(wǎng)站:https://www.icoderoad.com
但 JavaScript 不限于這些東西,它還可以用于:
它基本上可以做任何事情。它非常流行,以至于出現(xiàn)的所有新事物都會在某個時候能集成某種 JavaScript。
JavaScript 是一種編程語言,它是:
如您所知,JavaScript 與 Java 無關(guān),這是一個糟糕的名稱選擇,但我們必須忍受它。
手冊摘要
歷史
JavaScript 創(chuàng)建于 1995 年,自其不起眼的開始以來已經(jīng)走過了很長的路。
它是 Web 瀏覽器原生支持的第一種腳本語言,因此它獲得了優(yōu)于任何其他語言的競爭優(yōu)勢,今天它仍然是我們可以用來構(gòu)建 Web 應(yīng)用程序的唯一腳本語言。
也存在其他語言,但都必須編譯為 JavaScript - 或者最近編譯為 WebAssembly,但這是另一回事。
最初 JavaScript 還沒有今天那么強大,它主要用于花哨的動畫和當(dāng)時被稱為動態(tài) HTML奇跡。
隨著 Web 平臺(并且繼續(xù)要求)不斷增長的需求,JavaScript也有責(zé)任發(fā)展,以適應(yīng)世界上使用最廣泛的生態(tài)系統(tǒng)之一的需求。
JavaScript 現(xiàn)在也在瀏覽器之外廣泛使用。Node.js 在過去幾年的興起開啟了后端開發(fā)的大門,曾經(jīng)是 Java、Ruby、Python、PHP 和更傳統(tǒng)的服務(wù)器端語言的領(lǐng)域。
JavaScript 現(xiàn)在也是支持?jǐn)?shù)據(jù)庫和更多應(yīng)用程序的語言,甚至可以開發(fā)嵌入式應(yīng)用程序、移動應(yīng)用程序、電視應(yīng)用程序等等。最初是瀏覽器中的一種小語言,現(xiàn)在是世界上最流行的語言。
JavaScript
有時很難將 JavaScript 與使用它的環(huán)境的特性區(qū)分開來。
例如,console.log()您可以在許多代碼示例中找到的那行代碼不是 JavaScript。相反,它是瀏覽器中提供給我們的龐大 API 庫的一部分。
同樣,在服務(wù)器上,有時很難將 JavaScript 語言功能與 Node.js 提供的 API 分開。
React 或 Vue 是否提供特定功能?還是通常所說的“普通 JavaScript”?
在本手冊中,我將討論 JavaScript 這種語言。
不會因外部生態(tài)系統(tǒng)提供的事物而使您的學(xué)習(xí)過程復(fù)雜化。
JavaScript 語法簡介
在這個簡短的介紹中,我想告訴大家 5 個概念:
空白空間
JavaScript 不認(rèn)為空白是有意義的。至少在理論上,可以以您可能喜歡的任何方式添加空格和換行符。
在實踐中,您很可能會保持明確定義的樣式并遵守人們常用的樣式,并使用 linter 或Prettier等樣式工具強制執(zhí)行此操作。
例如,我總是為每個縮進使用 2 個空格字符。
區(qū)分大小寫
JavaScript 區(qū)分大小寫。一個名為something的變量不同于Something.
其它標(biāo)識符也是如此。
字面量
我們將字面量定義為在源代碼中寫入的值,例如,數(shù)字、字符串、布爾值或更高級的構(gòu)造,如 Object 字面量 或 Array 字面量:
5
'Test'
true
['a', 'b']
{color: 'red', shape: 'Rectangle'}
標(biāo)識符
標(biāo)識符是可用于標(biāo)識變量、函數(shù)或?qū)ο蟮淖址蛄小K梢砸宰帜浮⒚涝?/span>$或下劃線開頭_,并且可以包含數(shù)字。使用 Unicode,字母可以是任何允許的字符,例如,表情符號 ?。
Test
test
TEST
_test
Test1
$test
美元符號通常用于引用 DOM 元素。
有些名稱是為 JavaScript 內(nèi)部使用而保留的關(guān)鍵字,我們不能將它們用作標(biāo)識符。
注釋
注釋是任何編程語言中最重要的部分之一。它們很重要,因為它們讓我們可以注釋代碼并添加重要信息,否則其他人(或我們自己)閱讀代碼時無法獲得這些信息。
在 JavaScript 中,我們可以使用//進行注釋. JavaScript 解釋器不會將//之后的所有內(nèi)容視為代碼。
像這樣:
// a comment
true //another comment
另一種類型的注釋是多行注釋。它以 /*開頭和*/結(jié)尾。
兩者之間的所有內(nèi)容均被認(rèn)為注釋:
/* some kind
of
comment
*/
分號
JavaScript 程序中的每一行都可選地使用分號終止。
我說可選,因為 JavaScript 解釋器足夠聰明,可以為您引入分號。
在大多數(shù)情況下,您可以在程序中完全省略分號,甚至無需考慮它。
這個事實是非常有爭議的。一些開發(fā)人員將始終使用分號,而另一些開發(fā)人員則從不使用分號,并且您總是會發(fā)現(xiàn)使用分號的代碼和不使用分號的代碼。
我個人的偏好是避免使用分號,所以我在書中的示例不會包含它們。
值類型
字符串hello是一個值。像一個數(shù)字12是一個值。
hello和12是值。string 和 number是這些值的類型。
類型是值的種類,它的類別。JavaScript 中有許多不同的類型,稍后我們將詳細(xì)討論它們。每種類型都有自己的特點。
當(dāng)我們需要一個值的引用時,我們將它分配給一個變量。變量可以有一個名稱,而值是存儲在變量中的內(nèi)容,因此我們稍后可以通過變量名稱訪問該值。
變量
變量是分配給標(biāo)識符的值,因此您可以稍后在程序中引用和使用它。
這是因為 JavaScript 是弱類型的,這是您經(jīng)常聽到的概念。
必須先聲明變量,然后才能使用它。
我們有兩種主要的方式來聲明變量。首先是使用const:
const a = 0
第二種方法是使用let:
let a = 0
有什么不同?
const定義對值的常量引用。這意味著不能更改引用。不能為其重新分配新值。
使用letp聲明的變量可以為其分配一個新值。
例如,不能這樣做:
const a = 0
a = 1
因為會得到一個錯誤:TypeError: Assignment to constant variable..
另一方面,可以使用letp聲明變量:
let a = 0
a = 1
const并不像 C 等其他語言那樣表示“常量”。特別是,這并不意味著該值不能改變 - 這意味著它不能被重新分配。如果變量指向一個對象或數(shù)組(我們稍后會看到更多關(guān)于對象和數(shù)組的內(nèi)容),那么對象或數(shù)組的內(nèi)容可以自由改變。
const變量必須在聲明時初始化:
const a = 0
但let值可以稍后初始化:
let a
a = 0
可以在同一語句中一次聲明多個變量:
const a = 1, b = 2
let c = 1, d = 2
但是不能多次重新聲明同一個變量:
let a = 1
let a = 2
否則會收到“重復(fù)聲明”錯誤。
我的建議是始終使用const聲明產(chǎn)量,僅在您知道需要為該變量重新分配值時使用let。為什么?因為我們的代碼的功能越少越好。如果我們知道一個值不能被重新分配,那么它就少了一個錯誤來源。
既然我們已經(jīng)了解了如何使用const和 let,我想提一下var。
直到 2015 年,var這是我們在 JavaScript 中聲明變量的唯一方法。今天,現(xiàn)代代碼庫很可能只使用const和 letp聲明變量。我在這篇文章中詳細(xì)介紹了一些基本差異,但如果你剛剛開始學(xué)習(xí)JavaScript ,可能不會關(guān)心它們。只需使用const和letp聲明變量即可。
類型
JavaScript 中的變量沒有附加任何類型。
它們是無類型的。
將具有某種類型的值分配給變量后,可以稍后重新分配該變量以承載任何其他類型的值,而不會出現(xiàn)任何問題。
在 JavaScript 中,我們有 2 種主要類型:原始類型和對象類型。
原始類型
原始類型是
還有兩種特殊類型:null和undefined。
對象類型
任何不是原始類型(字符串、數(shù)字、布爾值、null 或未定義)的值都是對象。
對象類型有屬性,也有可以作用于這些屬性的方法。
稍后我們將更多地討論對象。
表達式
表達式是 JavaScript 引擎可以評估并返回值的單個 JavaScript 代碼單元。
表達式的復(fù)雜性可能會有所不同。
我們從非常簡單的開始,稱為初級表達式:
2
0.02
'something'
true
false
this //the current scope
undefined
i //where i is a variable or a constant
算術(shù)表達式是接受一個變量和一個運算符的表達式(稍后將詳細(xì)介紹運算符),并產(chǎn)生一個數(shù)字:
1 / 2
i++
i -= 2
i * 2
字符串表達式是產(chǎn)生字符串的表達式:
'A ' + 'string'
邏輯表達式使用邏輯運算符并解析為布爾值:
a && b
a || b
!a
更高級的表達式涉及對象、函數(shù)和數(shù)組,我稍后會介紹它們。
運算符
運算符允許獲得兩個簡單的表達式并將它們組合成一個更復(fù)雜的表達式。
我們可以根據(jù)它們使用的操作數(shù)對運算符進行分類。一些運算符使用 1 個操作數(shù)。大多數(shù)使用 2 個操作數(shù)。只有一個運算符可以處理 3 個操作數(shù)。
在對運算符的第一次介紹中,我們將介紹您最可能熟悉的運算符:具有 2 個操作數(shù)的運算符。
我在談?wù)撟兞繒r已經(jīng)介紹了一個:賦值運算符=。您用=為變量賦值:
let b = 2
現(xiàn)在讓我們介紹另一組在基礎(chǔ)數(shù)學(xué)中已經(jīng)熟悉的二元運算符。
加法運算符 (+)
const three = 1 + 2
const four = three + 1
如果使用字符串,+運算符也會進行字符串連接,因此請注意:
const three = 1 + 2
three + 1 // 4
'three' + 1 // three1
減法運算符 (-)
const two = 4 - 2
除法運算符 (/)
返回第一個運算符和第二個運算符的商:
const result = 20 / 5 //result === 4
const result = 20 / 7 //result === 2.857142857142857
如果除以零,JavaScript 不會引發(fā)任何錯誤,但會返回該Infinity值(或者-Infinity如果該值為負(fù)數(shù))。
1 / 0 //Infinity
-1 / 0 //-Infinity
余數(shù)運算符 (%)
在許多用例中,余數(shù)是非常有用的計算:
const result = 20 % 5 //result === 0
const result = 20 % 7 //result === 6
NaN余數(shù)總是為零,這是一個表示“非數(shù)字”的特殊值:
1 % 0 //NaN
-1 % 0 //NaN
乘法運算符 (*)
將兩個數(shù)字相乘
1 * 2 //2
-1 * 2 //-2
冪運算符 (**)
將第一個操作數(shù)提高到第二個操作數(shù)的冪
1 ** 2 //1
2 ** 1 //2
2 ** 2 //4
2 ** 8 //256
8 ** 2 //64
優(yōu)先規(guī)則
在同一行中包含多個運算符的每個復(fù)雜語句都會引入優(yōu)先級問題。
舉個例子:
let a = 1 * 2 + 5 / 2 % 2
結(jié)果是 2.5,但為什么呢?
哪些操作先執(zhí)行,哪些需要等待?
某些操作比其他操作具有更高的優(yōu)先級。下表列出了優(yōu)先規(guī)則:
操作員 | 描述 |
同一級別的操作(如+和-)按照它們被發(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
比較運算符
在賦值和數(shù)學(xué)運算符之后,我要介紹的第三組運算符是條件運算符。
可以使用以下運算符來比較兩個數(shù)字或兩個字符串。
比較運算符總是返回一個布爾值,即true或false)。
這些是不等式比較運算符:
例子:
let a = 2
a >= 1 //true
除此之外,我們還有 4 個相等運算符。它們接受兩個值,并返回一個布爾值:
請注意,我們在 JavaScript 中也有==和 !=,但我強烈建議只使用===和!==,因為它們可以防止一些微妙的問題。
條件語句
有了比較運算符,我們就可以討論條件語句了。
if語句用于使程序根據(jù)表達式求值的結(jié)果選擇一條路徑或另一條路徑。
這是最簡單的例子,它總是執(zhí)行:
if (true) {
//do something
}
相反,這將永遠(yuǎn)不會執(zhí)行:
if (false) {
//do something (? never ?)
}
條件檢查傳遞給它的表達式的真值或假值。如果傳遞一個數(shù)字,除非它是 0,否則它總是計算為真。如果傳遞一個字符串,它總是計算為真,除非它是一個空字符串。這些是將類型轉(zhuǎn)換為布爾值的一般規(guī)則。
注意到花括號了嗎?這稱為塊,它用于對不同語句的列表進行分組。
塊可以放在任何可以有單個語句的地方。如果在條件句之后有一條語句要執(zhí)行,可以省略該塊,只寫語句:
if (true) doSomething()
但我總是喜歡用花括號,這樣的語句更清楚。
else可以為if語句提供第二部分。
if如果條件為假,則附加將要執(zhí)行的語句:
if (true) {
//do something
} else {
//do something else
}
由于else接受一個語句,可以在其中嵌套另一個 if/else 語句:
if (a === true) {
//do something
} else if (b === true) {
//do something else
} else {
//fallback
}
數(shù)組
數(shù)組是元素的集合。
JavaScript 中的數(shù)組本身并不是一種類型。
數(shù)組是對象。
我們可以通過以下兩種不同的方式初始化一個空數(shù)組:
const a = []
const a = Array()
第一種是使用數(shù)組文字語法。第二個使用 Array 內(nèi)置函數(shù)。
您可以使用以下語法預(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
可以使用以下語法使用一組值初始化一個新數(shù)組,該語法首先初始化一個由 12 個元素組成的數(shù)組,并用數(shù)字0填充每個元素:
Array(12).fill(0)
可以通過檢查其length屬性來獲取數(shù)組中元素的數(shù)量:
const a = [1, 2, 3]
a.length //3
請注意,可以設(shè)置數(shù)組的長度。如果分配的數(shù)字大于陣列當(dāng)前容量,則不會發(fā)生任何事情。如果分配較小的數(shù)字,則在該位置切割數(shù)組:
const a = [1, 2, 3]
a //[ 1, 2, 3 ]
a.length = 2
a //[ 1, 2 ]
如何將項目添加到數(shù)組
我們可以使用push()方法在數(shù)組末尾添加一個元素:
a.push(4)
我們可以使用unshift()方法在數(shù)組的開頭添加一個元素:
a.unshift(0)
a.unshift(-2, -1)
如何從數(shù)組中刪除一個項目
我們可以使用pop()方法從數(shù)組末尾刪除一個項目:
a.pop()
我們可以使用shift()方法從數(shù)組的開頭刪除一個項目:
a.shift()
如何連接兩個或多個數(shù)組
可以使用concat()方法連接多個數(shù)組:
const a = [1, 2]
const b = [3, 4]
const c = a.concat(b) //[1,2,3,4]
a //[1,2]
b //[3,4]
還可以通過使用擴展運算符 ( ...):
const a = [1, 2]
const b = [3, 4]
const c = [...a, ...b]
c //[1,2,3,4]
如何在數(shù)組中查找特定項
可以使用數(shù)組的find()方法:
a.find((element, index, array) => {
//return true or false
})
返回第一個返回 true 的項目,如果未找到該元素則返回undefined。
一個常用的語法是:
a.find(x => x.id === my_id)
上面的行將返回數(shù)組中id === my_id的第一個元素。
findIndex()與 find()類似,但返回第一個為true 的項目的索引,如果未找到,則返回undefined:
a.findIndex((element, index, array) => {
//return true or false
})
另一種方法是includes():
a.includes(value)
a如果包含則返回真value。
a.includes(value, i)
如果在 position 之后包含value,則返回 true 。
字符串
字符串是一個字符序列。
它也可以定義為字符串文字,用引號或雙引號括起來:
'A string'
"Another string"
我個人一直更喜歡單引號,只在 HTML 中使用雙引號來定義屬性。
將字符串值分配給如下變量:
const name = 'Flavio'
length可以使用它的屬性來確定字符串的長度:
'Flavio'.length //6
const name = 'Flavio'
name.length //6
''這是一個空字符串. 它的長度屬性為 0:
''.length //0
可以使用+運算符連接兩個字符串:
"A " + "string"
可以使用+運算符來插入變量:
const name = 'Flavio'
"My name is " + name //My name is Flavio
定義字符串的另一種方法是使用在反引號內(nèi)定義的模板文字。它們對于使多行字符串更簡單特別有用。使用單引號或雙引號,您無法輕松定義多行字符串 - 您需要使用轉(zhuǎn)義字符。
使用反引號打開模板文字后,只需按 Enter 鍵即可創(chuàng)建一個新行,沒有特殊字符,并且按原樣呈現(xiàn):
const string = `Hey
this
string
is awesome!`
模板文字也很棒,因為它們提供了一種將變量和表達式插入字符串的簡單方法。
您可以使用以下${...}語法來執(zhí)行此操作:
const var = 'test'
const string = `something ${var}`
//something test
在${}里面可以添加任何東西,甚至是表達式:
const string = `something ${1 + 2 + 3}`
const string2 = `something
${foo() ? 'x' : 'y'}`
循環(huán)
循環(huán)是 JavaScript 的主要控制結(jié)構(gòu)之一。
使用循環(huán),我們可以自動化并重復(fù)一段代碼,無論我們希望它運行多少次,甚至無限期地運行。
JavaScript 提供了許多迭代循環(huán)的方法。
我想專注于3種方式:
while
while 循環(huán)是 JavaScript 提供給我們的最簡單的循環(huán)結(jié)構(gòu)。
我們在關(guān)鍵字之后添加一個條件while,并提供一個運行塊,直到條件評估為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)到下一個迭代continue:
while (true) {
if (somethingIsTrue) continue
//do something else
}
非常類似于while,我們有do..while循環(huán)。它與 基本相同while,只是在執(zhí)行代碼塊之后評估條件。
這意味著塊總是至少執(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 中第二個非常重要的循環(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),并且可以使用 快進到循環(huán)break的下一次迭代。forcontinue
for...of
這個循環(huán)是相對較新的(2015 年引入),它是for循環(huá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ù)是一個自包含的代碼塊。
這是一個函數(shù)聲明:
function getData() {
// do something
}
一個函數(shù)可以通過調(diào)用它隨時運行,如下所示:
getData()
一個函數(shù)可以有一個或多個參數(shù):
function getData() {
//do something
}
function getData(color) {
//do something
}
function getData(color, age) {
//do something
}
當(dāng)我們可以傳遞參數(shù)時,我們調(diào)用傳遞參數(shù)的函數(shù):
function getData(color, age) {
//do something
}
getData('green', 24)
getData('black')
請注意,在第二次調(diào)用中,我將black字符串參數(shù)作為color參數(shù)傳遞,但沒有傳遞age. 在這種情況下,age函數(shù)內(nèi)部是undefined.
我們可以使用以下條件檢查值是否未定義:
function getData(color, age) {
//do something
if (typeof age !== 'undefined') {
//...
}
}
typeof是一個一元運算符,它允許我們檢查變量的類型。
您也可以通過以下方式檢查:
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ù)組、對象以及函數(shù)。
一個函數(shù)有一個返回值。默認(rèn)情況下,函數(shù)返回undefined,除非您添加return帶有值的關(guān)鍵字:
function getData() {
// do something
return 'hi!'
}
我們可以在調(diào)用函數(shù)時將此返回值分配給變量:
function getData() {
// do something
return 'hi!'
}
let result = getData()
result現(xiàn)在保存一個帶有hi!值的字符串。
您只能返回一個值。
要返回多個值,您可以返回一個對象或數(shù)組,如下所示:
function getData() {
return ['Flavio', 37]
}
let [name, age] = getData()
函數(shù)可以在其他函數(shù)中定義:
const getData = () => {
const dosomething = () => {}
dosomething()
return 'test'
}
嵌套函數(shù)不能從封閉函數(shù)的外部調(diào)用。
你也可以從一個函數(shù)中返回一個函數(shù)。
箭頭函數(shù)
箭頭函數(shù)是最近對 JavaScript 的介紹。
它們經(jīng)常被用來代替我在前一章中描述的“常規(guī)”函數(shù)。您會發(fā)現(xiàn)這兩種形式隨處可見。
從視覺上看,它們允許您使用更短的語法編寫函數(shù),來自:
function getData() {
//...
}
到
() => {
//...
}
但是..注意我們這里沒有名字。
箭頭函數(shù)是匿名的。我們必須將它們分配給一個變量。
我們可以將常規(guī)函數(shù)分配給變量,如下所示:
let getData = function getData() {
//...
}
當(dāng)我們這樣做時,我們可以從函數(shù)中刪除名稱:
let getData = function() {
//...
}
并使用變量名調(diào)用函數(shù):
let getData = function() {
//...
}
getData()
這與我們對箭頭函數(shù)所做的事情相同:
let getData = () => {
//...
}
getData()
如果函數(shù)體只包含一條語句,則可以省略括號并將所有內(nèi)容寫在一行上:
const getData = () => console.log('hi!')
參數(shù)在括號中傳遞:
const getData = (param1, param2) =>
console.log(param1, param2)
如果您有一個(并且只有一個)參數(shù),則可以完全省略括號:
const getData = param => console.log(param)
箭頭函數(shù)允許您有一個隱式返回 - 無需使用return關(guān)鍵字即可返回值。
它在函數(shù)體中有一行語句時起作用:
const getData = () => 'test'
getData() //'test'
與常規(guī)函數(shù)一樣,我們可以為參數(shù)設(shè)置默認(rèn)值,以防它們未傳遞:
const getData = (color = 'black',
age = 2) => {
//do something
}
和常規(guī)函數(shù)一樣,我們只能返回一個值。
箭頭函數(shù)還可以包含其他箭頭函數(shù),甚至是常規(guī)函數(shù)。
這兩種函數(shù)非常相似,所以你可能會問為什么要引入箭頭函數(shù)。與常規(guī)函數(shù)的最大區(qū)別在于它們用作對象方法時。這是我們將很快研究的事情。
對象
任何不是原始類型(字符串、數(shù)字、布爾值、符號、null 或未定義)的值都是對象。
下面是我們定義對象的方式:
const car = {
}
這是對象字面量語法,它是 JavaScript 中最好的東西之一。
您還可以使用以下new Object語法:
const car = new Object()
另一種語法是使用Object.create():
const car = Object.create()
new您還可以在帶有大寫字母的函數(shù)之前使用關(guān)鍵字初始化對象。此函數(shù)用作該對象的構(gòu)造函數(shù)。在那里,我們可以初始化我們作為參數(shù)接收的參數(shù),以設(shè)置對象的初始狀態(tài):
function Car(brand, model) {
this.brand = brand
this.model = model
}
我們使用以下方法初始化一個新對象:
const myCar = new Car('Ford', 'Fiesta')
myCar.brand //'Ford'
myCar.model //'Fiesta'
對象總是通過引用傳遞。
如果您為一個變量分配與另一個變量相同的值,如果它是像數(shù)字或字符串這樣的原始類型,則它們是按值傳遞的:
舉個例子:
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ù),在底層也是對象,因此了解它們的工作原理非常重要。
對象屬性
對象具有屬性,這些屬性由與值關(guān)聯(lián)的標(biāo)簽組成。
屬性的值可以是任何類型,這意味著它可以是數(shù)組、函數(shù),甚至可以是對象,因為對象可以嵌套其他對象。
這是我們在上一章看到的對象字面量語法:
const car = {
}
我們可以color這樣定義一個屬性:
const car = {
color: 'blue'
}
在這里,我們有一個car對象,其屬性名為color,其值為blue。
標(biāo)簽可以是任何字符串,但要注意特殊字符 - 如果我想在屬性名稱中包含一個無效的字符作為變量名,我將不得不在它周圍使用引號:
const car = {
color: 'blue',
'the color': 'blue'
}
無效的變量名字符包括空格、連字符和其他特殊字符。
如您所見,當(dāng)我們有多個屬性時,我們用逗號分隔每個屬性。
我們可以使用 2 種不同的語法來檢索屬性的值。
第一個是點符號:
car.color //'blue'
第二個(這是我們唯一可以用于名稱無效的屬性)是使用方括號:
car['the color'] //'blue'
如果您訪問不存在的屬性,您將獲得以下undefined值:
car.brand //undefined
如前所述,對象可以具有嵌套對象作為屬性:
const car = {
brand: {
name: 'Ford'
},
color: 'blue'
}
在此示例中,您可以使用訪問品牌名稱
car.brand.name
或者
car['brand']['name']
您可以在定義對象時設(shè)置屬性的值。
但是您以后可以隨時更新它:
const car = {
color: 'blue'
}
car.color = 'yellow'
car['color'] = 'red'
您還可以向?qū)ο筇砑有聦傩裕?/span>
car.model = 'Fiesta'
car.model //'Fiesta'
給定對象
const car = {
color: 'blue',
brand: 'Ford'
}
您可以使用從該對象中刪除一個屬性
delete car.brand
對象方法
我在前一章中談到了函數(shù)。
可以將函數(shù)分配給函數(shù)屬性,在這種情況下,它們稱為方法。
在這個例子中,start屬性分配了一個函數(shù),我們可以使用我們用于屬性的點語法來調(diào)用它,括號在末尾:
const car = {
brand: 'Ford',
model: 'Fiesta',
start: function() {
console.log('Started')
}
}
car.start()
在使用function() {}語法定義的方法中,我們可以通過引用來訪問對象實例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()
這是因為箭頭函數(shù)沒有綁定到對象。
這就是為什么經(jīng)常將常規(guī)函數(shù)用作對象方法的原因。
方法可以接受參數(shù),如常規(guī)函數(shù):
const car = {
brand: 'Ford',
model: 'Fiesta',
goTo: function(destination) {
console.log(`Going to ${destination}`)
}
}
car.goTo('Rome')
類
我們討論了對象,這是 JavaScript 中最有趣的部分之一。
在本章中,我們將通過介紹類來提升一個層次。
什么是類?它們是一種為多個對象定義通用模式的方法。
讓我們看一個人對象:
const person = {
name: 'Flavio'
}
我們可以創(chuàng)建一個名為Person(注意大寫P,使用類時的約定)的類,它有一個name屬性:
class Person {
name
}
現(xiàn)在從這個類中,我們像這樣初始化一個flavio對象:
const flavio = new Person()
flavio稱為 Person 類的實例。
我們可以設(shè)置name屬性的值:
flavio.name = 'Flavio'
我們可以使用
flavio.name
就像我們對對象屬性所做的那樣。
類可以保存屬性,例如name和方法。
方法是這樣定義的:
class Person {
hello() {
return 'Hello, I am Flavio'
}
}
我們可以在類的實例上調(diào)用方法:
class Person {
hello() {
return 'Hello, I am Flavio'
}
}
const flavio = new Person()
flavio.hello()
當(dāng)我們創(chuàng)建一個新的對象實例時,我們可以使用一個特殊的方法 constructor()來初始化類屬性。
它是這樣工作的:
class Person {
constructor(name) {
this.name = name
}
hello() {
return 'Hello, I am ' + this.name + '.'
}
}
注意我們?nèi)绾问褂?/span>this來訪問對象實例。
現(xiàn)在我們可以從類中實例化一個新對象,傳入一個字符串,當(dāng)我們調(diào)用時,hello我們會得到一條個性化的消息:
const flavio = new Person('flavio')
flavio.hello() //'Hello, I am flavio.'
初始化對象時,將constructor使用傳遞的任何參數(shù)調(diào)用該方法。
通常方法是在對象實例上定義的,而不是在類上。
可以定義一個 static 方法以允許它在類上執(zhí)行:
class Person {
static genericHello() {
return 'Hello'
}
}
Person.genericHello() //Hello
這有時非常有用。
繼承
一個類可以擴展另一個類,使用該類初始化的對象繼承這兩個類的所有方法。
假設(shè)我們有一個類Person:
class Person {
hello() {
return 'Hello, I am a Person'
}
}
我們可以定義一個新類,Programmer擴展Person:
class Programmer extends Person {
}
現(xiàn)在,如果我們用 class 實例化一個新對象Programmer,它就可以訪問該hello()方法:
const flavio = new Programmer()
flavio.hello() //'你好, 我是一個人。'
在子類中,可以通過調(diào)用 super() 來引用父類方法:
class Programmer extends Person {
hello() {
return super.hello() +
'我也是一名程序員。'
}
}
const flavio = new Programmer()
flavio.hello()
上面的程序打印你好,我是一個人。我也是一名程序員。
異步編程和回調(diào)
大多數(shù)時候,JavaScript 代碼是同步運行的。
這意味著執(zhí)行一行代碼,然后執(zhí)行下一個代碼,以此類推。
一切都如您所愿,這是它在大多數(shù)編程語言中的工作方式。
但是,有時不能只等待一行代碼執(zhí)行。
不能只等待 2 秒鐘來加載一個大文件,然后完全停止程序。
不能只等待下載網(wǎng)絡(luò)資源后再做其他事情。
JavaScript 通過使用回調(diào)解決了這個問題。
如何使用回調(diào)的最簡單示例之一是使用計時器。計時器不是 JavaScript 的一部分,但它們由瀏覽器和 Node.js 提供。讓我談?wù)勎覀儞碛械囊粋€計時器:setTimeout()函數(shù)。
該setTimeout()函數(shù)接受 2 個參數(shù):一個函數(shù)和一個數(shù)字。該數(shù)字是在函數(shù)運行之前必須經(jīng)過的毫秒數(shù)。
例子:
setTimeout(() => {
// 2秒以后執(zhí)行
console.log('inside the function')
}, 2000)
包含該console.log('inside the function')行的函數(shù)將在 2 秒后執(zhí)行。
如果在函數(shù)之前添加一個 console.log('before') 日志,函數(shù)之后添加一個console.log('after')日志:
console.log('before')
setTimeout(() => {
// runs after 2 seconds
console.log('inside the function')
}, 2000)
console.log('after')
將在控制臺中看到這種情況:
before
after
inside the function
回調(diào)函數(shù)是異步執(zhí)行的。
當(dāng)在瀏覽器中使用文件系統(tǒng)、網(wǎng)絡(luò)、事件或 DOM 時,這是一種非常常見的模式。
我提到的所有東西都不是“核心”JavaScript,因此本手冊中沒有解釋它們,但會在https://flaviocopes.com上的其他手冊中找到很多示例。
以下是我們?nèi)绾卧诖a中實現(xiàn)回調(diào)。
我們定義一個接受callback參數(shù)的函數(shù),它是一個函數(shù)。
當(dāng)代碼準(zhǔn)備好調(diào)用回調(diào)時,我們通過傳遞結(jié)果來調(diào)用它:
const doSomething = callback => {
//do things
//do things
const result = /* .. */
callback(result)
}
使用此函數(shù)的代碼將像這樣使用它:
doSomething(result => {
console.log(result)
})
Promise
Promise 是處理異步代碼的另一種方法。
正如我們在前一章中看到的,通過回調(diào)我們將一個函數(shù)傳遞給另一個函數(shù)調(diào)用,該函數(shù)將在函數(shù)完成處理時調(diào)用。
像這樣:
doSomething(result => {
console.log(result)
})
當(dāng)doSomething()代碼結(jié)束時,它調(diào)用作為參數(shù)接收的函數(shù):
const doSomething = callback => {
//do things
//do things
const result = /* .. */
callback(result)
}
這種方法的主要問題是,如果我們需要在其余代碼中使用這個函數(shù)的結(jié)果,我們所有的代碼都必須嵌套在回調(diào)中,如果我們必須進行 2-3 次回調(diào),我們輸入的是通常定義“回調(diào)地獄”,將許多級別的函數(shù)縮進到其他函數(shù)中:
doSomething(result => {
doSomethingElse(anotherResult => {
doSomethingElseAgain(yetAnotherResult => {
console.log(result)
})
})
})
Promise 是處理這個問題的一種方法。
而不是這樣做:
doSomething(result => {
console.log(result)
})
我們以這種方式調(diào)用基于 Promise 的函數(shù):
doSomething()
.then(result => {
console.log(result)
})
我們首先調(diào)用函數(shù),然后我們有一個在函數(shù)結(jié)束時調(diào)用的then()方法。
縮進無關(guān)緊要,但為了清晰起見,通常會使用這種樣式。
使用以下catch()方法檢測錯誤很常見:
doSomething()
.then(result => {
console.log(result)
})
.catch(error => {
console.log(error)
})
現(xiàn)在,為了能夠使用這種語法,doSomething()函數(shù)實現(xiàn)必須有點特殊。它必須使用 Promises API。
而不是將其聲明為普通函數(shù):
const doSomething = () => {
}
我們將它聲明為一個 Promise 對象:
const doSomething = new Promise()
我們在 Promise 構(gòu)造函數(shù)中傳遞一個函數(shù):
const doSomething = new Promise(() => {
})
該函數(shù)接收 2 個參數(shù)。第一個是我們調(diào)用來解析Promise 的函數(shù),第二個是我們調(diào)用來拒絕 Promise 的函數(shù)。
const doSomething = new Promise(
(resolve, reject) => {
})
解決一個 Promise 意味著成功完成它(這導(dǎo)致then()在任何使用它的地方調(diào)用該方法)。
拒絕一個 Promise 味著以一個錯誤結(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 的更高層次的抽象。
一個異步函數(shù)返回一個 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ù)”字符串。
有一個特別的警告:每當(dāng)我們使用await關(guān)鍵字時,我們必須在定義為 async 的函數(shù)中這樣做。
像這樣:
const doSomething = async () => {
const data = await getData()
console.log(data)
}
async/await 讓我們擁有更簡潔的代碼和簡單的思維模型來處理異步代碼。
正如在上面的示例中看到的,我們的代碼看起來非常簡單。將其與使用Promise或回調(diào)函數(shù)的代碼進行比較。
這是一個非常簡單的例子,當(dāng)代碼復(fù)雜得多時,主要的好處就會出現(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)我介紹變量時,我談到了使用const、let和var。
范圍是對程序的一部分可見的變量集。
在 JavaScript 中,我們有全局作用域、塊作用域和函數(shù)作用域。
如果變量是在函數(shù)或塊之外定義的,它會附加到全局對象并且它具有全局范圍,這意味著它可以在程序的每個部分中使用。
let 、const 和var聲明變量之間有一個非常重要的區(qū)別。
在函數(shù)內(nèi)部定義的變量var僅在該函數(shù)內(nèi)部可見,類似于函數(shù)的參數(shù)。
另一方面,定義為const或 let 的變量僅在定義它的塊內(nèi)可見。
塊是組合成一對花括號的一組指令,就像我們可以在if語句、for循環(huán)或函數(shù)中找到的指令一樣。
重要的是要理解一個塊沒有為 定義一個新的范圍var,但它為let和 const 定義了一個新的范圍。
這具有非常實際的意義。
假設(shè)在函數(shù)的 if 條件內(nèi)定義了一個 var 變量
function getData() {
if (true) {
var data = 'some data'
console.log(data)
}
}
如果調(diào)用此函數(shù),ome data打印到控制臺。
如果嘗試將 console.log(data) 移動到if語句之后,它仍然有效:
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)
}
會得到一個錯誤:ReferenceError: data is not defined。
這是因為var是函數(shù)作用域,這里發(fā)生了一種特殊的事情,稱為提升。簡而言之,JavaScript 在運行代碼之前將聲明var移動到最近的函數(shù)的頂部。這或多或少是這個函數(shù)在 JS 內(nèi)部的樣子:
function getData() {
var data
if (true) {
data = 'some data'
}
console.log(data)
}
這就是為什么也可以console.log(data)在函數(shù)的頂部,甚至在它被聲明之前,會得到undefined該變量的值:
function getData() {
console.log(data)
if (true) {
var data = 'some data'
}
}
但是如果切換到let,會得到一個錯誤ReferenceError: data is not defined,因為 let 聲明不會發(fā)生提升。
const和let 遵循相同的規(guī)則:它們是塊范圍的。
一開始可能會很棘手,但一旦你意識到這種差異,你就會明白為什么var現(xiàn)在被認(rèn)為是一種不好的做法——它們的活動部件更少,而且它們的范圍僅限于塊,這也使它們非常好作為循環(huán)變量,因為它們在循環(huán)結(jié)束后不再存在:
function doLoop() {
for (var i = 0; i < 10; i++) {
console.log(i)
}
console.log(i)
}
doLoop()
當(dāng)您退出循環(huán)時,i將是一個值為 10 的有效變量。
如果切換到let,當(dāng)你嘗試切換到時console.log(i)會導(dǎo)致錯誤ReferenceError: i is not defined。
結(jié)論
非常感謝您閱讀完本手冊。
我希望它能激發(fā)您更多地了解 JavaScript。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。