JavaScript 入門基礎 03
JavaScript構造函數
JavaScript 創建對象的方式有兩種,一種是通過直接量的形式來創建對象,另外一種則是通過構造函數的形式來創建對象。
簡單的說,構造函數就是在創建對象時通過new關鍵字調用的函數,我們稱之為構造函數。
通常情況下構造函數的首字母應該大寫。
我們說在js當中,一切皆對象。而所有的對象都存在有一個constructor屬性,通過這個屬性,我們可以查看到每一個對象
的構造函數。
例如:
var str = 'hello,world!';// 創建一個字符串
// 查看str 的構造函數
console.log(str.constructor); // [Function: String]
在js當中,我們也可以通過構造函數來創建對象。
首先,我們來思考一個問題,我們為什么要使用構造函數來創建一個對象?
我們可以先來假設一種情況,在警局檔案中有6個嫌疑人,現在我們需要來通過
代碼存儲這幾個人的信息,我們如果采用直接量對象的形式來存儲,寫法大體如下:
var p1 = {name: "張三", age: 30, home: "山東"};
var p2 = {name: "李四", age: 50, home: "北京"};
var p3 = {name: "王五", age: 40, home: "上海"};
var p4 = {name: "趙六", age: 20, home: "江蘇"};
var p5 = {name: "周七", age: 40, home: "安徽"};
var p6 = {name: "付八", age: 50, home: "雲南"};
在上面的代碼中,我們每一次都需要創建一個完整的對象,來存儲不同的信息,很大程度上造成了代碼的冗余。
而我們使用構造函數來創建代碼,則可以把相同的內容進行封裝,從而實現代碼的簡化和復用。
例如:
function Criminal(name,age,home){
this.name = name;
this.age = age;
this.home = home;
}
// 存儲數據
var p1 = new Criminal('張三',30,'上海');
var p2 = new Criminal('李四',40,'北京');
var p3 = new Criminal('王五',20,'江蘇');
// ...
在上面的代碼中,我們創建了一個構造函數,並且通過new關鍵字調用構造函數創建了對象。
相比之前的寫法,雖然我們在創建構造函數的時候可能會麻煩一些,但是在創建對象的過程中則變得更加的簡單。
從這一個角度來說,我們之所以使用構造函數,目的就是為了減少代碼的重復書寫,並且提高代碼的復用性。
需要注意的是,我們之所以使用構造函數,是為了減少在使用對象直接量創建對象的時候那些重復編寫的相似的代碼。
通常情況下,構造函數和普通的函數其實看上去很相似,只有在通過
new關鍵字調用的時候,才能確定一個函數到底是不是構造函數。
下面來說下構造函數的執行流程。
首先,我們先來創建一個用於測試的構造函數。
function SayHello(name) {
this.name = name ;
}
var s1 = new SayHello("zhangsan");
當我們通過new關鍵字來創建一個對象的時候,相當於在內存中創建了一塊新的內存空間,標記為SayHello的實例。

在我們的代碼中,this關鍵字其實指向的就是存儲在內存中的這個實例。

