JavaScript 基礎知識 - 入門篇(一)

image

前言

最近一直有小夥伴跟我說JS有不少知識點常常不用,已經忘記的差很少了。平時找一個小問題都要在網上找半天,但願能有一套比較全面的筆記或者文章。可是網上的文章太過於分散,學習起來不是很方便。恰巧最近比較閒,因此爲你們整理出來了一套比較全面的JS基礎階段的文章,對於初學者仍是頗有幫助的,若是你是一名熟練掌握JS的攻城獅,你可能會以爲文章寫得太過於囉嗦,可是爲了照顧你們,囉嗦一點仍是有必要的。javascript

這篇文章主要講的是關於JS基礎的知識點,後面會陸續更新DOMJS高階AjaxH5C3JQ,包括一些主流的框架,可是本人時間有限,不可能專門去花費時間來寫,並且工做量也是很是大的,因此喜歡的小夥伴能夠點一波關注,後續會陸續更新。css

因爲是本身所寫,因此裏面有些語言可能表達的有些不明確,不明白的能夠給我留言。html

1. 初識JS

1.1 什麼是JS語言

javascript是一種運行在 客戶端腳本語言

客戶端:接受服務的一端,與服務端相對應,在前端開發中,一般客戶端指的就是瀏覽器前端

腳本語言: 也叫解釋型語言,特色是執行一行解釋一行,若是發現報錯,代碼就中止執行。java

1.2 JS的三個組成部分

javascript的三個組成部分: ECMAScriptBOMDOM

ECMAScript: 定義了javascript的語法規範。程序員

BOM: 一套操做瀏覽器功能的APIsegmentfault

DOM: 一套操做頁面元素的API數組

1.3 script 標籤

一、script標籤的書寫方式瀏覽器

書寫 Javascript代碼有兩種方式,第一種是直接在 script標籤中書寫,第二種是將代碼寫在 js文件中,經過 scriptsrc屬性進行引入。

直接在script中書寫javascript代碼:框架

<!-- type="text/javascript" 能夠省略 -->
<script type="text/javascript">
    alert("今每天氣真好呀");
</script>

經過script標籤引入一個JS文件,須要指定src屬性:

<!-- 表示引用了test.js文件,而且script標籤內不能夠繼續寫代碼 -->
<script src="test.js"></script>

若是script標籤指定了src屬性,說明是想要引入一個js文件,這個時候不能繼續在script標籤中寫js代碼,即使寫了,也不會執行。

二、script標籤的書寫位置

script標籤的書寫位置,原則上來講,能夠在頁面中的任意位置書寫。

寫在head標籤中,style標籤以後:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="demo.css">
    <!-- 寫在這裏 -->
    <script src="demo.js"></script>
</head>
<body>
</body>
</html>

瀏覽器有一個特性,就是在遇到<body>標籤時纔開始呈現內容。若是在head裏面引用js文件的話,意味着必需要等到所有的javascript代碼都被下載、解析和執行完成以後,才能開始呈現頁面的內容。若是文件數量一旦過多,將會影響頁面加載速度,此時頁面有可能會在加載完成前一片空白。

寫在</body>標籤的前面:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link rel="stylesheet" href="demo.css">
</head>
<body>
    <!-- 寫在這裏 -->
    <script src="demo.js"></script>
</body>
</html>

在解析javascript代碼以前,頁面的內容已經徹底呈如今瀏覽器當中了,用戶會明顯感受頁面加載變快了。

1.4 js中輸入輸出語句

  • console.log 控制檯輸出日誌
  • console.dir 對象的形式打印一個對象
  • document.write 往頁面中寫入內容
  • alert 彈框警告
  • confirm 確認框
  • prompt 輸入框

1.5 註釋

不被程序執行的代碼。用於程序員標記代碼,在後期的修改,以及他人的學習時有所幫助,在JS中,分爲 單行註釋多行註釋以及 文檔註釋

單行註釋

//這是單行註釋,只能註釋一行

多行註釋

/*
    這是多行註釋,不能嵌套
*/

文檔註釋

/**
 * 求圓的面積
 * @param r {number} 圓的半徑
 * @returns {number} 圓的面積
 * 這是文檔註釋
 */
function getArea (r) {
    return Math.PI * r * r;
}

註釋的做用

  • 模塊劃分,方便代碼查找和維護
  • 用於解釋複雜代碼的邏輯,方便維護和後期開發。

2. 變量

變量, 能夠變化的量,變量是在計算機中存儲數據的一個 標識符。能夠把變量當作 存儲數據的容器

變量與字面量:

  • 字面量:1020「abc」true這種從字面上就能看出來類型和值的量叫作字面量。
  • 變量:能夠變化的量。

2.1 變量的聲明與賦值

// 1- 同時聲明而且賦值
var num = 100;
console.log(num);  // 100

// 2- 先聲明瞭一個變量,再賦值
var num1;
num1 = 100;
console.log(num1); // 100

