Skip to content
坑坑洞洞
Github

給自己看的 JavaScript 基礎 - 迴圈、函式及其他觀念

程式導師計劃, coding 筆記, JavaScript10 min read

更新紀錄: 2020/07/01 一小時挑戰 2020/07/02 一小時挑戰之延長賽

迴圈

迴圈可用於處理重複進行的事情,最常見的形式為:

while (條件) {
// 指令
}

因此順序為先檢查條件是否為 true ,若為 true 則進入迴圈執行指令,結束後再回到第一行檢查條件,如此往復。 另一種經典的寫法如下:

for (初始值; 條件; 每圈結束後的指令) {
// 指令
}

例如我想要印出一到十,就可以寫:

for (let i = 1; i <= 10; i++) {
console.log(i);
}

函式

數學上的函式為 f(x) = y ,將 x 輸入進去就可以得到 y 。 JavaScript 中的函式寫法如下:

function 名稱(參數) {
// 指令
return 回傳值; //若沒設定則自動回傳 undefined
}

其中可以放其他的 function。若要查看函式的特性可以這樣:

function hi() {
return 'hello';
}
console.log(hi); // [function: hi]
console.log(hi()); // 'hello'

函式也不一定要取名字,例如:

function transform(arr, func) {
var result = [];
for (let i = 0; i < arr.length; i++) {
result = func(arr[i]);
}
return result;
}
console.log(
transform([1, 3, 5], function (x) {
return x * 2;
})
); //[2, 6, 10]

參數和引數

function add(a, b) {
return a + b;
}
console.log(add(2, 3)); // 5

上面例子中, a 和 b 就是函式的 參數 ,而 2 和 3 則是 引數。可以在函式中使用 console.log(arguments) 查看引數。引數會以物件形式出現,例如 {"0": 2, "1": 3}

函式的特性

函式再讀取引數時,對電腦來說是先複製一份才執行,因此所有變動都不會影響到外面。例如:

var n = 10;
function double(x) {
return x * 2;
}
double(n); // 20
console.log(n); // 10

不過物件和陣列可能會改變,和記憶體位置有關,可看本篇文章最後的「其他觀念」。

return

如果不需要知道結果(比如說只是要 console.log 某個東西)可以不用 return,此時會預設 return undefine 。 另外, return 後的東西都不會執行。

內建函式

數字相關

寫法用途範例
Number(str)字串轉數字var num = Number('11') //11
parseInt(str, 進位制)字串轉整數,通常使用十進位var num = parseInt(2, 10) //10
parseFloat(str)字串轉小數var num = parseFloat('3.2') //3.2
num.toFixed(幾位)取到小數點後幾位四捨五入var num = 2.78.toFixed(1) //2.8
Number.MAX_VALUE顯示 JavaScript 能記憶最大的數,再大會不精準var max = Number.MAX_VALUE //1.7976931348623157e+308
Number.MIN_VALUE顯示 JavaScript 能記憶最小的數,再小會不精準var min = Number.MIN_VALUE //5e-324
Math.PI圓周率var pi = Math.PI //3.141592653589793
Math.ceil(num)無條件進位var ceil = Math.ceil(10.1) //11
Math.floor(num)無條件捨去var floor = Math.floor(10.1) //10
Math.round(num)四捨五入法var round = Math.round(10.1) //10
Math.sqrt(num)開根號var sqrt = Math.sqrt(144) //12
Math.pow(num, times)num 的 times 次方var pow = Math.pow(3, 3) //27
Math.random()隨機生產從 0 到 1 的數字(包含 0 但不含 1)var pow = Math.random() //0.84

以上常數皆用大寫表示。 數字轉字串有兩種做法:

var a = 12;
a = a.toString(); //'12'
var b = 43;
b = b + ''; //'43',因為字串加數字等於字串

字串相關

大小寫

概念:以下所有的位置都是由 0 開始計算,而非 1 。
str.toUpperCase(a):將 str 的第 a 個字(從零開始)轉為大寫。
str.toLowerCase(a):將 str 的第 a 個字(從零開始)轉為小寫。

var a = 'hello'.toUpperCase(2); //'heLlo'
var b = 'HELLO'.toUpperCase(0); //'hELLO'
ASCII

ASCII 是將字串用數字存起來的形式,每個字母都可以對應到一個數字,且大小寫不同,例如 A 對應到 65 、 B 對應到 66 、 a 對應到 97 。
str.charCodeAt(a):得到字串第 a 位置的 ASCII。
String.fromCharCode(num):得到數字 num 在 ASCII 上對應到的字母。
運用 ASCII 可將數字轉大小寫,例如:

var str = 'a';
var temp = str.charCodeAt(a); //97
temp -= 32; //65
str = String.fromCharCode(temp); //'A'

