---
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); // 報錯
```