So,我們在使用new關鍵字創建對象的實例,實際上每一次調用new關鍵字都相當於在內存中開辟了一塊新的內存空間。
而this也會隨着實例化對象的不同而改變指向。
所以,我們在代碼中,給this添加屬性其實也就相當於給未來的實例添加屬性。
在構造函數的最后,我們再來說下構造函數的返回值。
在普通函數的最后,可以通過return來設置函數的返回值,如果不設置返回值,那么默認返回值為undefined。
但是在構造函數中,如果我們不設置返回值,就將默認返回this。也就是指向內存中實例的那塊內存空間,也就是相當於返回了那段存在
內存空間中的對象。
而如果我們在構造函數中手動的通過return返回一個基本類型的值,那么返回值將不會受到影響,還是this。
例如:
function SayHello(name) {
this.name = name ;
return "hello,world!";
}
var s1 = new SayHello("zhangsan");
console.log(s1); // SayHello { name: 'zhangsan' }
而如果return返回的是一個引用對象類型的數據,那么最終返回的則是對象。
例如:
function SayHello(name) {
this.name = name ;
return {
like:"I like you"
}
}
var s1 = new SayHello("zhangsan");
console.log(s1); // { like: 'I like you' }
上面只是簡單的介紹了一下構造函數,構造函數的使用往往與
原型和原型鏈是分不開的。在后續的博文中會針對原型和原型鏈進行深入的說明,本章只是一個簡單的介紹。
常用事件和事件處理函數
學習js,不僅僅要學習其核心語法,還要學習js所在宿主環境當中的一些api。
例如,當js運行在瀏覽器當中的時候,學習內容應該包括ECMAScript核心語法,DOM文檔對象模型和BOM瀏覽器對象模型。
在DOM當中,存在有很多的事件,通過這些事件,我們能夠很好地監聽用戶在瀏覽器網頁當中的一些動作,並且根據這些動作來設置相關的事件處理函數。
例如用戶在網頁中發生了單擊操作,雙擊操作,按下了鍵盤上的什么按鍵等等。
下面將來簡單的說一些常用的事件,具體的事件講解將在后續的博文中進行更新。
在本段博文中更主要的是來講解事件處理函數的使用。
常用事件:
- 單擊事件 onclick
- 雙擊事件 ondblclick
- 文檔加載事件 onload
- 表單內容更改 onchange
上面列出了四個不同的事件,通過這些事件來說一下事件和事件處理函數。
首先,我們通常情況下使用事件都是具有一定原由的。
例如,我們使用了單擊事件,目的是希望當用戶發生了單擊這個行為后,我們能夠做出什么反應。
我們可以將事件分成三個部分,事件源,事件,以及事件發生后執行的動作。
對應着元素、事件以及事件處理函數。
例如:
按鈕.單擊= function () {事件發生后執行的動作}
例如我們在網頁中有一個按鈕,當用戶點擊按鈕的時候我們讓網頁彈出彈窗,彈出信息為hello,world。
具體代碼可以如下:
// 找到按鈕
var oBtn = document.getElementById('btn');
// 綁定事件
oBtn.onclick = function () { // 事件處理函數
// 當用戶發生點擊操作之后彈出彈窗
alert('hello,world');
};
在上面的代碼中,我們通過給一個元素綁定單擊事件,並且添加了事件處理函數。
一旦用戶點擊了按鈕,那么就立刻會彈出彈窗。
當然,我們除了上面的寫法以外,對於給一個元素綁定事件和事件處理函數的寫法還可以換做另外一種形式:
<button id="btn" onclick="sayHello()">點擊</button>
<script >
function sayHello(){
alert('hello,world');
}
</script>
在上面的代碼中,我們把事件和事件處理函數都綁定到了元素的身上,這樣做的好處是能夠省略了獲取元素的過程。
在我們執行事件處理函數的時候,在某些時刻可能需要進行參數的傳遞,那么該如何進行參數的傳遞呢?
可以采用下面的幾種方式。下面同樣是點擊問好的案例,但是問好的對象是對指定的人進行問好。
第一種方式:
demo:
<button onclick="sayHello('張三')">點擊問好</button>
<script >
function sayHello(name){
alert('hello,' + name );
}
</script>
第二種方式:
demo:
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<input type="text" id="name">
<button id="btn">點擊問好</button>
</body>
<script>
// 獲取input
var oInput = document.getElementById('name');
// 獲取按鈕
var oBtn = document.getElementById('btn');
// 點擊按鈕然后執行問好
oBtn.onclick = function () {
var userName = oInput.value;
sayHello(userName);
};
function sayHello(name) {
alert('hello,' + name);
}
</script>
</html>
上面的代碼中,我們可以在input中輸入用戶名,當用戶點擊按鈕的時候,我們會將通過單擊事件的事件
處理函數來調用sayHello方法,在這個方法中,獲取用戶輸入的用戶名,然后問好。
上面的代碼基本上已經完成了我們的需求,但是我們仍然需要讓我們的代碼變得更加的完善。
例如,當我們點擊按鈕的時候,發現用戶並沒有輸入用戶名,我們該怎么辦?
demo:
// 點擊按鈕然后執行問好
oBtn.onclick = function () {
var userName = oInput.value;
// 判斷一下用戶輸入的內容是否為空
if (userName === "") {
alert("請輸入用戶名");
}else {
sayHello(userName);
}
};
在上面的代碼中,當用戶點擊按鈕調用了事件處理函數之后,我們進行了一個判斷,判斷用戶輸入的內容是否為空,如果為空,我們就可以繼續提示用戶,請輸入用戶名。
當然。上面的代碼其實演示的僅僅是一種思路,代碼仍然不是太嚴謹。
在我們的實際項目開發中,必須要讓我們的代碼盡可能的變得更加嚴謹,使我們的代碼變得更加的強壯。
小練習
上面我們講了階乘的定義,那么我們現在來完成一個簡單的小練習。
用戶在輸入框中輸入任意的數字,我們來幫助用戶完成這個數字的階乘。並且將結果顯示在網頁當中。
demo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>階乘</title>
<style>
#value {
font-size: 40px;
color:green;
}
</style>
</head>
<body>
請輸入需要計算階乘的數字:
<input type="text" id="number">
<button id="btn">點擊計算</button>
<br>
<div id="value"></div>
<script>
// 獲取按鈕
var oBtn = document.getElementById('btn');
// 創建階乘計算函數
function factorial(number) {
var base_number =1;
for (var i=1;i<=Number(number);i++){
base_number = base_number * i;
}
return base_number;
}
// 獲取div
var oDiv = document.getElementById('value');
// 獲取input
var input = document.getElementById('number');
// 綁定單擊事件
oBtn.onclick = function () {
// 獲取用戶輸入的內容
var oInput = input.value;
// 將階乘的結果賦值給oDiv
oDiv.innerHTML = factorial(oInput);
}
</script>
</body>
</html>
下面我們再來完成另外一個練習,當用戶在輸入框中輸入用戶名后,當用戶輸入完成后自動驗證,我們來檢測當前的用戶名是否可用。
demo:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>用戶名驗證</title>
<style>
#check {
font-size: 40px;
}
</style>
</head>
<body>
<input type="text" id="username">
<div id="check"></div>
</body>
<script>
// 獲取input 按鈕 和 div
var oInput , oDiv;
oInput = document.getElementById('username');
oDiv = document.getElementById('check');
// 在變量中存儲正確用戶名
var user_right = "張三";
// 綁定onchange事件
oInput.onchange = function () {
// 獲取用戶輸入的內容
var oInput_value = String(oInput.value);
if (oInput_value === user_right) {
// 如果用戶名正確
oDiv.style.color = "green";
oDiv.innerHTML = "輸入正確";
}else {
oDiv.style.color = "red";
oDiv.innerHTML = "輸入錯誤";
}
}
</script>
</html>
數據類型之間的差異性
我們之前說過,js的數據類型分為基礎數據類型和引用數據類型。上面我們說過的string、boolean、number等類型都屬於基礎數據類型。
而我們說過的函數則屬於引用數據類型。
我們下面說的數組類型同樣屬於引用數據類型。
在學習數組之前我們先來說下基礎數據類型和引用數據類型的區別。
基礎數據類型又叫做原始數據類型。通常情況下數據會存儲在內存的棧中。
例如,將hello,world這個字符串存儲在變量str中。這個變量連同hello,world都存在棧中。
如果我們存在一個函數或者數組等引用數據類型將其存在一個變量中,那么這個變量將會被存儲在內存的棧中。
而引用類型的數據將會被存在內存的堆中。
此時需要注意的是,變量和具體的引用類型的數據是分開存儲的,而存儲在棧中的變量里面存儲的只是引用類型的數據在堆中存儲的具體位置。
我們知道了基礎數據類型和引用類型的數據在內存中不同的存儲位置之后,我們還需要知道下面的這些內容。
首先,基礎類型的數據一旦創建之后不能夠進行更改。
例如:
var a = "hello,world";
此時這個變量a存儲的數據為一個字符串,是一個基礎數據類型,我們對這個變量里面的內容,只具有讀取的權限,但是並沒有辦法進行更改。
例如我們可以通過下標的形式進行查詢:
console.log(a[0]);// h
但是我們並沒有辦法進行更改:
a[0] = "z";
上面的這種做法是完全行不通的。
而如果變量當中存儲的數據是一個引用類型的數據,例如下面我們要學習的數組:
var a = [10,20,30];
我們是可以進行更改的:
a[0] = "hello";
此時我們再來查看數組,是一個已經被更改的數組。
在很多的面試題當中,經常出現下面的題目:
var a = "hello,world";
var b = a;
b[0] = 'x';
console.log(b[0]); // h
console.log(a); // hello,world
console.log(b); // hello,world
當存儲的數據變為引用類型的數據:
var a = [10,20,30];
var b = a;
b[0] = 'hello,world';
console.log(b); // [ 'hello,world', 20, 30 ]
console.log(a); // [ 'hello,world', 20, 30 ]
在上面的代碼中,通過b對數據進行了更改,那么a也跟着發生了更改。
再來看下面的試題:
var a = "hello,world";
var b = a;
console.log(b); // hello,world
console.log(a); // hello,world
b = "admin";
console.log(a); // hello,world 變量a並沒有發生變化
console.log(b); // admin 變量b相當於重新存儲了數據,並且在內存中重新開辟了一塊空間
在上面的案例中,我們將b重新的存儲了新的數據,並不會對原本的變量a產生任何的影響。
數組
介紹
數組(array)是按次序 排列的一組值。其中每一個值都有一個編號(編號默認從0開始).
當我們存儲一系列值的時候,通常情況下都會使用數組,這樣無論是從存儲還是從查詢獲取等方面都很便捷。
創建
下面我們來說下如何創建一個數組,我們創建數組,通常情況下可以使用下面的兩種方式:
第一種方式,是通過直接量的方式:
例如:
var test_arr = [10,20,30]; // 通過直接量的形式創建了一個數組
第二種方式,是通過構造函數的形式:
例如:
var test_arr = new Array();
console.log(test_arr); // []
// 也可以在使用構造函數創建的時候設置一個具體的值,例如
var test = new Array(10); // 相當於創建了一個空數組,並且長度為10
console.log(test); // [ <10 empty items> ] 打印出一個空的數組
console.log(test.length); // 10
var test_arr2 = new Array(10,20,30,40);
console.log(test_arr2); // [ 10, 20, 30, 40 ]
在上面的兩個案例中,我們通過直接量和構造函數的形式創建了數組,兩種方式都能夠創建出我們想要使用的
數組。但是無論是從創建速度還是運行效率來講,直接量的形式都優於構造函數的形式。
所以當我們需要創建一個數組的時候,推薦使用直接量的形式來創建數組。
下面我們來具體的說下,當我們使用構造函數創建數據的時候,與直接量創建數據的時候二者之間的區別。
當我們使用構造函數的形式來創建數組的時候,通常情況下,需要經歷以下的過程:
- 首先創建函數
- 查詢作用域鏈
- 創建作用域鏈
- 將數據寫入
而我們使用直接量的形式來創建數據,相當於直接將數據寫入內存中,速度是最快的,相當於直接作用在作用域鏈條中。
而作用域鏈條在es5中存在兩條。一條是var,也就是變量的作用域,另外一條是函數聲明。在代碼執行的過程中優先查找非函數鏈條。順序是從下到上,而函數鏈條順序是從上到下。
通常,我們在執行js代碼的階段,通過直接量直接向內存中存儲數據的速度是最快的,其次是通過變量聲明,最后是通過函數調用獲得的變量。
下面是關於直接量的補充擴展內容:
1976.6 ES1中,直接量有四種:null、boolean、numeric、string
1998.8 ES2中,與ES1相同
1999.12 ES3中,直接量加入了Regular
2011.6 ES5.1 與上面相同
而在ES3和ES5當中,將數組和對象納於表達式一章里,稱之為初始器(Initialiser)。
在很多經典的js書籍里,將對象和數組都稱之為對象直接量和數組直接量,為什么會有這種說法呢?
原因是,這些書籍的出版時間略早於上面規則的更改。
數組的常規使用
需要注意的是,當我們創建了一個數組,並且使用typeof查看其類型,會發現其類型為object。
var arr = [10,20,30,40];
console.log(typeof arr); // object
明明是數組,為什么會查看其類型為object呢?原因是因為在js當中,數組也是一種特殊類型的object。
我們如果想要來判斷數組類型,可以通過instanceof來進行判斷。
例如:
var arr = [];
console.log(arr instanceof Array); // true
在js當中,數組被定性為一種特殊的對象。
下面我們來說一下在創建一個數組之后,數組的一些常規操作:
創建數組:
demo:
// 數組的常規操作
// 創建一個空數組
var arr1 = [];
// 通過索引值的形式向數組中添加內容
arr1[0] = '張三豐';
arr1[1] = '張無忌';
arr1[2] = '張翠山';
// 打印查看數組
console.log(arr1); // [ '張三豐', '張無忌', '張翠山' ]
// 也可以在創建數組的初期向數組中添加內容
var arr2 = ['張三豐','張無忌','張翠山'];
console.log(arr2); // [ '張三豐', '張無忌', '張翠山' ]
// 通過構造函數的形式來創建一個數組
var arr3 = new Array(); // 創建一個空數組
// 向數組中添加內容
arr3[0] = '張三';
arr3[1] = '李四';
arr3[2] = '王五';
console.log(arr3); // [ '張三', '李四', '王五' ]
// 通過構造函數的形式創建一個數組
var arr4 = new Array('張三','李四','王五');
console.log(arr4); // [ '張三', '李四', '王五' ]
下面是數組的查找:
var arr1 = ['張三','李四','王五'];
// 查找數組當中指定位置的元素
console.log(arr1);// 打印全部的數組元素
console.log(arr1[0]); // 張三 通過索引下標來查找元素
console.log(arr1[2]); // 王五
當我們進行數組元素查找的時候,一旦索引值超過最大范圍,則為
undefined。
// 超過數組索引值最大值
console.log(arr1[100]); // undefined
當我們想要修改數組中的具體元素的時候,可以直接通過索引值找到這個元素並且進行重新賦值。
var arr1 = ['張三','李四','王五'];
// 通過索引值下標對數組元素中的具體元素進行修改
arr1[0] = '趙三';
arr1[2] = '歐陽';
console.log(arr1); // [ '趙三', '李四', '歐陽' ]
下面的操作是數組的刪除操作,在下面的案例中主要通過delete運算符進行刪除。
// 刪除數組中的元素
var arr1 = ['張三','李四','王五'];
delete arr1[0];
console.log(arr1); // [ <1 empty item>, '李四', '王五' ] 當我們通過delete 刪除了元素之后,元素雖然被刪除,但是位置依然存在,會被undefined占據
// 訪問一下被刪除的空位
console.log(arr1[0]); // undefined
在上面的代碼中,我們通過delete運算符刪除了數組元素,但是需要注意的是,雖然我們刪除了元素,但是被刪除的元素所在的位置依然被保留,只不過被undefined取代。
數組的length屬性
在Array對象當中,存在一個length屬性,能夠用來查看數組的長度。
例如:
var arr = [10,20,30,40];
console.log(arr.length);// 4
通常情況下,我們可以通過將length屬性值設置為0,來讓數組清空。
例如:
var arr = [10,20,30,40];
arr.length = 0;
console.log(arr); // [] 數組被清空
有一點我們是需要注意的,因為數組也是一種特殊的對象,所以我們通常情況下,數組索引值的設定,除了采用默認的索引值外,還可以采用自定義
索引值的索引。
但是一旦我們采用了自定義索引值的索引,那么這個數組里面的length屬性將會為失效。
var arr = [];
arr['hello'] = 'hello,world';
console.log(arr); // [ hello: 'hello,world' ]
arr['world'] = 'this is my new world';
console.log(arr); // [ hello: 'hello,world', world: 'this is my new world' ]
console.log(arr.length); // 0
數組當中常見的操作方法
在數組中,經常使用的操作方法有以下的幾個
- push
- pop
- unshift
- shift
首先來說下push()方法。通過這個方法,我們能夠將一個或者多個元素添加到數組的末尾,並且返回數組的新長度。
// 創建一個數組
var arr1 = ['張三','李四'];
// 通過Push方法向數組中添加元素
arr1.push("王五");
// 檢查數組內容
console.log(arr1); // [ '張三', '李四', '王五' ]
// 嘗試添加多個內容
arr1.push("趙六","劉七");
// 打印數組元素
console.log(arr1); // [ '張三', '李四', '王五', '趙六', '劉七' ]
// 創建一個新的數組
var arr2 = [1,2,3,4];
// 嘗試將arr2添加到arr1
arr1.push(arr2);
// 打印arr1;
console.log(arr1); // [ '張三', '李四', '王五', '趙六', '劉七', [ 1, 2, 3, 4 ] ]
// 向arr1中再次添加數據並且查看push方法的返回值
console.log(arr1.push('hello,world')); // 7
pop()方法能夠從數組中刪除最后一個元素,並且返回該元素的值。此方法更改數組的長度。
var plants = ['broccoli', 'cauliflower', 'cabbage', 'kale', 'tomato'];
console.log(plants.pop());
// expected output: "tomato"
console.log(plants);
// expected output: Array ["broccoli", "cauliflower", "cabbage", "kale"]
plants.pop();
console.log(plants);
// expected output: Array ["broccoli", "cauliflower", "cabbage"]
上面我們演示了pop方法刪除數組的最后一個元素,但是在使用pop方法的時候,我們需要注意,該方法通過length屬性來確定最后一個元素的位置,
如果不包含length屬性或者length屬性不能夠被轉換成一個數值,那么就會將length屬性設置為0,並且返回undefined。
同時,你在一個空數組上調用pop方法,也會返回undefined。
arr.pop();
console.log(arr);// 並沒有刪除成功
console.log(arr.pop()); // undefined
unshift()方法能夠將一個或者多個元素添加到數組的開頭,並且返回數組的新長度。
var array1 = [1, 2, 3];
console.log(array1.unshift(4, 5));
// expected output: 5
console.log(array1);
// expected output: Array [4, 5, 1, 2, 3]
shift()方法從數組中刪除第一個元素,並返回該元素的值。此方法更改數組的長度。
var array1 = [1, 2, 3];
var firstElement = array1.shift();
console.log(array1);
// expected output: Array [2, 3]
console.log(firstElement);
// expected output: 1
shift 方法移除索引為 0 的元素(即第一個元素),並返回被移除的元素,其他元素的索引值隨之減 1。如果 length 屬性的值為 0 (長度為 0),則返回 undefined。
shift 方法並不局限於數組:這個方法能夠通過 call 或 apply 方法作用於類似數組的對象上。但是對於沒有 length 屬性(從0開始的一系列連續的數字屬性的最后一個)的對象,調用該方法可能沒有任何意義。
數組的遍歷
遍歷指的是將對象當中的內容全部輸出出來,而數組 的遍歷可以通過for循環和專門針對對象的for..in循環來實現。
var arr = ['hello','world','how are you','nice to meet you'];
// 循環遍歷數組
for(var i=0;i<arr.length;i++){
console.log(arr[i]);
}
// 第二種遍歷數組的方式
for (var j in arr) {
console.log(arr[j]); // 同樣可以實現遍歷數組的目的
}
數組的分類
在js當中,數組可以分為稀疏數組、多維數組、自定義索引數組等等。
下面來說一下這幾種類型的數組以及在使用的過程中需要注意的內容。
需要注意的是,數組是一種特殊類型的對象,所以數組的里面可以存儲任意類型的數據。
稀疏數組
當數組的索引值處於不連續狀態的時候,被稱為稀疏數組。
var arr = [];
arr[0] = 'hello';
arr[2] = 'world';
arr[10] = 'test';
上面我們在創建的過程中指定了索引值,但是索引值並不連續,所以此時這個數組我們可以稱之為稀疏數組。
一旦我們主動的或者被動的創建了一個稀疏數組,那么我們在遍歷數組的過程中將會非常容易出現問題。
var arr = [];
arr[0] = "hello";
arr[3] = "world";
arr[6] = "test";
console.log(arr); // 我們創建了一個稀疏數組
// 循環輸出數組
for(var i=0;i<arr.length;i++){
console.log(arr[i]); // 會將空位輸出undefined
}
在上面的代碼中,我們創建的稀疏數組,一旦索引值不連續,那么就會形成空位。空位在js當中會被undefined代替。
多維數組
上面我們說到,js當中的數組里面可以存儲任何類型的數據,當然也包括數組,即在一個數組里面存儲另外的數組,這樣的數組我們稱之為多維數組。
例如:
var arr = [[1,2,3],[4,5,6]];
console.log(arr); // [ [ 1, 2, 3 ], [ 4, 5, 6 ] ]
我們如果想要操作多維數組,依然可以采取索引值的形式,整體的操作形式與一維數組相同。
自定義索引數組
上面我們在創建數組的過程中,曾創建過自定義索引的數組。
例如:
// 自定義索引數組
var arr = [];
arr['name'] = '張三';
arr['age'] = 30;
arr['like'] = '吃喝嫖賭';
document.write(arr); // 網頁當中並沒有效果
document.write(arr['name']); // 張三
document.write(arr['age']); // 30
document.write(arr['like']); // 吃喝嫖賭
console.log(arr);// [name: "張三", age: 30, like: "吃喝嫖賭"]
需要注意的是,數組因為是一種特殊類型的對象,所以數組的索引值無論是默認的數值還是我們設定的自定義索引,其實類型都是字符串類型。
即使索引值在創建之初看上去並不像是一個字符串,但是在代碼的運行過程中也會被轉換為字符串類型。
小練習
- 山上有一口缸可以裝50升水,現在有15升水。老和尚叫小和尚下山挑水,每次可以挑5升。問:小和尚要挑幾次水才可以把水缸挑滿?通過編程解決這個問題。
var water = 50;
var now_water = water - 15;
var step = now_water / 5 ;
console.log(step); // 7
數組的排序
- 冒泡排序
所謂的冒泡排序,其實指的是對數組中的數據進行排序,按照從小到大的順序來進行排列.
生活原理:假設小明是最矮的;然后通過比較,發現二狗要比小明矮,就和小明換位置,兩兩比較,通過第一次比較可以找出二狗是最矮的人,
然后假設隊伍的第二個人是最矮的,讓他和剩下的人比較身高,依次找出其他人的位置。
js思路:假想數組中的任意一個值是最小;然后通過比較兩兩比較,找出索引值,換位,然后賦值。
// 數組的冒泡排序
var arr = [10,3,4,2,32,43,100,99];
maoPao(arr);
// 希望對上面的數組進行冒泡排序的處理
// 將兩個值進行對比
function maoPao(arr) {
var flag = 1; // 用來標記某一次排序是否發生交換
for(var i =0;i<arr.length-1;i++) {
flag = 0; // 設置為0表示沒有發生交換
for (var j =0;j < arr.length-i-1;j++){ // arr.length - i - 1相當於 arr.length - (i + 1 ) 因為一次循環比較的是一個值,所以這一步求出的剩余的沒有比較的次數
if (arr[j] > arr[j+1]) {
// 進行交換
var temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
flag = 1; // 設置為1 表示本次循環發生了交換
}
}
console.log(arr); // 每次都輸出一下數組
if(flag === 0) break; // 如果沒有發生改變,則停止循環
}
}
- 選擇排序
生活原理:假設小明是最矮的;然后通過比較,發現二狗要比小明矮,
就和小明換位置,兩兩比較,通過第一次比較可以找出二狗是最矮的人,
然后假設隊伍的第二個人是最矮的,讓他和剩下的人比較身高,依次找出其他人的位置。
js思路:假想數組中的任意一個值是最小;然后通過比較兩兩比較,找出索引值,換位,然后賦值。
// 數組的冒泡排序
var arr = [10,3,4,2,32,43,100,99];
xuanZe(arr);
function xuanZe(arr) {
for(var i=0;i<arr.length-1;i++){
// 假設此時最小值
var min = arr[i];
// 假設此時最小值所在的索引
var index = i;
for (var j = i + 1;j < arr.length;j++){
if (min > arr[j]) {
index = j;
min = arr[index];
}
}
var temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
console.log(arr);
}
小練習
隨機點名:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>隨機點名</title>
<style>
#name {
width: 300px;
height: 300px;
border: 2px solid red;
text-align: center;
line-height: 300px;
font-weight: bold;
font-size: 80px;
}
</style>
</head>
<body>
<div id="name">
hi!
</div>
<button onclick="start()">開始</button>
<button onclick="end()">結束</button>
</body>
<script>
// 聲明變量
var time, // 計時器
div,
name; // 選中的用戶名
div = document.getElementById('name');
// 創建一個數組用來存儲數據
var name_list = ["張三", "李四", "王五", "趙六","張1","張2","張3",'張四'];
function start(){
// 生成一個隨機數
var num = Math.floor(Math.random() * name_list.length);
// 根據隨機索引值來確定選中的姓名
name = name_list[num];
// 更改網頁里div的值
div.innerHTML = name;
time = setTimeout("start()",100);
}
function end() {
clearTimeout(time);
}
</script>
</html>
