--- tags: JavaScript,第三章 --- # JavaScript第三章-數組與函數 # 數組 ## 定義 數組裡的每一個數據叫數組元素 數組索引號是從0、1、2、3...這樣算下去的 ``` var arr = new Array(); // 構造函數 var arr = new Array(2); // 數組長度為2,裡面有2個空數組 var arr = new Array(4,5); // 裡面有2個元素,是4和5 console.log(arr); var arr = []; var arr1 = [1, 2, 'pink', true]; ``` 打印數組 ``` console.log(arr1); console.log(arr1[2]); // pink console.log(arr1[4]); // undefined ``` 數組長度 ``` var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; console.log(arr.length); ``` 遍歷數組 ``` var arr = ['red', 'green', 'blue']; for (var i = 0; i < 3; i++) { console.log(arr[i]); } ``` ``` var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; console.log(arr.length); for (var i = 0; i < arr.length; i++) { console.log(arr[i]); } ``` ## 運算 求數組和及平均值 ``` var arr = [2, 6, 1, 7, 4]; var sum = 0; var average = 0; for (i = 0; i < arr.length; i++) { sum += arr[i]; } average = sum / arr.length; console.log(sum, average); ``` 求數組最大值 ``` var arr = [2, 6, 1, 77, 52, 25, 7]; var max = arr[0]; for (var i = 1; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } console.log(max); ``` ## 轉成字符串 ``` var arr = ['red', 'green', 'blue', 'pink']; var str = ''; var sep = '|'; for (var i = 0; i < arr.length; i++) { str += arr[i] + sep; } console.log(str); ``` ## 修改數組 ``` var arr = ['red', 'green', 'blue']; console.log(arr.length); arr.length = 5; console.log(arr); console.log(arr[3]); // undefined console.log(arr[4]); // undefined var arr1 = ['red', 'green', 'blue']; arr1[3] = 'pink'; console.log(arr1); arr1[4] = 'black'; console.log(arr1); arr1[0] = 'yellow'; console.log(arr1); arr1 = '天線寶寶'; console.log(arr1); ``` 存放1~10個值 ``` var arr = []; for (var i = 0; i < 10; i++) { arr[i] = i + 1; } console.log(arr); ``` 篩選大於10的值 ``` var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; var j = 0; for (var i = 0; i < arr.length; i++) { if (arr[i] > 10) { newArr[j] = arr[i]; j++; } } console.log(newArr); ``` ``` var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; for (var i = 0; i < arr.length; i++) { if (arr[i] > 10) { newArr[newArr.length] = arr[i]; } } console.log(newArr); ``` 刪除0元素 ``` var arr = [2, 0, 6, 1, 77, 0, 52, 0, 25, 7]; var newArr = []; for (var i = 0; i < arr.length; i++) { if (arr[i] != 0) { newArr[newArr.length] = arr[i]; } } console.log(newArr); ``` 翻轉數組 ``` var arr = ['red', 'green', 'blue', 'pink', 'purple']; var newArr = []; for (var i = arr.length - 1; i >= 0; i--) { newArr[newArr.length] = arr[i]; } console.log(newArr); ``` ## 冒泡排序 ``` var arr = [5, 4, 3, 2, 1]; for (var i = 0; i < arr.length - 1; i++) { for (var j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } console.log(arr); ``` ``` var arr = [5, 4, 3, 2, 1]; for (var i = 1; i < arr.length; i++) { for (var j = 0; j < arr.length - i; j++) { if (arr[j] > arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } console.log(arr); ``` ``` var arr = [5, 4, 3, 2, 1]; for (var i = arr.length - 1; i > 0; i--) { for (var j = 0; j < i; j++) { if (arr[j] > arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } console.log(arr); ``` # 數組進階 檢測是否為數組 方法一 ``` var arr = []; var obj = {}; console.log(arr instanceof Array); // true console.log(obj instanceof Array); // false ``` 方法二(HTML5才新增的方法) ``` var arr = []; var obj = {}; console.log(Array.isArray(arr)); // true console.log(Array.isArray(obj)); // false ``` 翻轉數組 ``` function reverse(arr) { if (arr instanceof Array) { var newArr = []; for (var i = arr.length - 1; i >= 0; i--) { newArr[newArr.length] = arr[i]; } return newArr; } else { return 'error 正確寫法是[1,2,3]'; } } console.log(reverse([1, 2, 3])); console.log(reverse(1, 2, 3)); ``` ## 增加數組元素 1.push可以在數組末端追加新元素 2.push()裡面直接寫數組元素 3.arr.push()返回的是新數組長度 4.使用console.log的同時又會再次執行添加的動作 ``` var arr = [1, 2, 3]; //arr.push(4, 5, '安安'); console.log(arr); console.log(arr.push(4, 5, '安安')); console.log(arr); ``` 1.unshift可以在數組最前面追加新元素 ``` arr.unshift(-1, 0); console.log(arr); ``` ## 刪除數組元素 1.pop()可以刪除數組最後一個元素,一次只能刪除1個 2.pop()沒有參數 3.pop完之後,返回的是刪除的那個元素 4.使用console.log的同時又會再次執行刪除的動作 ``` var arr = [1, 2, 3, 4, 5]; arr.pop(); console.log(arr); ``` 1.shift()可以刪除數組第一個元素,一次只能刪除1個 2.shift()沒有參數 3.shift完之後,返回的是刪除的那個元素 4.使用console.log的同時又會再次執行刪除的動作 ``` var arr = [1, 2, 3, 4, 5]; arr.pop(); console.log(arr); arr.shift(); console.log(arr); ``` ## 篩選數組 ``` var arr = [1500, 1200, 2000, 2100, 1800]; var newArr = []; for (i = 0; i < arr.length; i++) { if (arr[i] < 2000) { // newArr[newArr.length]=arr[i] newArr.push(arr[i]); } } console.log(newArr); ``` ## 進階翻轉、進階冒泡 ``` var arr = [1, 2, 3, 4, 5]; arr.reverse(); console.log(arr); ``` ``` var arr1 = [3, 5, 7, 1]; arr1.sort(); console.log(arr1); var arr2 = [13, 4, 77, 1, 7]; arr2.sort(); console.log(arr2); // 亂七八糟 arr2.sort(function (a, b) { return a - b; // 升序 }); console.log(arr2); arr2.sort(function (a, b) { return b - a; // 降序 }); console.log(arr2); ``` ## 數組元素索引 複習:數組索引號是0、1、2、3、4排下去的 indexOf可返回數組的索引號 1.只返回第一個符合條件的索引號 2.找不到該元素就返回-1 lastIndexOf 1.從後面數來返回第一個符合條件的索引號 2.找不到該元素就返回-1 ``` var arr = ['red', 'green', 'blue', 'pink', 'blue']; console.log(arr.indexOf('blue')); // 2 console.log(arr.lastIndexOf('blue')); // 4 console.log(arr.indexOf('yellow')); // -1 console.log(arr.lastIndexOf('yellow')); // -1 ``` ### 數組去重 ``` function unique(arr) { var newArr = []; for (var i = 0; i < arr.length; i++) { if (newArr.indexOf(arr[i]) === -1) { newArr.push(arr[i]); } } return newArr; } var demo = unique(['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b']); console.log(demo); ``` ## 數組轉字符串 toString() join('分隔符') ``` var arr = [1, 2, 3]; console.log(arr.toString()); var arr1 = ['green', 'blue', 'pink']; console.log(arr1.join()); console.log(arr1.join('-')); console.log(arr1.join('&')); ``` :::danger concat() slice() splice() ::: # 函數 ## 定義 ``` function 函數名(形參1,形參2,...) { 內容 } 函數名(實參1,實參2,...); ``` ``` function sayHi(){ console.log('hi~'); } sayHi(); ``` 函數就是封裝了一段可以被重複執行的代碼塊 ``` function getSum(num1, num2) { var sum = 0; for (var i = num1; i <= num2; i++) { sum += i; } console.log(sum); } getSum(1, 100); getSum(10, 50); getSum(1, 1000); ``` ## 形參實參匹配問題 ``` function getSum(num1, num2) { console.log(num1 + num2); } getSum(1, 2); //3 getSum(1, 2, 3); //3 getSum(1); //NaN // 多餘的形參定義為undefined,最終結果為NaN ``` ## return ``` function getResult() { console.log(123); return 666; } function noResult() { console.log(777); } console.log(getResult()); console.log(noResult()); ``` ``` function getSum(num1, num2) { return num1 + num2; } console.log(getSum(1,2)); ``` 函數找最大值 ``` function getMax(num1, num2) { if (num1 > num2) { return num1; } else { return num2; } } console.log(getMax(1, 3)); console.log(getMax(11, 3)); ``` 函數找最大值簡易寫法 ``` function getMax(num1, num2) { return num1 > num2 ? num1 : num2; } console.log(getMax(1, 3)); console.log(getMax(11, 3)); ``` 函數找數組最大值 ``` function getArrMax(arr) { var max = arr[0]; for (var i = 1; i <= arr.length; i++) { if (arr[i] > max) { max = arr[i]; } } return max; } // getArrMax([5,2,99,101,67,77]); var re = getArrMax([5, 2, 99, 101, 67, 77]); console.log(re); ``` return終止函數 ``` function getSum(num1, num2) { return num1 + num2; alert('我是不會被執行的哦'); } console.log(getSum(1, 2)); getSum(1, 2); ``` return只能返回一個值 ``` function fn(num1, num2) { return num1, num2; } console.log(fn(1, 2)); //返回結果是最後一個值 ``` return一個數組 ``` function getResult(num1, num2) { return [num1 + num2, num1 - num2, num1 * num2, num1 / num2]; } var re = getResult(1, 2); console.log(re); ``` ## 終止指令比較 break 結束當前循環體 continue 跳出本次循環,繼續下次循環 return 1.退出循環 2.返回一個值 3.讓後面程式碼不執行 ## arguments 偽數組不是真正意義的數組 只有函數才有arguments對象 1.具有length屬性 2.按照索引的方式進行存儲 3.沒有真正數組的一些方法pop() push() 等等 ``` function fn() { console.log(arguments); //裡面存儲所有傳遞過來的實參 console.log(arguments.length); console.log(arguments[2]); for (var i = 0; i < arguments.length; i++) { console.log(arguments[i]); } } fn(1, 2, 3); fn(1, 2, 3, 4, 5); ``` 求任意個數的最大值 ``` function getMax() { var max = arguments[0]; for (var i = 1; i < arguments.length; i++) { if (arguments[i] > max) { max = arguments[i]; } } return max; } console.log(getMax(1, 2, 3)); console.log(getMax(1, 2, 3, 4, 5)); console.log(getMax(11, 2, 33, 444, 100)); ``` 用函數翻轉數組 ``` function reverse(arr) { var newArr = []; for (var i = arr.length - 1; i >= 0; i--) { newArr[newArr.length] = arr[i]; } return newArr; } var arr1 = reverse([1, 2, 3, 4, 5]); console.log(arr1); var arr2 = reverse(['red', 'pink', 'blue']); console.log(arr2); ``` 封裝冒泡排序 ``` function sort(arr) { for (var i = 0; i < arr.length - 1; i++) { for (var j = 0; j < arr.length - i - 1; j++) { if (arr[j] > arr[j + 1]) { var temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } return arr; } var arr1 = sort([5, 4, 3, 2, 1]); console.log(arr1); ``` 函數判斷閏年 ``` function isRunYear(year) { var flag = false; if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { flag = true; } return flag; } console.log(isRunYear(2000)); console.log(isRunYear(1999)); ``` 函數相互調用 ``` function fn1() { console.log(111); fn2(); console.log('fn1'); } function fn2() { console.log(222); console.log('fn2'); } fn1(); fn2(); ``` 輸出2月份天數 ``` function isRunYear(year) { var flag = false; if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) { flag = true; } return flag; } function backDay() { var year = prompt('請輸入年份'); if (isRunYear(year)) { alert('今年有29天'); } else { alert('今年有28天'); } } backDay(); ``` ## 函數兩種聲明方式 1.自定義函數(命名函數) ``` function fn() { } fn(); ``` 2.函數表達式(匿名函數) fun是變量名,不是函數名 ``` var fun = function (aru) { console.log('我是函數表達式'); console.log(aru); } fun('pink'); ``` # 作用域 1.js作用域(es6)之前:全局作用域 局部作用域 2.全局作用域:整個script標籤,或是單獨一個js文件 注意:如果在函數內部,沒有聲明直接賦值的變量也是全局變量 3.局部作用域:在函數內部就是局部作用域,代碼的名字只能在函數內部起作用 注意:函數的形參可以當成局部變量 4.執行效率 (1)全局變量只有瀏覽器關閉才會銷毀,比較佔內存 (2)局部變量當程序執行完畢就會銷毀 ``` var num = 10; console.log(num); function fn() { var num = 20; console.log(num); } fn(); ``` ``` function fun() { var num1 = 10; num2 = 20; } fun(); // console.log(num1); console.log(num2); ``` JavaScript舊版沒有塊級作用域 在es6才新增塊級作用域 塊級作用域{} if{} for{} ## 作用域鍊 ``` var num = 10; var num1 = 100; function fn() { //外部函數 var num = 20; function fun() { //內部函數 console.log(num); console.log(num1); } fun(); } fn(); ``` # 預解析 問題一 ``` console.log(num); // 報錯 ``` 問題二 ``` console.log(num); var num = 10; // undefined ``` 問題三 ``` function fn() { console.log(11); } fn(); // 11 ``` ``` fn(); function fn() { console.log(11); } // 11 ``` 問題四 ``` var fun = function () { console.log(22); }; fun(); // 22 ``` ``` fun(); var fun = function () { console.log(22); }; // 報錯 ``` ## js引擎 預解析、代碼執行 (1)var和function提升到當前作用域最上面 (2)預解析完再執行代碼 var預解析:只預解析聲明,不賦值 function預解析:只預解析具名函數,不提升匿名函數 ## 案例一 ``` var num = 10; fun(); function fun() { console.log(num); var num = 20; } ``` ``` var num; function fun() { var num; console.log(num); num = 20; } num = 10; fun(); ``` ## 案例二 ``` var num = 10; function fn() { console.log(num); var num = 20; console.log(num); } fn(); ``` ``` var num; function fn() { var num; console.log(num); num = 20; console.log(num); } num = 10; fn(); ``` ## 案例三 ``` var a = 18; f1(); function f1() { var b = 9; console.log(a); console.log(b); var a = '123'; } ``` ``` var a; function f1() { var b; var a; b = 9; console.log(a); console.log(b); a = '123'; } a = 18; f1(); ``` ## 案例四 ``` f1(); console.log(c); console.log(b); console.log(a); function f1() { var a = b = c = 9; console.log(a); console.log(b); console.log(c); } ``` ``` function f1() { var a; a = b = c = 9; console.log(a); // 9 console.log(b); // 9 console.log(c); // 9 } f1(); console.log(c); // 9 console.log(b); // 9 console.log(a); // 報錯 ```