// 3- 沒有聲明變量,直接賦值(能夠,可是不推薦)
num2 = 200;
console.log(num2); // 200

// 4- 有變量聲明,可是沒有賦值(能夠,沒有賦值,變量的值默認是個undefined)
var num9;
console.log(num9); // undefined

// 5- 既沒有聲明,也沒有賦值,直接用。
console.log(num3); //報錯  num3

// 6- 一個 var,逗號分隔 能夠同時聲明多個變量
var name = "Levi丶",
    age  = 18,
    gender = "男";

2.2 變量的命名規則與規範

命名規則(必須遵照):

  • 由字母、數字、下劃線、$符號組成,開頭不能是數字。
  • 不能使用關鍵字和保留字
  • 區分大小寫

命名規範(建議遵照):

  • 命名要有意義
  • 遵照駝峯命名法。首字母小寫,後面單詞的首字母須要大寫。

2.3 交換兩個變量的值

方法一: 聲明一個新的變量

// 交換 num1 和 num2的值
var num1 = 11;
var num2 = 22;

var temp;
temp = num1; // num1=11 temp=11
num1 = num2; // num1=22 num2=22
num2 = temp; // temp=11 num2=11

方法二: 不經過聲明變量的方式

// 不使用臨時變量
var num1 = 11;
var num2 = 22;
// num1 = 11 + 22
num1 = num1 + num2; // num1=33 
// num2 = 33 - 22
num2 = num1 - num2; // num2=11
// num1 = 33 - 11 
num1 = num1 - num2; // num1=22

3. 數據類型

基本數據類型包括了: numberstringbooleanundefinednull

3.1 如何查看數據類型

使用 typeof關鍵字查看數據類型
typeof(name);  
// 括號能夠省略
typeof name;

3.2 Number 類型

進制

  • 十進制,咱們平時使用的就是十進制,進行運算時,八進制和十六進制的值最終都會轉換成十進制。
  • 二進制,計算機當中用的最多的計算方式,數值序列只有01
  • 八進制,0開頭的數值,數值序列:0-7
  • 十六進制,0x開頭的數值,數值序列:0-9A-Fa-f

浮點數

所謂浮點數,就是該數當中必須包含一個小數點,而且小數點後面至少有一位數字。

科學計數法:

//如何表示0.003和20000?
var num = 3e-3;   // 0.003
var num2 = 2e+4;  // 20000

浮點數的精度問題:

0.1 + 0.2 = ?    // 0.30000000000000004
0.07 * 100 = ?   // 7.000000000000001

浮點數在運算的時候會出現精度丟失的問題,所以在作比較運算的時候,儘可能不要用小數進行比較。在第五章的時候會着重講解這個問題

數值範圍

javascript不能表示世界上全部的數,所以在 javascript中,數值大小是有必定限制的。
  • Number.MIN_VALUE:5e-324 (js裏面能表示最小的數)
  • Number.MAX_VALUE:1.7976931348623157e+308 (js裏面能表示最大的數)
  • Infinity:正無窮 (若是超出js裏面最大的數,將會顯示infinity)
  • -Infinity:負無窮 (若是超出js裏面最小的數,將會顯示-infinity)

數值判斷

  • NaN: 表示一個非數值,當沒法運算或者運算錯誤的時候,會獲得一個NaNNaNnumber類型,表示一個非數值。
  • NaN與任何值都不想等,包括它自己
  • isNaN: 用來判斷是不是一個數字,當返回true的時候說明是NaN,表示的不是一個數字,返回false,說明不是NaN,表示的是一個數字。

示例代碼:

var str = "abc";
console.log(isNaN(str));  // true 說明不是一個數字

3.3 String 類型

字面量

字符串的字面量: 「abc」‘abc’ 字符串能夠是雙引號,也能夠是單引號引發來。

無論是雙引號,仍是單引號,都是成對出現的,假如打印的字符串裏有引號怎麼辦呢?

這裏就要活學活用,若是隻有一處有引號,就能夠用單雙引號混合使用:

console.log('我是"帥哥"');  // ==> 我是"帥哥"

假如引號很是多的時候怎麼辦呢? 用轉義字符:「\」

console.log("我是'帥哥',\"哈哈哈\""); // ==> 我是'帥哥',"哈哈哈"

字符串拼接

拼接字符串使用 +

示例代碼:

console.log(11 + 11);             //  22
console.log("hello" + " world");  // "hello world"
console.log("100" + "100");       // "100100"
console.log("11" + 11);           // "1111"

總結:

  • 兩邊只要有一個是字符串,那麼+就是字符串拼接功能
  • 兩邊若是都是數字,那麼就是算術功能。

字符串長度

length屬性用來獲取字符串的長度
var str = "abcdefghij";
str.length;// 字符串的長度  10

3.4. boolean 類型

boolean類型只有兩個字面量, truefalse,區分大小寫(True,False不是布爾類型,只是標識符)。

全部類型的值均可以轉化成true或者false

