前端開發中涉及表單的頁面非常多,看似功能簡單,開發快速,實則占去了很大一部分時間。當某個表單包含元素過多時還會導致html代碼過多,vue文件過大。從而不容易查找、修改和維護。為了提高開發效率及降低維護成本,下麵介紹表單配置化組件的封裝原理與封裝方法。 ...
JavaScript
簡介
JavsScript 於 1995 年由 Brendan Eich 用時 10 天寫出,用於網景瀏覽器。最初的名字叫 LiveScript,也被部分員工稱為 Mocha。那時 Java 語言很流行,出於商業化的考量,更名為 JavaScript,但兩者之間沒有關聯。
最早的 JS 作為腳本語言給瀏覽器增加一些諸如滑鼠跟隨等交互性特效,通過在 HTML 中添加 <script>
元素實現。
1996 年網景和 ECMA 達成了協議,起草 JS 的規範,第一版規範由 ECMA 做出並於 1997 釋出。這個規範被稱為 ECMA-262 標準。
JS 並不是一個獨立的實體,它僅存在於實現中,這個實現稱為 JS 引擎。
傳統的 JS 引擎環境就是瀏覽器,確切來說,JS 引擎是瀏覽器的一個構建塊。
此外,JS 引擎本身也可以和瀏覽器的其他部分交互,這些部分被稱為瀏覽器 API。
所以 JS 代碼有兩個功能:
- 和瀏覽器中的 JS 引擎交互
- 和瀏覽器中的 JS 引擎外的其他部分交互
隨後在 2009 年,Ryan Dahl 發佈了 Node.js,他把 JS 引擎作為一個獨立的實體,使得 JS 可以在瀏覽器外,作為服務端環境運行。
幾種類似 JavaScript 的語言
- JScript
- VBScript
- TypeScript
為什麼選擇 JavaScript
- 目前最流行的語言之一
- 瀏覽器唯一編程語言
- 使用者數量多
- 容易使用
- 無處不在
- 純 JavaScript (Vanilla JS / Plain JS)
- UI 庫/框架(React/Vue/Angular/jQuery/Ember/Next)
- 服務端(Node/Deno/Bun)
- 移動端(React Native)
- 桌面端(Electron)
- 社區龐大
- 需求大
註釋
被註釋的代碼塊是不會執行的。
JavaScript有兩種寫註釋(comment)的方法。
- 使用
//
註釋掉當前行的代碼。 這是一個行內註釋:
// This is an in-line comment.
- 也可以使用多行註釋,使用
/*
開始,*/
結束。 這是一個多行註釋:
/* this is a multi-line commment */
最佳實踐:應該添加註釋來解釋代碼的作用,適當的註釋能讓代碼更易懂。
分號
分號(semi-colon) ;
在 JavaScript 中用於表示一條語句的結尾。
console.log("hello world");
console.log("hello world")
瀏覽器有自動插入分號(Automatic Semi-Colon Insertion / ASI)的功能,所以不加分號瀏覽器也能正確識別語句的結尾。但是最佳實踐顯示,應該加上分號以提高代碼的可讀性。
變數 Variable
數據類型 Data Type
JavaScript 提供七種不同的基本類型(Primitive),分別是:
undefined
未定義、null
空、boolean
布爾、string
字元串、symbol
標誌、number
數字、bigint
任意大的整數
基本類型不是對象(object),沒有方法(method)和屬性(property)。
聲明 Declare
通過在變數前面使用關鍵字 var
,聲明一個變數,例如:
var myName;//undefined
變數名稱可以由數字、字母、美元符號 $
或者下劃線 _
組成,但是不能包含空格或者以數字為開頭。
如果只聲明不賦值,那麼值為 undefined
。
字元串變數 String
"your name"
被稱為字元串字面量(string literal)。 字元串文字或字元串是用單引號或雙引號括起來的一系列零個或多個字元。
與其他一些編程語言不同的是,單引號和雙引號的功能在 JavaScript 中是相同的。
字元串在開頭和結尾都要有相同的引號,如果在中間使用了相同的引號,字元串會提前中止並拋出錯誤。
'' // empty string
"" // empty string
var myFirstName = "Pete";
var myLastName = "Mitchell";
const conversation = 'Finn exclaims to Jake, "Algebraic!"';
var str = 'de'f'; // SyntaxError: Unexpected identifier
可迭代
在 JS 中,字元串是可迭代(iterable)類型,指的是這種數據類型可以用迴圈迭代。
字元串也被稱為類數組(array-like)類型。
字元串的長度 Length
通過 .length
來獲得字元串的長度。
let lastNameLength = 0;
const lastName = "Lovelace";
lastNameLength = lastName.length;
字元串索引 Index
方括弧表示法(Bracket notation)是一種在字元串中的特定 index(索引)處獲取字元的方法。
大多數現代編程語言,是從 0 開始計數。 這被稱為基於零(Zero-based)的索引。
let firstLetterOfLastName = "";
const lastName = "Lovelace";
firstLetterOfLastName = lastName[0]; // 'L'
字元串的不變性 Immutable
在 JavaScript 中,字元串(String
)的值是不可變的(immutable),這意味著一旦字元串被創建就不能被改變。
例如:
let myStr = "Bob";
myStr[0] = "J";
是不會把變數 myStr
的值改變成 Job
的,因為變數 myStr
是不可變的。 註意,這並不 意味著 myStr
永遠不能被改變,只是字元串字面量 string literal 的各個字元不能被改變。 改變 myStr
的唯一方法是重新給它賦一個值,例如:
let myStr = "Bob";
myStr = "Job";
字元串中的字元
為了讀取從 0 開始某特定位置的字元,使用 charAt()
方法:
var greet = 'hello';
greet.charAt(0) // h
字元串拼接
字元串拼接方法 concat()
:
"Wo".concat("rl").concat("d") # World
獲得某字元的索引
使用 indexOf()
獲得某字元在字元串中的索引位置,如果不包含該字元,則返回 -1
,如果包含多個相同字元,則返回第一個字元出現的位置;lastIndexOf()
返回相同字元出現的最後一個位置:
'greet'.indexOf('g') // 0
'greet'.indexOf('e') // 2
'greet'.indexOf('a') // -1
'cace'.lastIndexOf('c'); // 2
Undefined & Null
undefined
數據類型只有一個值:undefined
。
- 所有函數預設返回
undefined
,除非顯式返回一個值。 - 訪問對象不存在的屬性,返回
undefined
- 已聲明但未賦值的變數,
undefined
當 JavaScript 中的變數被聲明的時候,程式內部會給它一個初始值 undefined
。 當對一個值為 undefined
的變數進行運算操作的時候,算出來的結果將會是 NaN
,它的意思是 "Not a Number"。 當用一個值是 undefined
的變數來做字元串拼接操作的時候,它會轉換成字元串(string)undefined
。
null
指代缺少(absence)值,undefined
指代未賦值。
var str = 'abc';
str.match(/d/); // null
var str2; // undefined
變數名區分大小寫 Case Sensitivity
最佳實踐:使用駝峰命名法(camelCase)來命名一個 Javascript 變數。 在駝峰命名法中,變數名的第一個單詞的首字母小寫,後面的單詞的第一個字母大寫。
var someVariable;
var anotherVariable;
var 和 let
使用 var
關鍵字(keywords)聲明變數存在的問題:
- 在聲明前就可以被使用
- 相同的變數可以再次聲明
- 可以在全局或者函數內部的作用域起作用
// 第一種
console.log(user); // mike
var user = 'mike';
// 第二種
var camper = "James";
var camper = "David";
console.log(camper); // David
ES6 中引入了一個名為 let
的關鍵字,這是對 JavaScript 的一次重大更新,以解決與 var
關鍵字有關的潛在問題。
如果將上面代碼中的 var
替換為 let
,則會導致錯誤。使用 let
時,同名的變數只能聲明一次。
const
const
具有 let
的所有功能,另外還有一個額外的好處,即使用 const
聲明的變數是只讀(Read-only)的。 它們是一個常量值(constant),這意味著一旦一個變數被賦值為 const
,它就不能被重新賦值:
const FAV_PET = 'cats';
FAV_PETS = 'dogs'
// this line will cause a error;
命名常量的常見做法是全部使用大寫字母,單詞之間用下劃線分隔。
小數 Decimal
小數有時候也被稱作浮點數或者 floats。
提示: 不是所有的實數都可以用浮點數(floating point)來表示。 因為可能產生四捨五入的錯誤。
var myDecimal = 5.7;
布爾值 Boolean
布爾值只能是兩個值中的一個:true
或者 false
。
布爾值是不帶引號的。 字元串 "true"
和 "false"
不是布爾值,在 JavaScript 中也沒有特殊含義。
function welcomeToBooleans() {
return true;
}
真值 假值
真值(Truthy)和假值(Falsy)指的是在布爾值的上下文中,轉換後為 true 和 false 的值。
所有除 false
、0
、-0
、0n
、""
、null
、undefined
和 NaN
以外的皆為真值)。
if (true)
if ({})
if ([])
if (42)
if ("0")
if ("false")
if (new Date())
if (-42)
if (12n)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)
JS 中有 8 個假值:
值 | 說明 |
---|---|
false |
false 關鍵字 |
0 | 數值 zero |
-0 | 數值 負 zero |
0n | 當 BigInt 作為布爾值使用時,遵從其作為數值的規則. 0n 是 falsy 值。 |
"", '', `` | 這是一個空字元串 (字元串的長度為零). JavaScript 中的字元串可用雙引號 "" , 單引號 '' , 或 模板字面量 ```` 定義。 |
null | null - 缺少值 |
undefined | undefined - 原始值 |
NaN | NaN - 非數值 |
BigInt Symbol
這兩個數據類型是 ES6 引入的,BigInt 用於表示更大的數字,Symbol 用於表示統一標識符。
數字 Number
數字類型可以表示整數(integer) 或者小數(decimal)。
運算 Operation
賦值 Assignment
使用賦值(assignment)運算符 =
將值存儲在變數中。
var myVariable = 5; // 直接賦值
var myCode; // 先聲明後賦值
myCode = 100;
在賦值後,可使用賦值運算符將某變數的值賦給另一個變數。
var myVariable = 5;
var b;
b = myVariable;
加法 Add
var sum = 10 + 1; // sum = 11;
拼接 Concatenate
當 +
操作符被用於一個 String
類型的值的時候,它被稱作拼接操作符。
const myStr = "This is the start." + " " + "This is the end."; // myStr "This is the start This is the end"
如果一個數字和字元串做拼接,JS 會把數字轉化為字元串然後再拼接,最後得到一個字元串:
365 + " days" // "365 days"
1 + "2" // "12"
這種看不見(under-the-hood)的轉換稱為“強制類型轉換(coercion)”。
減法 Subtract
var difference = 10 - 2; // 8
乘法 Multiply
var product = 1 * 2; // 2
除法 Divide
var quotient = 10 / 2; // 5
自增 Increment
var my = 1;
my++; // my 2
自減 Decrement
var my = 2;
my--; // my 1
求餘 Reminder
求餘運算符(The modulus operator) %
返回兩個數相除得到的餘數
用法
在數學中,判斷一個數是奇數還是偶數,只需要判斷這個數除以 2
得到的餘數是 0 還是 1。
提示
餘數運算符(remainder)有時被錯誤地稱為“模數”運算符。 它與模數非常相似,但不能用於負數的運算。
let remainder = 11 % 3; // 2
求冪 Exponentiation
求冪運算符 **
返回某底數的次冪
let exp = 10 ** 2 // 100
複合賦值 Compound Assignment
+=
,-=
,*=
,`/=``
+=
稱為“addition assignment operator。
還可以使用 +=
運算符來拼接字元串到現有字元串變數的結尾。
let myVar = 1;
myVar += 5;
myVar -= 1;
myVar *= 1;
myVar /= 1;
let myStr = "This is the first sentence.";
myStr += " ";
myStr += "This is the second sentence."
相等 Equality Operator
相互比較的操作都返回一個 true
或 false
值。
最基本的運算符是相等運算符:==
。
在 JavaScript 中,為了讓兩個不同的數據類型(例如 numbers
和 strings
)的值可以作比較,它必須把一種類型轉換為另一種類型。 這叫作 “類型強制轉換”。 轉換之後,可以像下麵這樣來比較:
1 == 1 //true
1 == 2 //false
1 == '1' //true
"3" == 3 //true
嚴格相等 Strict Equality Operator
嚴格相等運算符不會做類型轉換。如果比較的值類型不同,那麼在嚴格相等運算符比較下它們是不相等的,會返回 false 。
3 === 3 //true
3 === '3' //false
不等 Inquality Opeartor
不相等運算符(!=
)與相等運算符是相反的。 不相等運算符在比較的時候也會轉換值的數據類型。
1 != 2 // true
1 != "1" // false
1 != '1' // false
1 != true // false
0 != false // false
嚴格不等 Strict Inequality Operator
嚴格不相等運算符(!==
)與全等運算符是相反的。 嚴格不相等運算符不會轉換值的數據類型。
3 !== 3 // false
3 !== '3' // true;
4 !== 3 // true;
大於 Greater Than Operator
使用大於運算符(>
)來比較兩個數字。 如果大於運算符左邊的數字大於右邊的數字,將會返回 true
。 否則,它返回 false
。
大於運算符在比較的時候,會轉換值的數據類型。
5 > 3 // true;
7 > '3' // true;
2 > 3 // false;
'1' > 9 // false;
大於等於 Greater Than Or Equal To Operator
使用大於等於運算符(>=
)來比較兩個數字的大小。 如果大於等於運算符左邊的數字比右邊的數字大或者相等,會返回 true
。 否則,會返回 false
。
大於等於運算符在比較的時候會轉換值的數據類型。
6 >= 6 // true
7 >= '3' // true
2 >= 3 // false
'7' >= 9 // false
小於 Less Than Operator
使用小於運算符(<
)來比較兩個數字。 如果小於運算符左邊的數字比右邊的數字小,它會返回 true
。 否則會返回 false
。 小於運算符在做比較的時候會轉換值的數據類型。
2 < 5 // true
'3' < 7 // true
5 < 5 // false
3 < 2 // false
'8' < 4 // false
小於等於 Less Than Or Equal To Operator
使用小於等於運算符(<=
)比較兩個數字的大小。 如果在小於等於運算符左邊的數字小於或者等於右邊的數字,它會返回 true
。 如果在小於等於運算符左邊的數字大於右邊的數字,它會返回 false
。小於或等於運算符會轉換數據類型。
4 <= 5 // true
'7' <= 7 // true
5 <= 5 // true
3 <= 2 // false
'8' <= 4 // false
邏輯與 Logical And Opeator
當且僅當運算符的左邊和右邊都是 true,邏輯與運算符(&&
)才會返回 true
。
該運算符可用於兩個比較運算:
if (val <= 50 && val >= 25) {
return "Yes";
}
邏輯或 Logical Or Operator
只要邏輯或運算符(||
)兩邊的任何一個運算的結果是 true
,則返回 true
。 否則,返回 false
。
if (val <= 10 || val >= 20) {
return "Outside";
}
邏輯非 Logical Not Operator
當結果為 true
,邏輯非(!
)返回 false
;反之返回 true
。
var a = 6
a > 5 # true
!(a > 5) # false
三元運算符 Ternary Operator
條件運算符( conditional operator,)(也稱為三元運算符( ternary operator))語法是:a ? b : c
, where a
是條件,當條件返回 true
的時候運行代碼 b
,當條件返回 false
的時候運行代碼 c
。
function checkEqual(a, b) {
return a === b ? "Equal" : "Not Equal";
}
確定類型 Typeof
使用 typeof
運算符確定變數或值的類型
typeof 3 // number
typeof '3' // string
typeof [] // object
typeof {} // object
優先順序和結合律
優先順序(precedence)決定了運算的先後次序,結合律(associativity)決定了在優先順序相同的情況下,運算的左右順序。
有兩種結合律:
- 從左到右
- 從右到左
轉義 Escape
定義一個字元串必須要用單引號或雙引號來包裹它。 那麼當字元串裡面包含引號 "
或者 '
時,在 JavaScript 中,可以通過在引號前面使用反斜杠(\
)來轉義引號。
const myStr = "I am a \"double quoted\" string inside \"double quotes\".";
轉義字元 Escape Sequence
引號不是字元串中唯一可以被轉義(escaped)的字元。 使用轉義字元有兩個原因:
- 首先是可以使用無法輸入的字元,例如退格。
- 其次是可以在一個字元串中表示多個引號,而不會出錯。
代碼 | 輸出 |
---|---|
\' |
單引號 |
\" |
雙引號 |
\\ |
反斜杠 |
\n |
換行符 |
\r |
回車符 |
\t |
製表符 |
\b |
退格 |
\f |
換頁符 |
請註意,必須對反斜杠本身進行轉義,它才能顯示為反斜杠。
const myStr = "FirstLine\n\t\\SecondLine\nThirdLine";
條件 Conditional
條件語句也被稱為控制流語句(flow control statement)。
if else
if
語句用於在代碼中做出決定。
當條件的計算結果為 true
,程式執行大括弧內的語句。 當布爾條件的計算結果為 false
,大括弧內的代碼將不會執行。使用 else
語句,可以執行當條件為假時相應的代碼。
如果有多個條件語句,通過 else if
語句把 if
語句鏈起來。
function trueOrFalse(wasThatTrue) {
if (wasThatTrue) {
return "Yes, that was true";
}
else {
return "No, that was false";
}
}
switch
switch
評估一個表達式,將表達式的值與 case 子句匹配。 從第一個匹配的 case
值執行語句,直到遇到 break
。
case
值使用嚴格相等(===
)運算符進行比較。 註意 case
的值,1
匹配數字 1
,'1' 匹配字元串 '1'。break
告訴 JavaScript 停止執行 switch 語句。 如果遺漏了 break
,下一個語句將會被執行。
在 switch
語句中,可能無法用 case
枚舉出所有可能的值。 相反,添加 default
語句,它會在找不到相匹配的 case
語句之後執行。 可以把它看作是 if/else
鏈中最後的那個 else
語句。
default
語句應該被放到最後。
function switchOfStuff(val) {
let answer = "";
switch(val) {
case 'a': answer = "apple"; break;
case 'b': answer = "bird"; break;
case 'c': answer = "cat"; break;
default : answer = "stuff"; break;
}
return answer;
}
switchOfStuff(1); // stuff
如果想為 switch
中的多個不同的輸入設置相同的結果,可以這樣寫:
function sequentialSizes(val) {
let answer = "";
switch(val) {
case 1:
case 2:
case 3: answer = "Low"; break;
case 4:
case 5:
case 6: answer = "Mid";
break;
case 7:
case 8:
case 9: answer = "High";break;
}
return answer;
}
sequentialSizes(1); // Low
迴圈 Loop
while
當 while 指定的條件為真,迴圈才會執行,反之不執行。
const myArray = [];
let i = 5;
while (i <= 5 && i >= 0) {
myArray.push(i);
i--;
}
上面的 i 稱為計數器(counter)。
for
最常見的迴圈就是 for
,它可以迴圈指定次數。
for 迴圈中的可選三個表達式用分號隔開:
for (a; b; c)
,其中 a
為初始化語句,b
為條件語句,c
是最終的表達式。
初始化語句只會在執行迴圈開始之前執行一次。 它通常用於定義和設置迴圈變數。
迴圈條件語句會在每一輪迴圈的開始前執行,只要條件判斷為 true
就會繼續執行迴圈。 當條件為 false
的時候,迴圈將停止執行。 這意味著,如果條件在一開始就為 false,這個迴圈將不會執行。
終止迴圈表達式在每次迴圈迭代結束, 在下一個條件檢查之前時執行,通常用來遞增或遞減迴圈計數。
const myArray = [];
for (let i = 1; i <= 5; i++) {
myArray.push(i);
}
for-of
for-of
迴圈可用在可迭代對象中:
const colors = ['red', 'blue', 'yellow'];
for (var color of colors) {
console.log(color);
}
do-while
它被稱為 do...while
迴圈,是因為不論什麼情況,它都會首先 do
(運行)迴圈里的第一部分代碼,然後 while
(當)規定的條件被評估為 true
(真)的時候,它會繼續運行迴圈。
const myArray = [];
let i = 10;
do {
myArray.push(i);
i++;
} while (i < 11);
嵌套迴圈
如果有一個二維數組,可以使用相同的邏輯,先遍歷外面的數組,再遍歷裡面的子數組。
let myArray = [[1, 2], [3, 4]];
for (let i = 0; i < myArray.length; i++) {
for (let j = 0; j < myArray[i].length; j++) {
console.log(myArray[i][j]);
}
}
函數 Function
把代碼的重覆部分抽取出來,放到一個函數 (function)中。
通過函數名加上後面的小括弧來調用(invoke / call)這個函數,就像這樣: functionName();
每次調用函數時,大括弧之間的所有代碼都將被執行。
function reusableFunction() {
console.log("Hi World");
}
reusableFunction(); // Hi World
傳參 Passing value with Argument
函數的參數 (parameters)在函數調用中充當傳入函數的輸入占位符(也叫形參)。 函數調用時,參數可以為一個或多個。 調用函數時輸入(或傳遞 "passed")的實際值被稱為參數(arguments)。
function functionWithArgs(a,b) {
console.log(a + b);
}
functionWithArgs(3, 4); // 7
返回值 Return Value
使用 return
語句把數據從一個函數中傳出來。
function timesFive(a) {
return a * 5;
}
timesFive(1); // 5
在函數沒有 return
語句的情況下,當調用它時,該函數會執行內部代碼,返回的值是 undefined
。
let sum = 0;
function addThree() {
sum = sum + 3;
}
function addFive() {
sum += 5;
}
addThree();
addFive();
作用域和函數 Scope
全局作用域 Gobal Scope
在 JavaScript 中,作用域涉及到變數的作用範圍。 在函數外定義的變數具有 全局 作用域。 具有全局作用域的變數可以在代碼的任何地方被調用。
未使用 let
或 const
關鍵字聲明的變數會在 global
範圍內自動創建。 當在代碼其他地方無意間定義了一個變數,剛好變數名與全局變數相同,這時會產生意想不到的後果。 應該總是用 let
或 const
聲明變數。
局部作用域 Local Scope
在一個函數內聲明的變數,以及該函數的參數都具有局部(local)作用域。 這意味著它們只在該函數內可見。
在 ES5 中,只有函數能創建局部作用域;ES6 中,使用 let
和 const
可以創建塊級作用域(block scope),塊級作用域是被聲明變數所屬的塊,如果在函數外就是全局,如果函數內就是塊級或者局部。
function test(a) {
let a = 3;
console.log(a);
}
// 3;
console.log(a);
// Reference Error;
優先順序
一個程式中有可能具有相同名稱的局部變數和全局變數。 在這種情況下,局部變數將會優先於全局變數。
const outerWear = "T-Shirt";
function myOutfit() {
const outerWear = "sweater";
return outerWear;
}
myOutfit(); // sweater
數組 Array
在 JS 中,array 也是 object,有內置方法和屬性。
使用數組(array
)存儲多個數據。以左方括弧開始定義一個數組,以右方括弧結束,裡面每個元素之間用逗號隔開。
const myArray = [0, 1, "code"];
多維數組 Multi-Dimensional Array
在其他數組中嵌套數組,這也叫做多維數組(multi-dimensional array)
const myArray = [["html","css"],"javascript"];
索引訪問 Index Access
使用索引(indexes)來訪問數組中的數據。數組索引與字元串一樣使用方括弧來表示,不同的是,它們不是指定字元,而是指定數組中的一個條目。 數組索引與字元串索引一樣是從 0 開始(zero-based)的。註意:數組名與方括弧之間不應該有任何空格,比如array [0]
。
const myArray = [50, 60, 70];
var myData = myArray[0]; // 50
訪問嵌套數組
與訪問嵌套對象類似,數組的方括弧可以用來對嵌套數組進行鏈式訪問。
const myPlants = [
{
type: "flowers",
list: [
"rose",
"tulip",
"dandelion"
]
},
{
type: "trees",
list: [
"fir",
"pine",
"birch"
]
}
];
const secondTree = myPlants[1].list[1]; // pine
索引修改 Index Modify
與字元串不同,數組的條目是 可變的 並且可以自由更改,即使數組是用 const
聲明的。
const myArray = [18, 64, 99];
myArray[0] = 45; // [45,64,99]
訪問多維數組
使用方括弧表示法訪問數組時,第一個方括弧訪問的是數組的最外層(第一層),第二個方括弧訪問的是數組的第二層,以此類推。
const myArray = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
[[10, 11, 12], 13, 14],
];
const myData = myArray[2][1]; // 8;
push()
將數據添加到數組末尾的簡單方法是 push()
函數。
.push()
接受一個或多個參數(parameters),並把它壓入到數組的末尾。
const myArray = [["John", 23], ["cat", 2]];
myArray.push(["dog", 3]); // [["John", 23], ["cat", 2],["dog", 3]]
pop()
.pop()
函數移除數組末尾的元素並返回這個元素。
const myArray = [["John", 23], ["cat", 2]];
let removedFromMyArray = myArray.pop(); // ["cat", 2]
shift()
shift()
移除的是第一個元素。
const myArray = [["John", 23], ["dog", 3]];
const removedFromMyArray = myArray.shift(); // ["John", 23]
unshift()
unshift
(移入)一個元素到數組的頭部。
const myArray = [["John", 23], ["dog", 3]];
myArray.unshift(["Paul", 35]); // ["Paul", 35]],[["John", 23],["dog", 3]
splice()
splice()
可以從數組中的任意位置連續刪除任意數量的元素。
splice()
最多可以接受 3 個參數。
splice()
接收的前兩個參數是整數,表示正在調用的splice()
數組中的元素的索引或位置。 splice()
的第一個參數代表從數組中的哪個索引開始移除元素,而第二個參數表示要從數組中的這個位置開始刪除多少個元素。
splice()
不僅會修改調用該方法的數組,還會返回一個包含被移除元素的數組:
const arr = [2, 4, 5, 1, 7, 5, 2, 1];
arr.splice(1, 4);
console.log(arr);
第三個參數可以是一個或多個元素,這些元素會被添加到數組中。 這樣,能夠便捷地將數組中的一個或多個連續元素換成其他的元素。
function htmlColorNames(arr) {
arr.splice(0, 2, "DarkSalmon", "BlanchedAlmond");
return arr;
}
console.log(htmlColorNames(['DarkGoldenRod', 'WhiteSmoke', 'LavenderBlush', 'PaleTurquoise', 'FireBrick']));
slice()
slice()
不會修改數組,而是會複製,或者說提取(extract)給定數量的元素到一個新數組。 slice()
只接收 2 個輸入參數:第一個是開始提取元素的位置(索引),第二個是提取元素的結束位置(索引)。 提取的元素中不包括第二個參數所對應的元素。
function forecast(arr) {
return arr.slice(2, 4);
}
console.log(forecast(['cold', 'rainy', 'warm', 'sunny', 'cool', 'thunderstorms']));
展開運算符...
展開運算符複製數組
let thisArray = [true, true, undefined, false, null];
let thatArray = [...thisArray];
展開運算符合併數組
展開語法(spread)的另一個重要用途是合併數組,或者將某個數組的所有元素插入到另一個數組的任意位置。
let thisArray = ['sage', 'rosemary', 'parsley', 'thyme'];
let thatArray = ['basil', 'cilantro', ...thisArray, 'coriander'];
forEach
forEach
方法接收一個函數,該函數會在每一個數組項中執行。該函數的第一個參數是當前數組元素本身,第二個參數是索引(可選參數)。
const fruits = ['kiwi','mango','apple','pear'];
function appendIndex(fruit,index) {
console.log(`${index}.${fruit}`)
}
fruits.forEach(appendIndex);
通常會把 forEach
接收的函數體直接寫入函數調用中:
const fruits = ['kiwi','mango','apple','pear'];
fruits.forEach(function(fruit, index) {
console.log(`${index}.${fruit}`)
})
filter()
類似 forEach
,該方法用於每一個數組項,它會根據傳入函數返回一個過濾後的數組:
const nums = [100,200,30,40,10,0];
nums.filter(function (item) {
return item > 100;
})
// [200]
map()
該方法根據傳入的函數,把某數組的值按照函數規則映射(map)到另一數組:
[0,10,20,30].map(function (num) {
return num ** 2;
}) // [0, 100, 400, 900]
對象 Object
對象(object)本質上是鍵值對(key-value pair)的集合。 或者說,一系列被映射到唯一標識符的數據就是對象;習慣上,唯一標識符叫做屬性(property)或者鍵(key);數據叫做值(value)。
JS 中常用對象字面量語法 {}
來創建一個對象。
var user = {};
也可以把屬性和值以鍵值對的形式直接聲明來創建對象:
const myDog = {
"name": "Good",
"legs": 4,
"tails": 1,
"friends": ["code", "fads"]
};
對象和arrays
類似,區別在於數組使用索引來訪問和修改數據,而對象中數據是通過屬性
訪問的。
對象非常適合用來存儲結構化數據。屬性都存儲為字元串,也可以使用數字作為屬性。甚至可以省略單字字元串屬性中的引號。
然而,如果對象有非字元串屬性的話,JavaScript 會自動將它們轉為字元串。
in
JavaScript 提供了兩種不同的方式來檢查對象是否有某個屬性: 一個是通過 hasOwnProperty()
方法,另一個是使用 in
關鍵字。
users.hasOwnProperty('Alan'); // true
'Alan' in users; // true
for ... in 遍歷對象
對象是不可迭代的,所以不能直接使用 for
和 for-of
迴圈。
const car = {
speed: 100,
color: 'blue'
}
for (prop of car) {
console.log(prop);
}
// Uncaught TypeError: car is not iterable
遍歷對象中的所有屬性, 只需要使用 JavaScript 中的 for...in 語句即可。
for-in
對象遍歷對象和其原型的屬性;for-of
僅遍歷對象自身的屬性。
let car = {
speed: 100,
engine: 'true'
}
let car2 = Object.create(car);
for (prop of car2) { console.log(prop); } // Uncaught TypeError: car2 is not iterable
for (prop in car2) {
console.log(prop);
} // color speed engine 順序不固定
for (key of Object.keys(car2)) {
console.log(key);
} // color
註意:對象中的鍵是無序的,這與數組不同。 因此,一個對象中某個屬性的位置,或者說它出現的相對順序,在引用或訪問該屬性時是不確定的。
for (let user in users) {
console.log(user);
}
Object.keys()
給 Object.keys()
方法傳入一個對象作為參數,來生成包含對象所有鍵的數組。 這會返回一個由對象中所有屬性(字元串)組成的數組。 需要註意的是,數組中元素的順序是不確定的。
let users = {
Alan: {
age: 27,
online: false
},
Jeff: {
age: 32,
online: true
},
Sarah: {
age: 48,
online: false
},
Ryan: {
age: 19,
online: true
}
};
function getArrayOfUsers(obj) {
return Object.keys(obj);
}
console.log(getArrayOfUsers(users));
// [ 'Alan', 'Jeff', 'Sarah', 'Ryan' ]
遍歷對象中的屬性和值:
var clothingItem = {
price: 50,
color: 'beige',
material: 'cotton',
season: 'autumn'
}
for (key of Object.keys(clothingItem)) {
console.log(keys, ":", clothingItem[key]);
}
Object.values()
給 Object.values()
方法傳入一個對象作為參數,來生成包含對象所有值的數組。 這會返回一個由對象中所有屬性的值組成的數組。
const car3 = {
speed: 300,
color: 'yellow'
}
console.log(Object.values(car3)); // [300,'yellow']
Object.entries()
給 Object.entries()
方法傳入一個對象作為參數,來生成包含對象所有鍵值對的數組。
const car4 = {
speed: 400,
color: 'magenta'
}
console.log(Object.entries(car4)); // [ ['speed', 400], ['color', 'magenta'] ]
訪問屬性 Access Property
訪問對象屬性有兩種方式:點號表示法(.
)和方括弧表示法([]
)
點號訪問 Dot Notation
如果提前知道要訪問的屬性名,使用點號表示法是最方便的。
const testObj = {
"hat": "ballcap",
"shirt": "jersey",
"shoes": "cleats"
};
const hatValue = testObj.hat; // ballcap
const shirtValue = testObj.shirt; // jersey
方括弧訪問 Bracket Notation
訪問對象屬性的第二種方式是方括弧表示法([]
)。這種方法需要把屬性作為字元串寫入方括弧內。如果要訪問的屬性名中包含空格,就必須使用方括弧表示法來獲取它的屬性值。
const testObj = {
"an entree": "hamburger",
"my side": "veggies",
"the drink": "water"
};
const entreeValue = testObj["an entree"];
const drinkValue = testObj["the drink"];
最後,方括弧訪問比點號訪問的優勢是:可以計算表達式。
var arrOfKeys = ['speed', 'altitude', 'color'];
var drone = {
speed: 100,
altitude: 200,
color: 'red'
}
for (var i = 0; i < arrOfKeys.length; i++) {
console.log(drone[arrOfkeys[i]]);
}
/*
100
200
red
*/
變數訪問
還可以訪問對象上作為變數值存儲的屬性。 當需要遍歷對象的所有屬性,或者根據一個變數的值查找對應的屬性值時,這種寫法尤其適用。
const dogs = {
Fido: "Mutt",
Hunter: "Doberman",
Snoopie: "Beagle"
};
const myDog = "Hunter";
const myBreed = dogs[myDog];
console.log(myBreed); // Doberman
使用這一概念的另一種情況是:屬性的名字是在程式運行期間動態收集得到的。
const someObj = {
propName: "John"
};
function propPrefix(str) {
const s = "prop";
return s + str;
}
const someProp = propPrefix("Name");
console.log(someObj[someProp]);
註意,當使用變數名訪問屬性時,沒有 使用引號包裹它,因為使用的是變數的值,而不是變數的名字。
const testObj = {
12: "Namath",
16: "Montana",
19: "Unitas"
};
const playerNumber = 16;
const player = testObj[playerNumber]; // Montana
嵌套訪問
通過連續使用點號表示法和方括弧表示法來訪問對象的嵌套屬性。
const myStorage = {
"car": {
"inside": {
"glove box": "maps",
"passenger seat": "crumbs"
},
"outside": {
"trunk": "jack"
}
}
};
const gloveBoxContents = myStorage.car.inside["glove box"]; // maps
更改屬性 Update
創建了 JavaScript 對象後,可以隨時更新它的屬性。 使用點或中括弧操作符來更新。
const myDog = {
"name": "Coder",
"legs": 4,
"tails": 1,
"friends": ["freeCodeCamp Campers"]
};
myDog["name"] = "Happy Coder";
添加屬性 Add
使用點號來更新,給 JavaScript 對象添加屬性。
可以給對象添加多種數據類型的屬性,包括函數;如果添加了函數屬性,就稱為“方法”。
const myDog = {
"name": "Happy Coder",
"legs": 4,
"tails": 1,
"friends": ["freeCodeCamp Campers"]
};
myDog.bark = "woof";
myDog.call = function() {
console.log('hello');
}
刪除屬性 Delete
可以使用 delete
刪除對象的屬性
const myDog = {
"name": "Happy Coder",
"legs": 4,
"tails": 1,
"friends": ["freeCodeCamp Campers"],
"bark": "woof"
};
delete myDog.tails;
檢查對象屬性 Test
用對象的 .hasOwnProperty(propname)
方法來檢查對象是否有指定的屬性。 .hasOwnProperty()
找到該屬性時返回 true
,找不到該屬性時返回 false
。
obj.hasOwnProperty(check);
複雜對象 Complex Object
提示:數組中有多個 JSON 對象的時候,對象與對象之間要用逗號隔開。
const myMusic = [
{
"artist": "Billy Joel",
"title": "Piano Man",
"release_year": 1973,
"formats": [
"CD",
"8T",
"LP"
],
"gold": true
},
{
"artist": "Mitchell",
"title": "Cocomo",
"release_year": 1900,
"formats": [
"fds",
"Fsdf"
]
}
];
遞歸 Recursion
遞歸是函數調用自身的操作。
function sum(arr, n) {
if (n <= 0) return 0;
else return sum(arr, n - 1) + arr[n-1];
}
Math 庫
常用的常量
- PI 值:
Math.PI
- 歐拉數 Euler 常量:
Math.E
- 2 的自然對數:
Math.LN2
舍入方法
Math.ceil()
無論小數部分如何,向上舍入到最接近的整數Math.floor()
無論小數部分如何,向下捨去到最接近的整數Math.round()
如果小數部分大於.5
,向上舍入到最接近的整數 ,否則向下捨去最接近整數Math.trunc()
去掉小數部分,僅留下整數部分
console.log(Math.ceil(2.3)); // 3
console.log(Math.ceil(2.7)); // 3
console.log(Math.floor(2.3)); // 2
console.log(Math.floor(2.7)); // 2
console.log(Math.round(2.3)); // 2
console.log(Math.round(2.7)); // 3
console.log(Math.trunc(2.3)); // 2
console.log(Math.trunc(2.7)); // 2
隨機分數 Random
隨機數非常適合用來創建隨機行為。
在 JavaScript 中,可以用 Math.random()
生成一個在0
(包括 0)到 1
(不包括 1)之間的隨機小數。
function randomFraction() {
return Math.random();
}
隨機整數
- 用
Math.random()
生成一個隨機小數。 - 把這個隨機小數乘以
20
。 - 用
Math.floor()
向下取整,獲得它最近的整數。
記住 Math.random()
永遠不會返回 1
。同時因為是在向下取整,所以最終獲得的結果不可能有 20
。 這確保了我們獲得了一個在 0
到 19
之間的整數。
function randomWholeNum() {
return Math.floor(Math.random() * 10);
}
生成某個範圍內的數字
需要定義一個最小值 min
和一個最大值 max
。
function randomRange(myMin, myMax) {
return Math.floor(Math.random() * (myMax - myMin + 1)) + myMin;
}
parseInt
parseInt()
函數解析一個字元串返回一個整數。
如果字元串中的第一個字元不能轉換為數字,則返回 NaN
。
function convertToInteger(str) {
return parseInt(str);
}
convertToInteger("56");
它還可以傳入第二個參數,指定了字元串中數字的基數。 基數可以是 2 到 36 之間的整數。
parseInt(string, radix);
function convertToInteger(str) {
return parseInt(str, 2);
}
convertToInteger("10011");
數學計算方法 Arithmetic and calculus
- 冪運算:
Math.pow()
- 開算術平方根:
Math.sqrt()
- 開立方根:
Math.cbrt()
- 取絕對值:
Math.abs()
- 取對數:
Math.log()
Math.log2()
Math.log10()
- 取最值:
Math.min()
Math.max()
- 三角(Trigonometric)計算:
Math.sin()
Math.cos()
Math.tan()
Math.pow(2,3)
8
Math.sqrt(4)
2
Math.cbrt(8)
2
Math.abs(-2)
2
Math.log(4)
1.3862943611198906
Math.log2(4)
2
Math.log10(100)
2
Math.log(2.7)
0.9932517730102834
Math.sin(4/5)
0.7173560908995228
Math.cos(4/5)
0.6967067093471654
Math.tan(4/5)
1.0296385570503641