a
、b
為 fun1()
的參數c
、d
為 fun1()
的引數( 實際引用進來的 )function fun1 (a, b) {
return a+b;
}
var c = 10;
var d = 20;
console.log( fun1(c,d) );
fun2()
也可以當作引數傳入fun1()
當作參數。
以下例子中,fun1()
的參數 newFunction
其實傳入的就是 fun2()
。
function fun1(i, newFunction) { // newFunction 為 fun1() 的參數
return i + newFunction;
}
function fun2(x) {
return x * 2;
}
console.log(fun1(5, fun2(10))); // fun2() 為 fun1() 的引數
以下例子將陣列 [1, 2, 3]
傳入 transform()
,目的是回傳兩倍 & 三倍的陣列值。
function transform(arr, transformFunction) {
var result = [];
for (var i=0; i<arr.length; i++) {
result.push(transformFunction(arr[i]));
}
return result;
}
function double(x) {
return x*2;
}
function triple(x) {
return x*3;
}
console.log(transform([1,2,3], double)); // [2, 4, 6]
console.log(transform([1,2,3], triple)); // [3, 6, 9]
依照上面的例子,也可以將函式 double()
跟 triple()
改寫成 匿名函式 Anonymous Function
(函式內容一樣,只是沒有名字)
function transform(arr, transformFunction) {
var result = [];
for (var i=0; i<arr.length; i++) {
result.push(transformFunction(arr[i]));
}
return result;
}
console.log(transform([1,2,3], function(x){ return x*2 })); // [2, 4, 6]
console.log(transform([1,2,3], function(x){ return x*3 })); // [3, 6, 9]
有關 Function 的宣告方式其實還有另一種,更詳細的可以參考以前筆記:Javascript大全 - 06 函式(一) 函式的定義方法,裡面有個經典案例去說明 JavaScript 對於不同的宣告方式會造成的不同編譯順序結果。
又回到那個 pass by value 還是 pass by reference 還是 pass by address 還是 pass by sharing…無窮迴圈。 這大概是每隔一陣子就要複習一次,陷入漫長的查資料地獄,發現每個人說得好像都有點道理,開始進入越查越不懂的恐怖循環裡。
而 Huli 分享了他之前研究此問題的過程,連結在此:深入探討 JavaScript 中的參數傳遞:call by value 還是 reference?
幸好之前有留下 CS50 對 C 語言中指標的筆記,所以那篇文章我居然看得懂(開心)!推薦大家認真看完,文章也說明了此問題在其他語言( Java, C )的情形,我甚至有點像坐在榕樹下聽說書人講故事的感覺 (?),我直接引用結尾的一斷話:
別忘了,重點其實不在這個,而是搞清楚到底參數在操作的時候會有怎樣的行為。你要知道 JavaScript 傳 object 進去的時候,可以更改原本物件的值,但重新賦值並不會影響到外部的 object。只要知道這一點,其他的我覺得都沒那麼重要了。
看到這段話有「啊~我得到救贖了」的感覺,所以我決定不再去追根究底名詞背後的定義是什麼,我想我只要了解其中的行為,比該如何定義此行為還重要。
概念有點像之前看到一個網路上蠻有名的昆蟲教授,他說:「 要怎樣才算是瞭解一個昆蟲呢?講得出他的中英文學名、知道介門綱目科屬種分在哪一類?還是說得出他的生物特性、了解什麼環境或因素會引發什麼特殊行為。 」( 原文找不到,其實應該不是這麼說的,我只是憑印象說明 )
原始型別 num
、string
、boolean
都是傳值 pass by value,原來的 num1
、num2
並沒有被更改。
function swap (a, b){
var temp = a;
a = b;
b = temp;
}
var num1 = 10;
var num2 = 5;
swap(num1, num2);
console.log(num1, num2); // 印出 10, 5
而物件 object
則是傳分享 pass by sharing,原來的 obj1
被更改到了
function swap (obj){
var temp = obj.a;
obj.a = obj.b;
obj.b = temp;
}
var obj1 = {
a: 10,
b: 5
}
swap(obj1);
console.log(obj1); // 印出 { a: 5, b:10 }
而又如果物件 object
本身被重新賦值,原來的 obj1
就不會收到影響。
function double(obj) {
obj = {
a: obj.a * 2
}
}
var obj1 = { a: 10 };
double(obj1);
console.log(obj1); // 印出 { a: 10 }
不同的程式語言總會有些自己的內建函式,目的在於簡化一些常用的功能,總之就是有人貼心造好的輪子,就不用再自己造了。
Math.ceil()
: 無條件進位Math.floor()
: 無條件捨去Math.round()
: 四捨五入Math.random
: 產生 0 ~ 1 的隨機數( 不包括 1 )Math.max(num1, num2, num3)
: 丟入一系列數字,回傳最大值
展開運算子 ...
,例如: Max.max(...arr)
Math.min(num1, num2, num3)
: 丟入一系列數字,回傳最小值
Math.max()
Number.MAX_VALUE
: 回傳 JavaScript 能存的最大數字。Number.toFixed(x)
: 取到小數點後第 x 位數( 無條件捨去 )
Math.sqrt()
: 開根號Math.log()
: 對數Math.pow(x, y)
: 次方運算
參考資料:
字串轉數字:
parseInt(<string>, x)
Number(<string>)
console.log(parseInt('50', 10)) // 50,10 代表 10 進位
console.log(Number('50')) // 50
數字轉字串:
<number>.toString()
<number> + ''
: ( 數字加上空字串 )var num = 10;
console.log(num.toString());
console.log(num+'');
length
: 回傳字串的長度toUpperCase()
: 將字串全部轉為大寫toLowerCase()
: 將字串全部轉為小寫charCodeAt(char)
: 取出字元的 ASCII 碼String.fromCharCode(num)
: 將 ASCII 碼轉成字元indexOf(keyword)
: 找出關鍵字 keyword 有沒有在字串裡
-1
replace(x, y)
: 找的第一個 x
字串,用 y
取代
x
,要用正規表達式 : replace(/x/g ,y)
split(x)
: 分割字串成陣列
x
作為分割字串的參考,回傳陣列trim()
: 去掉前後的空格var name = 'Yakim';
console.log(name.toUpperCase()); // Upper: YAKIM
console.log(name.toLowerCase()); // Lower: yakim
console.log(name.charCodeAt(0)); // code of Y: 89
console.log(name.charCodeAt(1)); // code of a: 97
console.log(String.fromCharCode(97)); // char of 97: a
var name2 = 'Yakim, hahahahaha';
console.log(name2.replace('ha', 'yo')); // Yakim, yohahahaha
// 注意:前面的引數類型不是字串,不用加 ''
console.log(name2.replace(/ha/g, 'yo')); // Yakim, yoyoyoyoyo
console.log(name2.split(',')); // [ 'Yakim', ' hahahahaha' ]
var name3 = ' Yakim ';
console.log(name3.trim()); // Yakim
字串轉陣列:
str.split('')
''
: 把 string
切成 array
陣列轉字串:
arr.join('')
''
: 把 array
轉成 string
這部分先偷懶拿以前筆記來看,不然進度太慢、我要開天窗了啊啊啊啊
重點在於不同函式之間,有會改到原本陣列跟不會改到原本陣列、而回傳一個新陣列或其他變數類型的差別,通常是在於 回傳值也是陣列的情況下,就很有可能會改到陣列本身,聽起來也很合理,因為既然是要對陣列做改變,就直接在陣列本身做操作麻!( 說了通常是因為有例外,例如: slice()
、concat()
)
想要看更詳細的資訊,可以上 MDN - Array 裡面有超詳細的列表:
( 以上內容大部分是 程式導師實驗計畫第三期 的學習筆記,如有錯誤歡迎糾正,非常感謝 🤓 )
Written on April 24th, 2019 by Yakim shu