NaN""undefinednullalse06個值能夠轉換成false,其他的都是true

3.5 undefined類型與null類型

undefined表示一個聲明瞭沒有賦值的變量

var name ;
console.log(name); // undefined

null表示一個空的對象

var name = null;
console.log(typeof name); // Object

若是定義的變量,未來是準備用於保存對象的話,最好將變量初始化爲null

var name = null;

undefinednull 的關係

undefined == null;   // true
undefined === null;  // false

實際上,undefiner值是派生自null值的,因此判斷相等時爲true,可是兩種用途是徹底不同的。

4. 簡單數據類型轉換

如何使用谷歌瀏覽器,快速的查看數據類型?
  • 字符串的顏色是黑色
  • 數值類型是藍色
  • 布爾類型也是藍色
  • undefinednull灰色

這個在調試過程當中時很是有用的。

4.1 轉字符串類型

一、String()函數轉換

var num = 123;
console.log(String(num)); // "123"

二、toString() 轉換不了undefinednull

var num = 123;
console.log(num.toString());        // "123"
console.log(undefined.toString());  // 報錯
console.log(null.toString());       // 報錯

三、+ "" 加引號

var num = 123;
console.log(num + ""); // "123"

4.2 轉數值類型

一、Number

  • 若是轉換的是空字符串,返回的是0
  • 若是是數字字符串,轉換後保留原數據;
  • 非數字字符串,轉換以後爲NaN
console.log(Number("-123"));    // -123
console.log(Number(""));        // 0
console.log(Number("123abc"));  // NaN

二、parseInt(取整)

  • 小數數字字符串,轉換以後,保留整數部分(取整);
  • 數字開頭非純數字字符串,轉換以後保留整數部分;
  • 非數字字符串,轉換以後爲NaN
console.log(parseInt("123.123"));       // 123
console.log(parseInt("123.123abc"));    // 123
console.log(parseInt("abc123.123"));    // NaN
console.log(parseInt(""));              // NaN
console.log(parseInt("abc"));           // NaN

三、parseFloat(取數)

  • 數字字符串,轉換以後保留原數據;
  • 數字開頭的非純數字字符串,轉換以後保留數字部分(包括小數);
  • 非數字字符串轉換以後爲NaN
console.log(parseFloat("123.123")); // 123.123
console.log(parseFloat("123.123abc")); // 123.123
console.log(parseFloat("abc123.123")); // NaN
console.log(parseFloat("")); // NaN
console.log(parseFloat("abc")); // NaN

四、參與運算==> "+" or "-0"

var str = "-123";
console.log(+str);  // -123
console.log(str-0); // -123

4.3 轉布爾類型

布爾類型只有 truefalse,可是全部類型的值均可以轉換成布爾類型

一、可以轉換成false的只有6種:

  • ""
  • 0
  • NaN
  • undefined
  • null
  • false

其他的都是true

二、! 轉換

var str = "";
// Boolean() 判斷這個參數的布爾類型
console.log(Boolean(str)); // false

console.log(!str); // true

5. JS小數運算精度丟失

5.1 JS數字精度丟失的一些典型問題

js在使用小數進行計算的時候,會出現精度丟失的問題。不要用來跟其餘的小數作比較。

0.1 + 0.2 != 0.3 //true   0.30000000000000004

// 16位數 和 17位數相等
9999999999999999 == 10000000000000001 // true

9007199254740992 + 1 == 9007199254740992 // true

5.2 JS數字丟失精度的緣由

計算機的二進制實現和位數限制有些數沒法有限表示。就像一些無理數不能有限表示,如 圓周率 3.1415926...1.3333... 等。JS 遵循 IEEE 754 規範,採用 雙精度存儲(double precision) ,佔用 64 bit。如圖

精度丟失

意義:

  • 1位用來表示符號位
  • 11位用來表示指數
  • 52位表示尾數

浮點數,好比:

0.1 >> 0.0001 1001 1001 1001…(1001無限循環)
0.2 >> 0.0011 0011 0011 0011…(0011無限循環)

此時只能模仿十進制進行四捨五入了,可是二進制只有01兩個,因而變爲01入。這便是計算機中部分浮點數運算時出現偏差,丟失精度的根本緣由。

大整數的精度丟失和浮點數本質上是同樣的,尾數位最大是 52 位,所以 JS 中能精準表示的最大整數是 Math.pow(2, 53),十進制即 9007199254740992

大於 9007199254740992 的可能會丟失精度:

9007199254740992     >> 10000000000000...000 // 共計 53 個 0
9007199254740992 + 1 >> 10000000000000...001 // 中間 52 個 0
9007199254740992 + 2 >> 10000000000000...010 // 中間 51 個 0

實際上:

9007199254740992 + 1 // 丟失  
9007199254740992 + 2 // 未丟失
9007199254740992 + 3 // 丟失
9007199254740992 + 4 // 未丟失

結果如圖:

計算結果