若將數字比大小,則是轉換為 ASCII 再比。因為字母的 ASCII 有連貫,因此若要測試字母是否為大寫,可以用 str >= 'A' && str <= 'Z'

搜尋和取代

str.indexOf('key') : key 第一個字在 str 的位置。若有兩個以上,則回傳最前面的。若找不到 key,會回傳負數。
str.replace('key', new):將 str 中的 key 換成 new。一樣只會換第一個,若想要全部替換可使用正規表達式。詳細可參考 MDN

var a = 'hello'.indexOf('el'); // 1
var b = 'hello'.replace('l', 'i'); // 'hello'
其他

str.spilt(a):以 a 為標準將字串拆開,並變成陣列。
str.trim():去掉字串前後的空格。
str[i]:叫出字串位置 i 的字。

var a = 'hello world';
var spilt = a.spilt(' '); // ['hello', 'world']
var b = a[4]; //'o'

陣列相關

arr.join(a):用 a 將陣列接起來,回傳字串。

var a = ['hello', 'i', 'am'];
a = a.join('!'); // 'hello!i!am'

arr.map(function):讓串列中每個元素都跑過函式。

var a = [1, 3, 5, 7, 9];
a = a.map(function (i) {
return i + 1;
});
console.log(a); // [2, 4, 6, 8, 10]

arr.filter(function):串列通過函式回傳 true 的會留下。

var a = [1, 2, 3, 4, 5];
a = a.filter(function (i) {
return i % 2 === 0;
});
console.log(a); // [2, 4]

只要還是陣列, .map 和 .filter 可以一起使用,也可以無限往後加。 arr.slice(a, b): 回傳陣列的第 a 個元素到第 b-1 個數。

var a = [1, 2, 3, 4, 5];
a = a.slice(2, 4); //[3, 4]

arr.splice(start, remove, new):在第 start 的位置,刪除 remove 個元素,並插入 new 為新的元素。(會改變陣列本身)

var a = [1, 2, 3, 4, 5];
a.splice(1, 0, 9); //[1, 9, 2, 3, 4, 5]
a.splice(3, 1, 'hi'); //[1, 9, 2, 'hi', 4, 5]

arr.sort(function):將陣列的元素由小排到大。

var a = ['apple', 'zipper', 'cute'];
a.sort(); //['apple', 'cute', 'zipper']
var b = [22, 18, 9];
b.sort(); //[18, 22, 9]

上面數字的排序只是看最前面的數字,要真正幫數字排序可使用函數。概念為若回傳值小於等於 0 不調換,但若 > 0 則互換。詳細可參考MDN因此若要由小排到大,可用:

b.sort(function (a, b) {
return a - b;
});

此時若要由小排到大,改成 b - a 即可。 arr.reduce(function):可用於累積加總,例如求陣列總和:

var a = [22, 18, 9];
var sum = a.reduce(function (acc, cur) {
return acc + cur;
}, 0);

其實就是將上次執行的成果(如 22 + 18)存到 acc ,再執行下一個( acc + 9)。這個方法可以避免外面再多存一個初始值。

其他觀念

詳細觀念可參考:
從博物館寄物櫃理解變數儲存模型
Immutability 為何重要?淺談 immutable.js 和 seamless-immutable

物件在記憶體內儲存的方式

可先看看這幾題:

var a = [] === [];
var b = [1] === [1];
var c = {} === {};
var d = { a: 1 } === { a: 1 };

以上四個全部都是 false!
因為物件儲存的方式是先將物件放再記憶體位置內,再紀錄記憶體位置。左邊的 [] 和右邊的 [] 其實是存在不同記憶體位置,等式判斷時是看記憶體位置,因此才會得出 false。
另外也有這種狀況:

var a = [1];
var b = a;
b[1] = 2;
console.log(a, b); // [1,2], [1,2]

此時因為 b 的記憶體位置直接對應到 a 的,因此修改到 b 的內容就會修改到 a。但如果:

var a = [1];
var b = a;
b = [1, 2];
console.log(a, b); // [1], [1,2]

上面直接將 b 指定到新的記憶體位置,因此 a 不會受到影響。

Immutable 不可變

不可變是指在創建變數、賦值後便不可改變,若對其有任何變更(例如:新增、修改、刪除),就會回傳一個新值。例如:

var a = 'hello'; //放在記憶體 0x01
a = 'change'; //開新的記憶體 0x02
a.toUpperCase(0); // 只有 return 沒有改變 a
console.log(a); // 'change'

所有的字串都是不可變的,有些內建函式可以改變陣列,因此使用前可先看 說明書 才不會產生奇怪的 bug。

心得

最後花了總共三個小時才完成這篇(躺)果然記筆記吃力不討好,不過相信未來的我會感謝自己的(?)