以上,能夠知道看似有窮的數字,在計算機的二進制表示裏倒是無窮的,因爲存儲位數限制所以存在「捨去」,精度丟失就發生了。

5.3 JS數字丟失精度的解決方案

對於整數,前端出現問題的概率可能比較低,畢竟不多有業務須要須要用到超大整數,只要運算結果不超過 Math.pow(2, 53) 就不會丟失精度。

對於小數,前端出現問題的概率仍是不少的,尤爲在一些電商網站涉及到金額等數據。解決方式:把小數放到位整數(乘倍數),再縮小回原來倍數(除倍數)

// 0.1 + 0.2
(0.1*10 + 0.2*10) / 10 == 0.3 // true

6. 運算符

6.1 一元運算符

  • 一元運算符有1個操做數。例如,遞增運算符"++",或者遞減運算符"--"就是一元運算符。
  • 二元運算符有2個操做數。例如,除法運算符"/"2個操做數。
  • 三元運算符有3個操做數。例如,條件運算符"?:"具備3個操做數。
遞增 "++" 和 遞減 "--" 還分爲 前自增後自增前自減後自減,兩種自增自減的運算結果是不同的;
  • ++num 前自增 --num 前自減 先+1-1,再返回值
  • num++ 後自增 num-- 後自減 先返回值,再+1-1

舉個例子,看代碼:

var num = 5;
console.log(num++);  // 5 
console.log(++num);  // 7 (由於剛剛num自增了一次,這裏打印的話就等於在6的基礎上前自增了,在計算機科學中,被稱爲副效應)
console.log(num--);  // 7 (這裏是後自減,因此先返回值,返回7,再運算--,此時的num實際是等於6了)
console.log(--num);  // 5

6.2 邏輯運算符

  • &&(與運算):只要有一個值爲,結果就是。找值 找到假值就返回,若是都是,返回最後一個
  • ||(或運算):只要有一個值爲,結果就是。找值 找到真值就返回,若是都是,返回最後一個
  • !(非運算):取反

示例代碼:

/*細讀上面三句話,就能理解爲何會是這個打印結果了*/
console.log(true && true);          //true
console.log(false || false);        //false
console.log(null && undefined);     //null
console.log(null || undefined);     //undefined
console.log("abc" && undefined);    //undefined
console.log("abc" || undefined);    //abc
console.log(null || false || 0 || 1 || null);   //1
console.log("abc" && "bcd" && "def");           //def

6.3 運算符的優先級

  • 一、() 優先級最高
  • 二、一元運算符 ++ -- !
  • 三、算數運算符 先* / %+ -
  • 四、關係運算符 > >= < <=
  • 五、相等運算符 == != === !==
  • 六、邏輯運算符 先&&||

示例代碼:

// 第一題              true              &&           true
console.log(((4 >= 6) || ("人" != "狗")) && !(((12 * 2) == 144) && true));  // true

// 第二題 
var num = 10;
// true         &&           true
if(5 == num / 2 && (2 + 2 * num).toString() === "22") {
   console.log(true);        //  true
}else{
   console.log(false);
}

7. 選擇語句

7.1 if..else語句

語法:

只有一個判斷條件的時候 if..else

if(判斷條件){   // 當判斷條件爲true的時候執行代碼1,爲false的時候執行代碼2
    代碼1;     
}else{
    代碼2;
}

當不止一個判斷條件的時候 elseelse if 代替:

if(判斷條件1){          // 判斷條件 1 爲 true 的時候執行 代碼 1
    代碼1; 
}else if(判斷條件2){    // 判斷條件 2 爲 true 的時候執行 代碼 2
    代碼2; 
}else{                  // 兩個條件都不知足的時候執行代碼 3
    代碼3;         
}

思考1:

  • 若是滿18,告訴他能夠看電影
  • 若是滿了16,告訴他能夠在家長的陪同下觀看
  • 若是不夠16,告訴他不許看
var age = 20;
if(age >= 18){
    console.log("沒時間解釋了,趕忙上車吧");   // 打印這條
}else if(age >= 16){
    console.log("請在家長的陪同下觀看");
}else {
    console.log("回家學習吧");
}

思考2:

  • 根據new Date().getDay()獲取今天是星期幾
  • 因爲獲取到的是純數字,如今須要根據這個數字輸出"今天是周*"的字符串
var date = new Date();      // 獲取當前的時間
var week = date.getDay();   // 得到 0-6 表示周幾 0:星期日
if(week == 0){
    console.log("今天是星期天");
}else if(week == 1){
    console.log("今天是星期一");
}else if(week == 2){
    console.log("今天是星期二");
}else if(week == 3){
    console.log("今天是星期三");
}else if(week == 4){
    console.log("今天是星期四");
}else if(week == 5){
    console.log("今天是星期五");
}else if(week == 6){
    console.log("今天是星期六");
}else{
    console.log("你火星的來的吧");
}

7.2 switch..case

語法:

// switch: 開關; case: 案列;

switch(變量){       // 判斷變量是否全等於case的值1,或者值2,
    case 值1:
        執行代碼1;  // 全等於的時候執行代碼1
        break;      // 而後break;代碼跳出switch語句, 不加break,會繼續執行下面的代碼
    case 值2:
        執行代碼2;
        break;
    default:
        執行代碼3; // 當都不知足條件的時候,會執行默認裏的執行代碼3
}

思考:素質教育(把分數變成ABCDE)

// 90-100 : A
// 80-89:   B
// 70-79:   C
// 60-69:   D
// 0-59 :   E
// 這裏的等級是根據一個範圍的分數劃定的,用if..else很容易實現,可是switch..case是一個具體的條件,怎麼辦呢?
// 方法:將分數除以10再用parseInt屬性取整
  
var score = 85;
score = parseInt(score/10); // 8
switch (score) {
// score = 10 或者 9 的時候 返回 A
case 10:
case 9:
    console.log("A");
    break;
// score = 8 的時候 返回 B
case 8:
    console.log("B");
    break;
case 7:
    console.log("C");
    break;
case 6:
    console.log("D");
    break;
default:
    console.log("E");
}

7.3 三元運算符

這個運算符能夠用來代替 if..else條件判斷。可是爲何有這個運算符呢?這裏的緣由是 if..else使用兩個代碼塊,卻只有一個會執行,在講究的程序員看來是一種浪費。因此使用三元運算符,用一條語句就能夠完成功能。

語法:

判斷語句?表達式1:表達式2;  

根據判斷語句返回的布爾值,true的話,返回表達式1,false的話返回表達式2

舉個例子,看代碼:

var sex = 1;
sex == 1 ? "男":"女";   // 判斷sex是否等於1,若是true,返回第一個表達式:"男"

例題:判斷兩個數的大小

// 用if..else語句解決
// 這裏使用了兩個代碼塊,有點浪費
var num1 = 18;
var num2 = 39;
var max;
if(num1>num2){
    max = num1;
}else{
    max = num2;
}
console.log(max);

// 用三元運算符
var num3 = 28;
var num4 = 49;
var max1 = num3>num4? num3:num4;
console.log(max1);

注意(容易出錯的地方):

下面這個語句判斷若是是會員,費用爲 2美圓,非會員,爲 10美圓。如今設置了非會員,卻打印出了 2美圓,顯然出錯了。
var isMember = false;
console.log("當前費用" + isMember ? "$2.00" : "$10.00"); // "$2.00"
出錯的緣由是 號的優先級比 號低,因此實際運行的語句是
//              true
console.log("當前費用false" ? "$2.00" : "$10.00");  // "$2.00"

8.循環語句

8.1 while 循環

語法:

  • 一、若是循環條件的結果是true的時候,就會執行循環體
  • 二、若是循環條件的結果是false的時候,結束循環。
// 1. 若是循環條件的結果是true的時候,就會執行循環體
// 2. 若是循環條件的結果是false的時候,結束循環。
while(循環條件){
  循環的代碼;      // 循環體
  自增或者自減;    // 必定不要忘記自增或自減,不然就會死循環
}

例如,求0~100的和:

var num = 0;
var sum = 0;
while(num <= 100){
    sum += num;
    num++;
}
console.log(sum); // 5050

8.2 do..while 循環

語法:

  • do..while循環和while循環很是像,兩者常常能夠相互替代
  • 可是do..while的特色是無論條件成不成立,都會執行1次。
do{
    循環的代碼;      // 循環體
    自增或者自減;    // 必定不要忘記自增或自減,不然就會死循環
}while(循環條件);

例如,求0~100的和:

var num = 0;
var sum = 0;
do{
    sum += num;
    num++;
}while(num<=100);
console.log(sum); // 5050

8.3 for 循環

while循環的常常會忘記自增, for循環實際上是 while循環演化過來的,語法更加的簡潔明瞭,使用很是的普遍。

語法:

  • 初始化表達式
  • 判斷表達式
  • 自增表達式
  • 循環體
//主要for循環的表達式之間用的是;號分隔的,千萬不要寫成,號
for(初始化表達式;判斷表達式;自增表達式){
  //循環體
}

例如:求0~100的和:

var sum = 0;
for(var num = 0; num <= 100; num++){
    sum += num;
}
console.log(sum);  // 5050

8.4 break 和 continue

break:當即跳出整個循環,即循環結束,開始執行循環後面的內容(直接跳到大括號)

continue:當即跳出當前循環,繼續下一次循環(跳到i++的地方)

一、continue 示例代碼:

for(var i = 1; i <= 10; i++) {
    if(i == 5) {
      continue;
    }
    console.log(i); // 1,2,3,4,6,7,8,9,10
}

二、break 示例代碼:

for(var i = 1; i <= 10; i++) {
    if(i == 5) {
      break;
    }
    console.log(i); // 1,2,3,4
}

8.5 循環語句練習

一、計算一個數的位數

當不知道循環次數的時候,用while循環:

var num = 1234567;
//由於不知道循環次數,因此推薦使用while循環
var count = 0;      // count記錄位數
while(num != 0){    // 循環條件
    num = parseInt(num/10);// 讓num縮小10倍
    count++;     // ,每縮小10倍就計算一次位數了
}
console.log(count);  // 7

二、翻轉一個數

var num = 12345678;
//由於不知道循環次數,因此推薦使用while循環
var str = "";  
while(num != 0){
    str += num%10;  // 將每一位取餘
    num = parseInt(num/10);//讓num縮小10倍
}
// str 是一個字符串,因此 +str將它轉回Number類型
console.log(+str); //

三、總結:

  • 循環有不少種,可是之後用得最多的是for循環
  • 當不明確循環次數的時候,可使用while循環
  • 當不管如何都要執行一次代碼的時候,可使用do..while循環。
  • 循環能夠相互替代。

9. 數組

所謂數組,就是將多個元素(一般是同一類型的),按必定順序排列放到一個集合中,那麼這個集合就稱之爲數組

javascript中,數組是一個有序的列表,能夠在數組中存放任意的數據,而且數組的長度能夠動態的調整

9.1 建立數組

一、經過構造函數建立數組:

  • var arr = new Array(); 建立了一個空數組;
  • var arr = new Array('aa','bb','cc'); 建立了一個數組,裏面存放了三個字符串
  • var arr = new Array(11,22,33) 建立了一個數組,裏面存放了三個數字

二、經過數組子面量建立數組:

  • var arr = []; 建立了一個空數組
  • var arr = [11,22,33]; 建立了一個數組,裏面存放了三個數字
  • var arr = ['aa','bb','cc']; 建立了一個數組,裏面存放了三個字符串

9.2 數組的下標與長度

數組的下標:

數組是有序的,數組中的每個元素都對應了一個下標,下標是從 0開始的
var arr = ['aa','bb','cc'];
arr[0]; // 下標是0,對應的值是'aa'
arr[2]; // 下標是2,對應的值是'cc'

數組的長度:

跟字符串同樣,數組也有一個 length的屬性,指數組中存放的元素的 個數
var arr = ['aa','bb','cc'];
arr.length; // 數組的長度爲3

空數組的長度爲0

數組的長度與下標的關係:

數組的最大下標 = 數組的長度 - 1

9.3 數組的賦值與取值

數組的取值:

  • 格式:數組名[下標]
  • 功能:獲取數組對應下標的那個值,若是下標不存在,返回undefined
var arr = ['red','blue','green'];
arr[0]; // red
arr[2]; // green
arr[3]; // 返回undefined,由於數組最大的下標爲2

數組的賦值:

  • 格式:數組名[下標] = 值;
  • 功能:爲數組新增值,若是下標有對應的值,會把原來的覆蓋,若是下標不存在,會給數組新增一個元素
  • 注意:若是一個數組的最大長度是3,但是卻給數組下標爲5賦了一個值,則下標爲三、4的值爲empty(空)
var arr = ["red", "green", "blue"];
arr[0] = "yellow"; // 把red替換成了yellow
arr[3] = "pink";   // 給數組新增長了一個pink的值
arr[5] = "black";  // 數組輸出爲["red", "green", "blue",empty,empty,"black"]

9.4 數組的遍歷

遍歷: 對數組的每個元素都訪問一次,叫作遍歷

數組遍歷的基本語法:

var arr = [1,2,3,4,5,6,7,8,9];
for(var i = 0; i < arr.length; i++){
    console.log(arr[i]); // 1 2 3 4 5 6 7 8 9 
}

數組遍歷的逆向遍歷語法:

// i= arr.length-1 ==> 表示初始化表達式 從數組最後一位開始遍歷
// i>=0 表示判斷條件,下標要知足大於等於0
// i--,表示每次遍歷 初始值都是自減的
var arr = [1,2,3,4,5,6,7,8,9];
for(var i = arr.length-1; i >= 0; i--){
    console.log(arr[i]); // 9 8 7 6 5 4 3 2 1
}

9.5 數組綜合練習

一、求一個數組中的最大值、最小值以及對應的下標

var arr = [298, 1, 3, 4, 6, 2, 23, -88,77,44];
var max = arr[0]; // 隨機取數組中的一個值與其餘值比較
var maxIndex = 0; // 初始化最大值的下標
var min = arr[0];
var minIndex = 0;
for(var i = 0; i< arr.length; i++){
    if(max < arr[i]){    // 用一開始選擇的值,與遍歷後的值進行比較
        max = arr[i];    // 當後面的值比初始值大,就將後面的這個值賦值給初始值,再用這個全新的值再v  去與後面的比較
        maxIndex = i;    // 比較結束後,此時的索引就是最大值的索引
    }
    if(min > arr[i]){
        min = arr[i];
        minIndex = i;
    }
}
console.log("最大的值是:" + max);
console.log("最大值的下標是:" + maxIndex);
console.log("最小的值是:" + min);
console.log("最小值的下標是:" + minIndex);

二、讓數組倒序保存到一個新的數組中

須要瞭解數組的一個方法 push,在數組的最後面添加

var arr = ["大喬", "小喬", "甄姬", "不知火舞"];
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
    newArr.push(arr[i]);
}
console.log(newArr); // ["不知火舞", "甄姬", "小喬", "大喬"]

三、將字符串數組用"|"或其餘符號拼成一個字符串

var arr = ["aa","bb","cc","dd"];
var str = "";
for(var i = 0; i<arr.length; i++){
    if(i == arr.length-1){
        str = str + arr[i]; // 判斷一下,若是是最後一個的話就不用加「|」
    }else{
        str = str + arr[i]+"|";  // str初始值是一個空字符串,遍歷的時候須要加上前一次的結果
    }
    
}

四、數組去重

  • 定義一個新的數組,分別遍歷兩個數組,判斷兩個裏的每一項是否相等;
  • 若是發現兩個相等,說明是重複的;
  • 當兩個不相等的時候,將這個去重數組的當前項push到新數組中;
var arr = [1, 1, 5, 7, 8, 3, 2, 5, 7, 2, 4, 6, 2, 5, 7, 2, 5];
//定義一個新數組
var newArr = [];

//遍歷須要去重的數組
for (var i = 0; i < arr.length; i++) {
    //假設不存在
    var flag = true;
    //須要判斷arr[i]這個值是否在新數組中存在
    for(var j = 0; j < newArr.length; j++){
        //進行比較便可
        if(arr[i] == newArr[j]){
            //若是發現了相等的數,說明存在
            flag = false;
        }
    }
    if(flag){
        //若是假設成立,說明不存在
        newArr.push(arr[i]);
    }
}
console.log(newArr);

10. 冒泡排序

10.1 冒泡排序的思路

一個有 8位元素的數組,讓它的第一位與後面每一位進行比較,前面一位小於後面的時候,位置不變,前面的大於後面的交換位置,就這樣一共要比七趟(最後一趟不要比,就剩一位,就是最小的);

實現原理以下圖:

image

10.2 按性能等級冒泡排序分3個等級

一、冒泡排序 60分:

var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
var tang = 0;
var ci = 0;
for (var i = 0; i < arr.length - 1; i++) {       // 外層for循環,循環的是比較的趟數,由於只要比較8趟 因此i判斷的條件爲length-1
    tang++;
    for (var j = 0; j < arr.length - 1; j++) {   // 內層for循環,循環的是比較的次數,每趟比較8次
        ci++;
        if (arr[j] > arr[j + 1]) {  // 判斷比較的兩個數,若是前面的大於後面的一位,交換位置
            var temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
}
console.log("趟數:" + tang);   // 8趟
console.log("次數:" + ci);     // 64次
console.log(arr);
}
  • 外層for循環,循環的是比較的趟數,由於只要比較8趟(數組長度爲9) 因此i判斷的條件爲length-1
  • 內層for循環,循環的是比較的次數,每趟比較8次,其實這裏次數多比較了,由於第一趟已經找到一個最大值了,第二趟就不須要比8次了 應該比7次,這裏先無論,下面會進行優化;
  • 判斷比較的兩個數,若是前面的大於後面的一位,交換位置。

測試代碼:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <span id="demo"></span><br/>
    <button id="stb">從小到大</button>
    <button id="bts">從大到小</button>
    <span id="show">
</span>
    <script>
        var demo = document.getElementById("demo");
        var show = document.getElementById("show");
        var bts = document.getElementById("bts");
        var stb = document.getElementById("stb");

        var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
        demo.innerHTML = arr;

        bts.onclick = function() {
            bubbleSort(function(a, b) {
                return b - a;
            });
        }
        stb.onclick = function() {
            bubbleSort(function(a, b) {
                return a - b;
            });
        }

        function bubbleSort(fn) {
            var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
            var strArr = [];
            show.innerHTML = "";
            strArr.push("<br/>");
            var inner = 0;
            var outer = 0;
            for (var i = 0; i < arr.length - 1; i++) {
                strArr.push("第" + (i + 1) + "趟");
                for (var j = 0; j < arr.length - 1; j++) {
                    if (fn(arr[j], arr[j + 1]) > 0) {
                        var tmp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = tmp;
                    }
                    inner++;
                }
                strArr.push(arr.toString());
                strArr.push("共" + j + "次" + "<br/>");
                outer++;
            }
            strArr.push("外循環" + outer + "次");
            strArr.push("內循環" + inner + "次");
            show.innerHTML = strArr.join(" ");
        }
    </script>
</body>

</html>

image

每趟都比較8次?明顯是多餘了,下面進行優化

二、冒泡排序80分:

var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
var tang = 0;
var ci = 0;
for (var i = 0; i < arr.length - 1; i++) {
    tang++;
    for (var j = 0; j < arr.length - 1 - i; j++) {  // 第二趟只比了7次 依次遞減
        ci++;
        if (arr[j] > arr[j + 1]) {
            var temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
}
console.log("趟數:" + tang); // 8趟
console.log("次數:" + ci);   // 36次
console.log(arr);

i 是從下標0開始的,第一趟的時候i=0,比了8次,第二趟i=1,只須要比7次,第三趟i=2,只須要比6次...依次類推,因此 比的次數應該就是arr.length - 1 -i;

測試代碼:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <span id="demo"></span><br/>
    <button id="stb">從小到大</button>
    <button id="bts">從大到小</button>
    <span id="show">
</span>
    <script>
        var demo = document.getElementById("demo");
        var show = document.getElementById("show");
        var bts = document.getElementById("bts");
        var stb = document.getElementById("stb");

        var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];

        demo.innerHTML = arr;

        bts.onclick = function() {
            bubbleSort(function(a, b) {
                return b - a;
            });
        }
        stb.onclick = function() {
            bubbleSort(function(a, b) {
                return a - b;
            });
        }

        function bubbleSort(fn) {
            var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];

            var strArr = [];
            show.innerHTML = "";
            strArr.push("<br/>");
            var inner = 0;
            var outer = 0;
            for (var i = 0; i < arr.length - 1; i++) {
                strArr.push("第" + (i + 1) + "趟");
                for (var j = 0; j < arr.length - 1 - i; j++) {
                    if (fn(arr[j], arr[j + 1]) > 0) {
                        var tmp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = tmp;
                    }
                    inner++;
                }
                strArr.push(arr.toString());
                strArr.push("共" + j + "次" + "<br/>");
                outer++;
            }
            strArr.push("外循環" + outer + "次");
            strArr.push("內循環" + inner + "次");
            show.innerHTML = strArr.join(" ");
        }
    </script>
</body>

</html>

image

還有什麼能夠優化的嗎? 假如8個數在第3趟的時候就排好了,還須要繼續排嗎?

三、冒泡排序100分:

假設成立法(3步):

  • 假設成立
  • 想辦法推翻假設
  • 若是推翻不了,說明假設成立
var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];
var tang = 0;
var ci = 0;
for (var i = 0; i < arr.length - 1; i++) {
    var flag = true;   // 假設每一次進來都排好了
    tang++;
    for (var j = 0; j < arr.length - 1 - i; j++) {
        ci++;
        if (arr[j] > arr[j + 1]) {
            flag = false;        // 若是兩位比較還知足前面的比後面的大的時候,說明假設不成立
            var temp = arr[j];
            arr[j] = arr[j + 1];
            arr[j + 1] = temp;
        }
    }
    if (flag == true) {    // 最後判斷一下,若是假設推翻不了,就中止運行。
        break;
    }
}
console.log("趟數:" + tang);   // 4 趟
console.log("次數:" + ci);     // 26 次
console.log(arr);

當順序已經排好後,就不用再去執行趟數了;

測試代碼:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title></title>
</head>

<body>
    <span id="demo"></span><br/>
    <button id="stb">從小到大</button>
    <button id="bts">從大到小</button>
    <span id="show">
</span>
    <script>
        var demo = document.getElementById("demo");
        var show = document.getElementById("show");
        var bts = document.getElementById("bts");
        var stb = document.getElementById("stb");

        var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];

        demo.innerHTML = arr;

        bts.onclick = function() {
            bubbleSort(function(a, b) {
                return b - a;
            });
        }
        stb.onclick = function() {
            bubbleSort(function(a, b) {
                return a - b;
            });
        }

        function bubbleSort(fn) {
            var arr = [3, 1, 2, 5, 4, 8, 9, 7, 6];

            var strArr = [];
            show.innerHTML = "";
            strArr.push("<br/>");
            var inner = 0;
            var outer = 0;
            for (var i = 0; i < arr.length - 1; i++) {
                var sorted = true;
                strArr.push("第" + (i + 1) + "趟");
                for (var j = 0; j < arr.length - 1 - i; j++) {
                    if (fn(arr[j], arr[j + 1]) > 0) {
                        var tmp = arr[j];
                        arr[j] = arr[j + 1];
                        arr[j + 1] = tmp;
                        sorted = false;
                    }
                    inner++;
                }
                strArr.push(arr.toString());
                strArr.push("共" + j + "次" + "<br/>");
                outer++;
                if (sorted) {
                    break;
                }
            }
            strArr.push("外循環" + outer + "次");
            strArr.push("內循環" + inner + "次");
            show.innerHTML = strArr.join(" ");
        }
    </script>
</body>

</html>

image

第三趟已經排好了,爲何還要排第四趟呢? 緣由很簡單,由於第三趟的時候js是不知道你已經排好的,只有第四趟的時候,js再進行換位比較的時候,發現位置都不須要換了,說明排好了。

下一篇:JavaScript 基礎知識 - 入門篇(二)

相關文章
相關標籤/搜索