07-JavaScript基礎語法
07-JavaScript基礎語法
01-變數
1 - 程式語言
1.1 程式設計
- 程式設計:
- 就是讓計算機為解決某個問題而使用某種程式設計語言編寫程式程式碼,並最終得到結果的過程。
- 計算機程式:
- 就是計算機所執行的一系列的指令集合,而程式全部都是用我們所掌握的語言來編寫的,所以人們要控制計算機一定要通過計算機語言向計算機發出命令。
1.2 計算機語言
-
計算機語言指用於人與計算機之間通訊的語言,它是人與計算機之間傳遞資訊的媒介。
-
計算機語言的種類非常的多,總的來說可以分成機器語言,組合語言和高階語言三大類。
-
實際上計算機最終所執行的都是 機器語言,它是由“0”和“1”組成的二進位制數,二進位制是計算機語言的基礎。
1.3 程式語言
程式語言:
可以通過類似於人類語言的“語言”來控制計算機,讓計算機為我們做事情,這樣的語言就叫做程式語言(Programming Language)。程式語言是用來控制計算機的一系列指令,它有固定的格式和詞彙(不同程式語言的格式和詞彙不一樣),必須遵守。如今通用的程式語言有兩種形式:組合語言和高階語言。
語言型別 | 說明 |
---|---|
組合語言 | 組合語言和機器語言實質是相同的,都是直接對硬體操作,只不過指令採用了英文縮寫的識別符號,容易識別和記憶。 |
高階語言 | 高階語言主要是相對於低階語言而言,它並不是特指某一種具體的語言,而是包括了很多程式語言,常用的有C語言、C++、Java、C#、Python、PHP、JavaScript、Go語言、Objective-C、Swift等。 |
1.4 翻譯器
高階語言所編制的程式不能直接被計算機識別,必須經過轉換才能被執行,為此,我們需要一個翻譯器。翻譯器可以將我們所編寫的原始碼轉換為機器語言,這也被稱為二進位制化。
1.5 程式語言和標記語言區別
語言 | 說明 |
---|---|
程式語言 | 程式語言有很強的邏輯和行為能力。在程式語言裡, 你會看到很多 if else 、for 、while等具有邏輯性和行為能力的指令,這是主動的。 |
標記語言 | 標記語言(html)不用於向計算機發出指令,常用於格式化和連結。標記語言的存在是用來被讀取的, 他是被動的。 |
總結
- 計算機可以幫助人類解決某些問題
- 程式設計師利用程式語言編寫程式發出指令控制計算機來實現這些任務
- 程式語言有機器語言、組合語言、高階語言
- 高階語言需要一個翻譯器轉換為計算機識別的機器語言
- 程式語言是主動的有很強的邏輯性
2 - 計算機基礎
2.1 計算機組成
2.2 資料儲存
- 計算機內部使用二進位制 0 和 1來表示資料。
- 所有資料,包括檔案、圖片等最終都是以二進位制資料(0 和 1)的形式存放在硬碟中的。
- 所有程式,包括作業系統,本質都是各種資料,也以二進位制資料的形式存放在硬碟中。平時我們所說的安裝軟體,其實就是把程式檔案複製到硬碟中。
- 硬碟、記憶體都是儲存的二進位制資料。
2.3 資料儲存單位
大小關係:bit < byte < kb < GB < TB<.....
- 位(bit): 1bit 可以儲存一個 0 或者 1 (最小的儲存單位)
- 位元組(Byte):1B = 8b
- 千位元組(KB):1KB = 1024B
- 兆位元組(MB):1MB = 1024KB
- 吉位元組(GB): 1GB = 1024MB
- 太位元組(TB): 1TB = 1024GB
2.4 程式執行
計算機執行軟體的過程:
- 開啟某個程式時,先從硬碟中把程式的程式碼載入到記憶體中
- CPU執行記憶體中的程式碼
注意:之所以要記憶體的一個重要原因,是因為 cpu執行太快了,如果只從硬碟中讀資料,會浪費cpu效能,所以,才使用存取速度更快的記憶體來儲存執行時的資料。(記憶體是電,硬碟是機械)
3 - 初始JavaScript
3.1 JavaScript 是什麼
-
JavaScript 是世界上最流行的語言之一,是一種執行在客戶端的指令碼語言 (Script 是指令碼的意思)
-
指令碼語言:不需要編譯,執行過程中由 js 直譯器( js 引擎)逐行來進行解釋並執行
-
現在也可以基於 Node.js 技術進行伺服器端程式設計
3.2 JavaScript的作用
- 表單動態校驗(密碼強度檢測) ( JS 產生最初的目的 )
- 網頁特效
- 服務端開發(Node.js)
- 桌面程式(Electron)
- App(Cordova)
- 控制硬體-物聯網(Ruff)
- 遊戲開發(cocos2d-js)
3.3 HTML/CSS/JS 的關係
3.4 瀏覽器執行 JS 簡介
瀏覽器分成兩部分:渲染引擎和 JS 引擎
瀏覽器本身並不會執行JS程式碼,而是通過內建 JavaScript 引擎(直譯器) 來執行 JS 程式碼 。JS 引擎執行程式碼時逐行解釋每一句原始碼(轉換為機器語言),然後由計算機去執行,所以 JavaScript 語言歸為指令碼語言,會逐行解釋執行。
3.5 JS的組成
1.ECMAScript
ECMAScript 是由ECMA 國際( 原歐洲計算機制造商協會)進行標準化的一門程式語言,這種語言在全球資訊網上應用廣泛,它往往被稱為 JavaScript或 JScript,但實際上後兩者是 ECMAScript 語言的實現和擴充套件。
ECMAScript:規定了JS的程式設計語法和基礎核心知識,是所有瀏覽器廠商共同遵守的一套JS語法工業標準。
更多參看MDN: MDN手冊
2. DOM——文件物件模型
文件物件模型(DocumentObject Model,簡稱DOM),是W3C組織推薦的處理可擴充套件標記語言的標準程式設計介面。通過 DOM 提供的介面可以對頁面上的各種元素進行操作(大小、位置、顏色等)
3. BOM——瀏覽器物件模型
瀏覽器物件模型(Browser Object Model,簡稱BOM) 是指瀏覽器物件模型,它提供了獨立於內容的、可以與瀏覽器視窗進行互動的物件結構。通過BOM可以操作瀏覽器視窗,比如彈出框、控制瀏覽器跳轉、獲取解析度等。
3.6 JS 初體驗
JS 有3種書寫位置,分別為行內、內嵌和外部。
1. 行內式
<input type="button" value="點我試試" onclick="alert('Hello World')" />
- 可以將單行或少量 JS 程式碼寫在HTML標籤的事件屬性中(以 on 開頭的屬性),如:onclick
- 注意單雙引號的使用:在HTML中我們推薦使用雙引號, JS 中我們推薦使用單引號
- 可讀性差, 在html中編寫JS大量程式碼時,不方便閱讀;
- 引號易錯,引號多層巢狀匹配時,非常容易弄混;
- 特殊情況下使用
2. 內嵌式
<script>
alert('Hello World~!');
</script>
- 可以將多行JS程式碼寫到 script 標籤中
- 內嵌 JS 是學習時常用的方式
3. 外部JS檔案
<script src="my.js"></script>
- 利於HTML頁面程式碼結構化,把大段 JS程式碼獨立到 HTML 頁面之外,既美觀,也方便檔案級別的複用
- 引用外部 JS檔案的 script 標籤中間不可以寫程式碼
- 適合於JS 程式碼量比較大的情況
4 - JavaScript註釋
- flex子專案佔的份數
- align-self控制子項自己在側軸的排列方式
- order屬性定義子項的排列順序(前後順序)
4.1 單行註釋
為了提高程式碼的可讀性,JS與CSS一樣,也提供了註釋功能。
JS中的註釋主要有兩種,分別是 單行註釋 和 多行註釋。
單行註釋的註釋方式如下:
// 我是一行文字,不想被 JS引擎 執行,所以 註釋起來
// 用來註釋單行文字( 快捷鍵 ctrl + / )
4.2 多行註釋
多行註釋的註釋方式如下:
/*
獲取使用者年齡和姓名
並通過提示框顯示出來
*/
/* */ 用來註釋多行文字( 預設快捷鍵 alt + shift + a )
快捷鍵修改為: ctrl + shift + /
vscode → 首選項按鈕 → 鍵盤快捷方式 → 查詢 原來的快捷鍵 → 修改為新的快捷鍵 → 回車確認
5 - JavaScript輸入輸出語句
為了方便資訊的輸入輸出,JS中提供了一些輸入輸出語句,其常用的語句如下:
方法 | 說明 | 歸屬 |
---|---|---|
alert(msg) | 瀏覽器彈出警示框 | 瀏覽器 |
console.log(msg) | 瀏覽器控制檯列印輸出資訊 | 瀏覽器 |
prompt(info) | 瀏覽器彈出輸入框,使用者可以輸入 | 瀏覽器 |
- 注意:alert() 主要用來顯示訊息給使用者,console.log() 用來給程式設計師自己看執行時的訊息。prompt取過來的值是字元型。
6 - 變數的概念
6.1 什麼是變數
白話:變數就是一個裝東西的盒子。
通俗:變數是用於存放資料的容器。 我們通過 變數名 獲取資料,甚至資料可以修改。
6.2 變數在記憶體中的儲存
本質:變數是程式在記憶體中申請的一塊用來存放資料的空間。類似我們酒店的房間,一個房間就可以看做是一個變數。
7 - 變數的使用
- 變數的宣告
- 變數的賦值
7.1 宣告變數
// 宣告變數
var age; // 宣告一個 名稱為age 的變數
-
var 是一個 JS關鍵字,用來宣告變數( variable 變數的意思 )。使用該關鍵字宣告變數後,計算機會自動為變數分配記憶體空間,不需要程式設計師管
-
age 是程式設計師定義的變數名,我們要通過變數名來訪問記憶體中分配的空間
7.2 賦值
age = 10; // 給 age 這個變數賦值為 10
- = 用來把右邊的值賦給左邊的變數空間中 此處代表賦值的意思
- 變數值是程式設計師儲存到變數空間裡的值
7.3 變數的初始化
var age = 18; // 宣告變數同時賦值為 18
// 宣告一個變數並賦值, 我們稱之為變數的初始化。
7.4 變數語法擴充套件
-
更新變數
一個變數被重新復賦值後,它原有的值就會被覆蓋,變數值將以最後一次賦的值為準。
var age = 18; age = 81; // 最後的結果就是81因為18 被覆蓋掉了
-
同時宣告多個變數
同時宣告多個變數時,只需要寫一個 var, 多個變數名之間使用英文逗號隔開。
var age = 10, name = 'zs', sex = 2;
-
宣告變數特殊情況
情況 說明 結果 var age ; console.log (age); 只宣告 不賦值 undefined console.log(age) 不宣告 不賦值 直接使用 報錯 age = 10; console.log (age); 不宣告 只賦值 10
7.5 變數命名規範
規則:
- 由字母(A-Za-z)、數字(0-9)、下劃線(_)、美元符號( $ )組成,如:usrAge, num01, _name
- 嚴格區分大小寫。var app; 和 var App; 是兩個變數
- 不能 以數字開頭。 18age 是錯誤的
- 不能 是關鍵字、保留字。例如:var、for、while
- 變數名必須有意義。 MMD BBD nl → age
- 儘量不使用name作為變數名,因為name在網站中有特殊含義
- 遵守駝峰命名法。首字母小寫,後面單詞的首字母需要大寫。myFirstName
推薦翻譯網站: 有道 愛詞霸
8 - 資料型別
8.1 資料型別簡介
-
為什麼需要資料型別
在計算機中,不同的資料所需佔用的儲存空間是不同的,為了便於把資料分成所需記憶體大小不同的資料,充分利用儲存空間,於是定義了不同的資料型別。
簡單來說,資料型別就是資料的類別型號。比如姓名“張三”,年齡18,這些資料的型別是不一樣的。
-
變數的資料型別
變數是用來儲存值的所在處,它們有名字和資料型別。變數的資料型別決定了如何將代表這些值的位儲存到計算機的記憶體中。JavaScript 是一種弱型別或者說動態語言。這意味著不用提前宣告變數的型別,在程式執行過程中,型別會被自動確定:
var age = 10; // 這是一個數字型 var areYouOk = '是的'; // 這是一個字串
在程式碼執行時,變數的資料型別是由 JS引擎 根據 = 右邊變數值的資料型別來判斷 的,執行完畢之後, 變數就確定了資料型別。JavaScript 擁有動態型別,同時也意味著相同的變數可用作不同的型別:
var x = 6; // x 為數字 var x = "Bill"; // x 為字串
-
資料型別的分類
JS 把資料型別分為兩類:
-
簡單資料型別 (Number,String,Boolean,Undefined,Null,Symbol)
-
複雜資料型別 (object)
-
8.2 簡單資料型別
簡單資料型別(基本資料型別)7+1
JavaScript 中的簡單資料型別及其說明如下:
簡單資料型別 | 說明 | 預設值 |
---|---|---|
Number | 數字型,包含整型值和浮點型值,如21、0.21 | 0 |
Boolean | 布林值型別,如true、false,等價於1和0 | false |
String | 字串型別,如“張三” 注意咱們js裡面,字串都帶引號 | “” |
Undefined | var a; 聲明瞭變數a但是沒有給值,此時a=undefined | undefined |
Null | var a=null;聲明瞭變數a為空值,使用null通常是想強調說這裡本應該是一個物件 | null |
bigInt | 用於任意長度的整數 | |
Symbol | Symbol(符號)是ES6 引入了一種新的原始資料型別,表示獨一無二的值。 |
數字型 Number
JavaScript 數字型別既可以儲存整數,也可以儲存小數(浮點數)。
var age = 21; // 整數
var Age = 21.3747; // 小數
1.數字型進位制
最常見的進位制有二進位制、八進位制、十進位制、十六進位制。
// 1.八進位制數字序列範圍:0~7
var num1 = 07; // 對應十進位制的7
var num2 = 010; // 對應十進位制的8
var num3 = 012; // 對應十進位制的10
// 2.十六進位制數字序列範圍:0~9以及A~F
var num = 0xA;
現階段我們只需要記住,在JS中八進位制前面加0,十六進位制前面加 0x
2.數字型範圍
JavaScript中數值的最大和最小值
-
最大值:Number.MAX_VALUE,這個值為: 1.7976931348623157e+308
-
最小值:Number.MIN_VALUE,這個值為:5e-32
3.數字型三個特殊值
-
Infinity ,代表無窮大,大於任何數值
-
-Infinity ,代表無窮小,小於任何數值
-
NaN ,Not a number,代表一個非數字值
4.isNaN
用來判斷一個變數是否為非數字的型別,返回 true 或者 false
var usrAge = 21;
var isOk = isNaN(userAge);
console.log(isNum); // false ,21 不是一個非數字
var usrName = "andy";
console.log(isNaN(userName));// true ,"andy"是一個非數字
字串型 String
字串型可以是引號中的任意文字,其語法為 雙引號 "" 和 單引號''
var strMsg = "我愛北京天安門~"; // 使用雙引號表示字串
var strMsg2 = '我愛吃豬蹄~'; // 使用單引號表示字串
// 常見錯誤
var strMsg3 = 我愛大肘子; // 報錯,沒使用引號,會被認為是js程式碼,但js沒有這些語法
因為 HTML 標籤裡面的屬性使用的是雙引號,JS 這裡我們更推薦使用單引號。
-
字串引號巢狀
JS 可以用單引號巢狀雙引號 ,或者用雙引號巢狀單引號 (外雙內單,外單內雙)
var strMsg = '我是"高帥富"程式猿'; // 可以用''包含"" var strMsg2 = "我是'高帥富'程式猿"; // 也可以用"" 包含'' // 常見錯誤 var badQuotes = 'What on earth?"; // 報錯,不能 單雙引號搭配
-
字串轉義符
類似HTML裡面的特殊字元,字串中也有特殊字元,我們稱之為轉義符。
轉義符都是 \ 開頭的,常用的轉義符及其說明如下:
轉義符 解釋說明 \n 換行符,n 是 newline 的意思 \ \ 斜槓 \ \' ' 單引號 \" ”雙引號 \t tab 縮排 \b 空格 ,b 是 blank 的意思 -
字串長度
字串是由若干字元組成的,這些字元的數量就是字串的長度。通過字串的 length 屬性可以獲取整個字串的長度。
var strMsg = "我是帥氣多金的程式猿!"; alert(strMsg.length); // 顯示 11
-
字串拼接
-
多個字串之間可以使用 + 進行拼接,其拼接方式為 字串 + 任何型別 = 拼接之後的新字串
-
拼接前會把與字串相加的任何型別轉成字串,再拼接成一個新的字串
//1.1 字串 "相加" alert('hello' + ' ' + 'world'); // hello world //1.2 數值字串 "相加" alert('100' + '100'); // 100100 //1.3 數值字串 + 數值 alert('11' + 12); // 1112
- + 號總結口訣:數值相加 ,字元相連
-
-
字串拼接加強
console.log('pink老師' + 18); // 只要有字元就會相連 var age = 18; console.log('pink老師age歲啦'); // 這樣不行哦 console.log('pink老師' + age); // pink老師18 console.log('pink老師' + age + '歲啦'); // pink老師18歲啦
- 經常會將字串和變數來拼接,變數可以很方便地修改裡面的值
- 變數是不能新增引號的,因為加引號的變數會變成字串
- 如果變數兩側都有字串拼接,口訣“引引加加 ”,刪掉數字,變數寫加中間
布林型Boolean
布林型別有兩個值:true 和 false ,其中 true 表示真(對),而 false 表示假(錯)。
布林型和數字型相加的時候, true 的值為 1 ,false 的值為 0。
console.log(true + 1); // 2
console.log(false + 1); // 1
Undefined和 Null
一個聲明後沒有被賦值的變數會有一個預設值undefined ( 如果進行相連或者相加時,注意結果)
js中用undefined代表一些預設的情況或預設沒有值的情況
var variable;
console.log(variable); // undefined
console.log('你好' + variable); // 你好undefined
console.log(11 + variable); // NaN
console.log(true + variable); // NaN
一個宣告變數給 null 值,裡面存的值為空(學習物件時,我們繼續研究null)
注:使用null通常是想強調說這裡本應該是一個物件,但這個物件還不存在的時候
var vari = null;
console.log('你好' + vari); // 你好null
console.log(11 + vari); // 11
console.log(true + vari); // 1
8.3 獲取變數資料型別
-
獲取檢測變數的資料型別
typeof 可用來獲取檢測變數的資料型別
var num = 18; console.log(typeof num) // 結果 number
不同型別的返回值
型別 例 結果 String typeof "小白" "string" Number typeof 18 "number" Boolean typeof true "boolean" Undefined typeof undefined "undefined" Null typeof null "object" 從控制檯顏色判斷資料型別
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <script> console.log(18); console.log('18'); console.log(true); console.log(undefined); console.log(null); </script> </head> <body> </body> </html>
從上往下分別為Number、String、Boolean、Undefined、Null型
-
字面量
字面量是在原始碼中一個固定值的表示法,通俗來說,就是字面量表示如何表達這個值。
- 數字字面量:8, 9, 10
- 字串字面量:'黑馬程式設計師', "大前端"
- 布林字面量:true,false
8.4 資料型別轉換
什麼是資料型別轉換?
使用表單、prompt 獲取過來的資料預設是字串型別的,此時就不能直接簡單的進行加法運算,而需要轉換變數的資料型別。通俗來說,就是把一種資料型別的變數轉換成另一種資料型別,通常會實現3種方式的轉換:
轉換為字串型別
轉換為數字型
轉換為布林型
-
轉換為字串
- toString() 和 String() 使用方式不一樣。
- 三種轉換方式,更多第三種加號拼接字串轉換方式, 這一種方式也稱之為隱式轉換。
-
轉換為數字型(重點)
方式 說明 案例 parseInt(string) 函式 將string型別轉成整數數值型 parseInt('78') parseFloat(string) 函式 將string型別轉成浮點數數值型 parseFloat('78.21') Number() 強制轉換函式 將string型別轉為數值型 Number('12') js隱式轉換(+ - * /) 利用算術運算隱式轉換為數值型 '12'-0;+'1' %也可以隱式轉換為數值型
- 注意 parseInt 和 parseFloat 單詞的大小寫,這2個是重點
- 隱式轉換是我們在進行算數運算的時候,JS 自動轉換了資料型別
-
轉換為布林型
-
代表空、否定的值會被轉換為 false ,如 ''、0、NaN、null、undefined
-
其餘值都會被轉換為 true
console.log(Boolean('')); // false console.log(Boolean(0)); // false console.log(Boolean(NaN)); // false console.log(Boolean(null)); // false console.log(Boolean(undefined)); // false console.log(Boolean('小白')); // true console.log(Boolean(12)); // true
-
9 - 解釋型語言和編譯型語言
9.1 概述
計算機不能直接理解任何除機器語言以外的語言,所以必須要把程式設計師所寫的程式語言翻譯成機器語言才能執行程式。程式語言翻譯成機器語言的工具,被稱為翻譯器。
- 翻譯器翻譯的方式有兩種:一個是編譯,另外一個是解釋。兩種方式之間的區別在於翻譯的時間點不同
- 編譯器是在程式碼執行之前進行編譯,生成中間程式碼檔案
- 直譯器是在執行時進行及時解釋,並立即執行(當編譯器以解釋方式執行的時候,也稱之為直譯器)
9.2 執行過程
類似於請客吃飯:
編譯語言:首先把所有菜做好,才能上桌吃飯
解釋語言:好比吃火鍋,邊吃邊涮,同時進行
10 - 關鍵字和保留字
10.1 識別符號
標識(zhi)符:就是指開發人員為變數、屬性、函式、引數取的名字。
識別符號不能是關鍵字或保留字。
10.2 關鍵字
關鍵字:是指 JS本身已經使用了的字,不能再用它們充當變數名、方法名。
包括:break、case、catch、continue、default、delete、do、else、finally、for、function、if、in、instanceof、new、return、switch、this、throw、try、typeof、var、void、while、with 等。
10.3 保留字
保留字:實際上就是預留的“關鍵字”,意思是現在雖然還不是關鍵字,但是未來可能會成為關鍵字,同樣不能使用它們當變數名或方法名。
包括:boolean、byte、char、class、const、debugger、double、enum、export、extends、fimal、float、goto、implements、import、int、interface、long、mative、package、private、protected、public、short、static、super、synchronized、throws、transient、volatile 等。
注意:如果將保留字用作變數名或函式名,那麼除非將來的瀏覽器實現了該保留字,否則很可能收不到任何錯誤訊息。當瀏覽器將其實現後,該單詞將被看做關鍵字,如此將出現關鍵字錯誤。
02-運算子
1 - 運算子(操作符)
1.1 運算子的分類
運算子(operator)也被稱為操作符,是用於實現賦值、比較和執行算數運算等功能的符號。
JavaScript中常用的運算子有:
- 算數運算子
- 遞增和遞減運算子
- 比較運算子
- 邏輯運算子
- 賦值運算子
1.2 算數運算子
-
算術運算子概述
概念:算術運算使用的符號,用於執行兩個變數或值的算術運算。
-
浮點數的精度問題
浮點數值的最高精度是 17 位小數,但在進行算術計算時其精確度遠遠不如整數。
var result = 0.1 + 0.2; // 結果不是 0.3,而是:0.30000000000000004 console.log(0.07 * 100); // 結果不是 7, 而是:7.000000000000001
所以:不要直接判斷兩個浮點數是否相等 !
-
表示式和返回值
表示式:是由數字、運算子、變數等以能求得數值的有意義排列方法所得的組合
簡單理解:是由數字、運算子、變數等組成的式子
表示式最終都會有一個結果,返回給開發者,稱為返回值
1.3 遞增和遞減運算子
-
遞增和遞減運算子概述
如果需要反覆給數字變數新增或減去1,可以使用遞增(++)和遞減( -- )運算子來完成。
在 JavaScript 中,遞增(++)和遞減( -- )既可以放在變數前面,也可以放在變數後面。放在變數前面時,我們可以稱為前置遞增(遞減)運算子,放在變數後面時,我們可以稱為後置遞增(遞減)運算子。
注意:遞增和遞減運算子必須和變數配合使用。
-
遞增運算子
-
前置遞增運算子
++num 前置遞增,就是自加1,類似於 num = num + 1,但是 ++num 寫起來更簡單。
使用口訣:先自加,後返回值
var num = 10; alert(++num + 10); // 21
-
後置遞增運算子
num++ 後置遞增,就是自加1,類似於 num = num + 1 ,但是 num++ 寫起來更簡單。
使用口訣:先返回原值,後自加
var num = 10; alert(10 + num++); // 20
-
1.4 比較運算子
-
比較運算子概述
概念:比較運算子(關係運算符)是兩個資料進行比較時所使用的運算子,比較運算後,會返回一個布林值(true / false)作為比較運算的結果。
運算子名稱 說明 例項 結果 < 小於號 1<2 true > 大於號 1>2 false >= 大於等於號(大於或者等於) 2>=2 true <= 小於等於號(小於或者等於) 3<=2 false == 判等號(會轉型) 37==37 true != 不等號 37!=37 false === !== 全等 要求值和資料型別都一致 37==='37' false -
等號比較
符號 作用 用法 = 賦值 把右邊給左邊 == 判斷 判斷兩邊值是否相等(注意此時有隱式轉換) === 全等 判斷兩邊的值和資料型別是否完全相同 console.log(18 == '18');//true,預設轉換資料型別 會把字串型的資料轉換為數字型 console.log(18 === '18'); //flase
1.5 邏輯運算子
-
邏輯運算子概述
概念:邏輯運算子是用來進行布林值運算的運算子,其返回值也是布林值。後面開發中經常用於多個條件的判斷
-
邏輯與&&
兩邊都是 true才返回 true,否則返回 false
-
邏輯或 ||
兩邊都是 true才返回 true,否則返回 false
-
邏輯非 !
邏輯非(!)也叫作取反符,用來取一個布林值相反的值,如 true 的相反值是 false
var isOk = !true; console.log(isOk); // false
-
短路運算(邏輯中斷)
短路運算的原理:當有多個表示式(值)時,左邊的表示式值可以確定結果時,就不再繼續運算右邊的表示式的值;
-
邏輯與
語法: 表示式1 && 表示式2
-
如果第一個表示式的值為真,則返回表示式2
-
如果第一個表示式的值為假,則返回表示式1
console.log( 123 && 456 ); // 456 console.log( 0 && 456 ); // 0 console.log(0 && 1 + 2 && 456 * 56789);// 0 console.log( 123 && 456&& 789 ); // 789
-
-
-
邏輯或
語法: 表示式1 || 表示式2
-
如果第一個表示式的值為真,則返回表示式1
-
如果第一個表示式的值為假,則返回表示式2
console.log( 123 || 456 ); // 123 console.log( 0 || 456 ); // 456 console.log( 123 || 456 || 789 ); // 123
-
1.6 賦值運算子
概念:用來把資料賦值給變數的運算子。
var age = 10;
age += 5; // 相當於 age = age + 5;
age -= 5; // 相當於 age = age - 5;
age *= 10; // 相當於 age = age * 10;
1.7 運算子優先順序
- 一元運算子裡面的邏輯非優先順序很高
- 邏輯與比邏輯或優先順序高
2 - 流程控制
2.1 流程控制概念
在一個程式執行的過程中,各條程式碼的執行順序對程式的結果是有直接影響的。很多時候我們要通過控制程式碼的執行順序來實現我們要完成的功能。
簡單理解:**流程控制就是來控制程式碼按照一定結構順序來執行**
流程控制主要有三種結構,分別是**順序結構**、**分支結構**和**迴圈結構**,代表三種程式碼執行的順序。
2.2 順序流程控制
順序結構是程式中最簡單、最基本的流程控制,它沒有特定的語法結構,程式會按照程式碼的先後順序,依次執行,程式中大多數的程式碼都是這樣執行的。
2.3 分支流程控制
-
分支結構
由上到下執行程式碼的過程中,根據不同的條件,執行不同的路徑程式碼(執行程式碼多選一的過程),從而得到不同的結果
JS 語言提供了兩種分支結構語句:if 語句、switch 語句
-
if 語句
- 語法結構
// 條件成立執行程式碼,否則什麼也不做 if (條件表示式) { // 條件成立執行的程式碼語句 }
語句可以理解為一個行為,迴圈語句和分支語句就是典型的語句。一個程式由很多個語句組成,一般情況下,會分割成一個一個的語句。
-
執行流程
-
if else語句(雙分支語句)
-
語法結構
// 條件成立 執行 if 裡面程式碼,否則執行else 裡面的程式碼 if (條件表示式) { // [如果] 條件成立執行的程式碼 } else { // [否則] 執行的程式碼 }
-
執行流程
-
-
if else if 語句(多分支語句)
-
語法結構
// 適合於檢查多重條件。 if (條件表示式1) { 語句1; } else if (條件表示式2) { 語句2; } else if (條件表示式3) { 語句3; .... } else { // 上述條件都不成立執行此處程式碼 }
-
執行邏輯
-
2.4 三元表示式
-
語法結構
表示式1 ? 表示式2 : 表示式3;
-
執行思路
- 如果表示式1為 true ,則返回表示式2的值,如果表示式1為 false,則返回表示式3的值
- 簡單理解: 就類似於 if else (雙分支) 的簡寫
2.5 switch分支流程控制
-
語法結構
switch 語句也是多分支語句,它用於基於不同的條件來執行不同的程式碼。當要針對變數設定一系列的特定值的選項時,就可以使用 switch。
switch( 表示式 ){ case value1: // 表示式 等於 value1 時要執行的程式碼 break; case value2: // 表示式 等於 value2 時要執行的程式碼 break; default: // 表示式 不等於任何一個 value 時要執行的程式碼 }
-
switch :開關 轉換 , case :小例子 選項
-
關鍵字 switch 後面括號內可以是表示式或值, 通常是一個變數
-
關鍵字 case , 後跟一個選項的表示式或值,後面跟一個冒號
-
switch 表示式的值會與結構中的 case 的值做比較
-
如果存在匹配全等(===) ,則與該 case 關聯的程式碼塊會被執行,並在遇到 break 時停止,整個 switch 語句程式碼執行結束
-
如果所有的 case 的值都和表示式的值不匹配,則執行 default 裡的程式碼
注意: 執行case 裡面的語句時,如果沒有break,則繼續執行下一個case裡面的語句。
-
-
switch 語句和 if else if 語句的區別
- 一般情況下,它們兩個語句可以相互替換
- switch...case 語句通常處理 case為比較確定值的情況, 而 if…else…語句更加靈活,常用於範圍判斷(大於、等於某個範圍)
- switch 語句進行條件判斷後直接執行到程式的條件語句,效率更高。而if…else 語句有幾種條件,就得判斷多少次。
- 當分支比較少時,if… else語句的執行效率比 switch語句高。
- 當分支比較多時,switch語句的執行效率比較高,而且結構更清晰。
03-迴圈
1 - 迴圈
1.1 for迴圈
-
語法結構
for(初始化變數; 條件表示式; 操作表示式 ){ //迴圈體 }
名稱 作用 初始化變數 通常被用於初始化一個計數器,該表示式可以使用 var 關鍵字宣告新的變數,這個變數幫我們來記錄次數。 條件表示式 用於確定每一次迴圈是否能被執行。如果結果是 true 就繼續迴圈,否則退出迴圈。 操作表示式 是每次迴圈最後執行的程式碼 經常用於我們計數器變數進行更新(遞增或者遞減) 執行過程:
- 初始化變數,初始化操作在整個 for 迴圈只會執行一次。
-
執行條件表示式,如果為true,則執行迴圈體語句,否則退出迴圈,迴圈結束。
- 執行操作表示式,此時第一輪結束。
- 第二輪開始,直接去執行條件表示式(不再初始化變數),如果為 true ,則去執行迴圈體語句,否則退出迴圈。
- 繼續執行操作表示式,第二輪結束。
- 後續跟第二輪一致,直至條件表示式為假,結束整個 for 迴圈。
斷點除錯:
斷點除錯是指自己在程式的某一行設定一個斷點,除錯時,程式執行到這一行就會停住,然後你可以一步一步往下除錯,除錯過程中可以看各個變數當前的值,出錯的話,除錯到出錯的程式碼行即顯示錯誤,停下。斷點除錯可以幫助觀察程式的執行過程
斷點除錯的流程:
1、瀏覽器中按 F12--> sources -->找到需要除錯的檔案-->在程式的某一行設定斷點
2、Watch: 監視,通過watch可以監視變數的值的變化,非常的常用。
3、摁下F11,程式單步執行,讓程式一行一行的執行,這個時候,觀察watch中變數的值的變化。
-
for 迴圈重複相同的程式碼
比如輸出10句“媳婦我錯了”
// 基本寫法 for(var i = 1; i <= 10; i++){ console.log('媳婦我錯了~'); } // 使用者輸入次數 var num = prompt('請輸入次數:'); for ( var i = 1 ; i <= num; i++) { console.log('媳婦我錯了~'); }
-
for 迴圈重複不相同的程式碼
例如,求輸出1到100歲:
// 基本寫法 for (var i = 1; i <= 100; i++) { console.log('這個人今年' + i + '歲了'); }
例如,求輸出1到100歲,並提示出生、死亡
// for 裡面是可以新增其他語句的 for (var i = 1; i <= 100; i++) { if (i == 1) { console.log('這個人今年1歲了, 它出生了'); } else if (i == 100) { console.log('這個人今年100歲了,它死了'); } else { console.log('這個人今年' + i + '歲了'); } }
for迴圈因為有了計數器的存在,還可以重複的執行某些操作,比如做一些算術運算。
1.2 雙重for迴圈
-
雙重 for 迴圈概述
迴圈巢狀是指在一個迴圈語句中再定義一個迴圈語句的語法結構,例如在for迴圈語句中,可以再巢狀一個for 迴圈,這樣的 for 迴圈語句我們稱之為雙重for迴圈。
-
雙重 for 迴圈語法
for (外迴圈的初始; 外迴圈的條件; 外迴圈的操作表示式) { for (內迴圈的初始; 內迴圈的條件; 內迴圈的操作表示式) { 需執行的程式碼; } }
- 內層迴圈可以看做外層迴圈的迴圈體語句
- 內層迴圈執行的順序也要遵循 for 迴圈的執行順序
- 外層迴圈執行一次,內層迴圈要執行全部次數
-
列印五行五列星星
var star = ''; for (var j = 1; j <= 3; j++) { for (var i = 1; i <= 3; i++) { star += '☆' } // 每次滿 5個星星 就 加一次換行 star += '\n' } console.log(star);
核心邏輯:
1.內層迴圈負責一行列印五個星星
2.外層迴圈負責列印五行
-
for 迴圈小結
- for 迴圈可以重複執行某些相同程式碼
- for 迴圈可以重複執行些許不同的程式碼,因為我們有計數器
- for 迴圈可以重複執行某些操作,比如算術運算子加法操作
- 隨著需求增加,雙重for迴圈可以做更多、更好看的效果
- 雙重 for 迴圈,外層迴圈一次,內層 for 迴圈全部執行
- for 迴圈是迴圈條件和數字直接相關的迴圈
1.3 while迴圈
while語句的語法結構如下:
while (條件表示式) {
// 迴圈體程式碼
}
執行思路:
- 1 先執行條件表示式,如果結果為 true,則執行迴圈體程式碼;如果為 false,則退出迴圈,執行後面程式碼
- 2 執行迴圈體程式碼
- 3 迴圈體程式碼執行完畢後,程式會繼續判斷執行條件表示式,如條件仍為true,則會繼續執行迴圈體,直到迴圈條件為 false 時,整個迴圈過程才會結束
注意:
- 使用 while 迴圈時一定要注意,它必須要有退出條件,否則會成為死迴圈
1.4 do-while迴圈
do... while 語句的語法結構如下:
do {
// 迴圈體程式碼 - 條件表示式為 true 時重複執行迴圈體程式碼
} while(條件表示式);
執行思路
-
1 先執行一次迴圈體程式碼
-
2 再執行條件表示式,如果結果為 true,則繼續執行迴圈體程式碼,如果為 false,則退出迴圈,繼續執行後面程式碼
注意:先再執行迴圈體,再判斷,do…while迴圈語句至少會執行一次迴圈體程式碼
1.5 continue、break
continue 關鍵字用於立即跳出本次迴圈,繼續下一次迴圈(本次迴圈體中 continue 之後的程式碼就會少執行一次)。
例如,吃5個包子,第3個有蟲子,就扔掉第3個,繼續吃第4個第5個包子,其程式碼實現如下:
for (var i = 1; i <= 5; i++) {
if (i == 3) {
console.log('這個包子有蟲子,扔掉');
continue; // 跳出本次迴圈,跳出的是第3次迴圈
}
console.log('我正在吃第' + i + '個包子呢');
}
執行結果:
break 關鍵字用於立即跳出整個迴圈(迴圈結束)。
例如,吃5個包子,吃到第3個發現裡面有半個蟲子,其餘的不吃了,其程式碼實現如下:
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 直接退出整個for 迴圈,跳到整個for下面的語句
}
console.log('我正在吃第' + i + '個包子呢');
}
執行結果:
2 - 程式碼規範
2.1 識別符號命名規範
- 變數、函式的命名必須要有意義
- 變數的名稱一般用名詞
- 函式的名稱一般用動詞
2.2 操作符規範
// 操作符的左右兩側各保留一個空格
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 直接退出整個 for 迴圈,跳到整個for迴圈下面的語句
}
console.log('我正在吃第' + i + '個包子呢');
}
2.3 單行註釋規範
for (var i = 1; i <= 5; i++) {
if (i == 3) {
break; // 單行註釋前面注意有個空格
}
console.log('我正在吃第' + i + '個包子呢');
}
2.4 其他規範
關鍵詞、操作符之間後加空格
04-陣列
1 - 陣列
1.1 陣列的概念
- 陣列可以把一組相關的資料一起存放,並提供方便的訪問(獲取)方式。
- 陣列是指一組資料的集合,其中的每個資料被稱作元素,在陣列中可以存放任意型別的元素。陣列是一種將一組資料儲存在單個變數名下的優雅方式。
1.2 建立陣列
JS 中建立陣列有兩種方式:
-
利用 new 建立陣列
var 陣列名 = new Array(); var arr = new Array(); // 建立一個新的空陣列
注意 Array () ,A 要大寫
-
利用陣列字面量建立陣列
//1. 使用陣列字面量方式建立空的陣列 var 陣列名 = []; //2. 使用陣列字面量方式建立帶初始值的陣列 var 陣列名 = ['小白','小黑','大黃','瑞奇'];
- 陣列的字面量是方括號 [ ]
- 宣告陣列並賦值稱為陣列的初始化
- 這種字面量方式也是我們以後最多使用的方式
-
陣列元素的型別
陣列中可以存放任意型別的資料,例如字串,數字,布林值等。
var arrStus = ['小白',12,true,28.9];
1.3 獲取陣列中的元素
索引 (下標) :用來訪問陣列元素的序號(陣列下標從 0 開始)。
陣列可以通過索引來訪問、設定、修改對應的陣列元素,可以通過“陣列名[索引]”的形式來獲取陣列中的元素。
// 定義陣列
var arrStus = [1,2,3];
// 獲取陣列中的第2個元素
alert(arrStus[1]);
注意:如果訪問時陣列沒有和索引值對應的元素,則得到的值是undefined
1.4 遍歷陣列
-
陣列遍歷
把陣列中的每個元素從頭到尾都訪問一次(類似學生的點名),可以通過 for 迴圈索引遍歷陣列中的每一項
var arr = ['red','green', 'blue'];
for(var i = 0; i < arr.length; i++){
console.log(arrStus[i]);
}
-
陣列的長度
陣列的長度:預設情況下表示陣列中元素的個數
使用“陣列名.length”可以訪問陣列元素的數量(陣列長度)。
var arrStus = [1,2,3]; alert(arrStus.length); // 3
注意:
- 此處陣列的長度是陣列元素的個數 ,不要和陣列的索引號混淆。
-
當我們數組裡面的元素個數發生了變化,這個 length 屬性跟著一起變化
- 陣列的length屬性可以被修改:
-
如果設定的length屬性值大於陣列的元素個數,則會在陣列末尾出現空白元素;
- 如果設定的length屬性值小於陣列的元素個數,則會把超過該值的陣列元素刪除
1.5 陣列中新增元素
陣列中可以通過以下方式在陣列的末尾插入新元素:
陣列[ 陣列.length ] = 新資料;
1.6 案例
氣泡排序:(pink老師講的盡供參考,具體見個人部落格)
氣泡排序是一種簡單的排序演算法。它重複地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重複地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個演算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。
我們可以將陣列 [5, 4, 3, 2, 1]中的元素按照從小到大的順序排序,輸出: 1,2,3,4,5
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var arr = [5, 4, 3, 2, 1];
for (var i = 1; i < arr.length; i++) { //外層迴圈管趟數
for (var j = 0; j <= arr.length - i - 1; j++) { //裡面的迴圈管 每一趟的交換次數
//內部交換2個變數的值 前一個和後面一個數組元素相比較
if (arr[j] > arr[j + 1]) {
var temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
console.log(arr);
</script>
</head>
<body>
</body>
</html>
05-函式
2 - 函式
2.1 函式的概念
在 JS 裡面,可能會定義非常多的相同程式碼或者功能相似的程式碼,這些程式碼可能需要大量重複使用。雖然 for迴圈語句也能實現一些簡單的重複操作,但是比較具有侷限性,此時我們就可以使用 JS 中的函式。
函式:就是封裝了一段可被重複呼叫執行的程式碼塊。通過此程式碼塊可以實現大量程式碼的重複使用。
2.2 函式的使用
宣告函式
// 宣告函式
function 函式名() {
//函式體程式碼
}
-
function 是宣告函式的關鍵字,必須小寫
-
由於函式一般是為了實現某個功能才定義的, 所以通常我們將函式名命名為動詞,比如 getSum
呼叫函式
// 呼叫函式
函式名(); // 通過呼叫函式名來執行函式體程式碼
-
呼叫的時候千萬不要忘記新增小括號
-
口訣:函式不呼叫,自己不執行
注意:宣告函式本身並不會執行程式碼,只有呼叫函式時才會執行函式體程式碼。
函式的封裝
-
函式的封裝是把一個或者多個功能通過函式的方式封裝起來,對外只提供一個簡單的函式介面
-
簡單理解:封裝類似於將電腦配件整合組裝到機箱中 ( 類似快遞打包)
例子:封裝計算1-100累加和
/* 計算1-100之間值的函式 */ // 宣告函式 function getSum(){ var sumNum = 0;// 準備一個變數,儲存數字和 for (var i = 1; i <= 100; i++) { sumNum += i;// 把每個數值 都累加 到變數中 } alert(sumNum); } // 呼叫函式 getSum();
2.3 函式的引數
函式引數語法
-
形參:函式定義時設定接收呼叫時傳入
-
實參:函式呼叫時傳入小括號內的真實資料
引數的作用 : 在函式內部某些值不能固定,我們可以通過引數在呼叫函式時傳遞不同的值進去。
函式引數的運用:
// 帶引數的函式宣告 function 函式名(形參1, 形參2 , 形參3...) { // 可以定義任意多的引數,用逗號分隔 // 函式體 } // 帶引數的函式呼叫 函式名(實參1, 實參2, 實參3...);
- 呼叫的時候實參值是傳遞給形參的
- 形參簡單理解為:不用宣告的變數
- 實參和形參的多個引數之間用逗號(,)分隔
函式形參和實引數量不匹配時
注意:在JavaScript中,形參的預設值是undefined。
小結:
- 函式可以帶引數也可以不帶引數
- 宣告函式的時候,函式名括號裡面的是形參,形參的預設值為 undefined
- 呼叫函式的時候,函式名括號裡面的是實參
- 多個引數中間用逗號分隔
- 形參的個數可以和實參個數不匹配,但是結果不可預計,我們儘量要匹配
案例:求任意兩個數的和
<script>
// 求兩個數之間的和
function getSum(num1, num2) {
console.log(num1 + num2);
}
getSum(1, 2);
</script>
2.4 函式的返回值
return 語句
返回值:函式呼叫整體代表的資料;函式執行完成後可以通過return語句將指定資料返回 。
// 宣告函式
function 函式名(){
...
return 需要返回的值;
}
// 呼叫函式
函式名(); // 此時呼叫函式就可以得到函式體內return 後面的值
- 在使用 return 語句時,函式會停止執行,並返回指定的值
- 如果函式沒有 return ,返回的值是 undefined
break ,continue ,return 的區別
- break :結束當前的迴圈體(如 for、while)
- continue :跳出本次迴圈,繼續執行下次迴圈(如 for、while)
- return :不僅可以退出迴圈,還能夠返回 return 語句中的值,同時還可以結束當前的函式體內的程式碼
2.5 arguments的使用
當不確定有多少個引數傳遞的時候,可以用 arguments 來獲取。JavaScript 中,arguments實際上它是當前函式的一個內建物件。所有函式都內建了一個 arguments 物件,arguments 物件中儲存了傳遞的所有實參。arguments展示形式是一個偽陣列,因此可以進行遍歷。偽陣列具有以下特點:
-
具有 length 屬性
-
按索引方式儲存資料
-
不具有陣列的 push , pop 等方法
-
只有函式才有arguments物件 而且每個函式都內建好了這個arguments
注意:在函式內部使用該物件,用此物件獲取函式呼叫時傳的實參。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
// arguments 的使用 只有函式才有 arguments物件 而且是每個函式都內建好了這個arguments
function fn() {
// console.log(arguments); // 裡面儲存了所有傳遞過來的實參 arguments = [1,2,3]
// console.log(arguments.length);
// console.log(arguments[2]);
// 我們可以按照陣列的方式遍歷arguments
for (var i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
}
fn(1, 2, 3);
fn(1, 2, 3, 4, 5);
// 偽陣列 並不是真正意義上的陣列
// 1. 具有陣列的 length 屬性
// 2. 按照索引的方式進行儲存的
// 3. 它沒有真正陣列的一些方法 pop() push() 等等
</script>
</head>
<body>
</body>
</html>
2.6 函式案例
函式內部可以呼叫另一個函式,在同一作用域程式碼中,函式名即代表封裝的操作,使用函式名加括號即可以將封裝的操作執行。
翻轉任意一個數組
方法一:
function reverse() {
var newArr = [];
for (var i = arguments.length - 1; i >= 0; i--) {
arr[arr.length] = arguments[i];
}
return newArr;
}
console.log(reverse(1, 2, 3, 5, 4));
方法二:
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, 3, 4, 6, 9]);
console.log(arr1);
氣泡排序
2.7 函式的兩種宣告方式
-
自定義函式方式(命名函式)
利用函式關鍵字 function 自定義函式方式
// 宣告定義方式 function fn() {...} // 呼叫 fn();
- 因為有名字,所以也被稱為命名函式
- 呼叫函式的程式碼既可以放到宣告函式的前面,也可以放在宣告函式的後面
-
函式表示式方式(匿名函式)
利用函式表示式方式的寫法如下:
// 這是函式表示式寫法,匿名函式後面跟分號結束 var fn = function(){...}; // 呼叫的方式,函式呼叫必須寫到函式體下面 fn();
- 因為函式沒有名字,所以也被稱為匿名函式
- 這個fn 裡面儲存的是一個函式
- 函式表示式方式原理跟宣告變數方式是一致的
- 函式呼叫的程式碼必須寫到函式體後面
06-作用域
1-作用域
1.1 作用域概述
通常來說,一段程式程式碼中所用到的名字並不總是有效和可用的,而限定這個名字的可用性的程式碼範圍就是這個名字的作用域。作用域的使用提高了程式邏輯的區域性性,增強了程式的可靠性,減少了名字衝突。
JavaScript(es6前)中的作用域有兩種:
- 全域性作用域
- 區域性作用域(函式作用域)
1.2 全域性作用域
作用於所有程式碼執行的環境(整個 script 標籤內部)或者一個獨立的 js 檔案。
1.3 區域性作用域
作用於函式內的程式碼環境,就是區域性作用域。 因為跟函式有關係,所以也稱為函式作用域。
1.4 JS沒有塊級作用域
-
現階段js沒有塊級作用域,在es6的時候新增的塊級作用域
-
塊作用域由 { } 包括。
-
在其他程式語言中(如 java、c#等),在 if 語句、迴圈語句中建立的變數,僅僅只能在本 if 語句、本迴圈語句中使用,如下面的Java程式碼:
java有塊級作用域:
if(true){ int num = 123; system.out.print(num); // 123 } system.out.print(num); // 報錯
以上java程式碼會報錯,是因為程式碼中 { } 即一塊作用域,其中宣告的變數 num,在 “{ }” 之外不能使用;
而與之類似的JavaScript程式碼,則不會報錯:
Js中沒有塊級作用域(在ES6之前)
if(true){
var num = 123;
console.log(123); //123
}
console.log(123); //123
### 2-變數的作用域
在JavaScript中,根據作用域的不同,變數可以分為兩種:
- 全域性變數
- 區域性變數
2.1 全域性變數
在全域性作用域下宣告的變數叫做全域性變數(在函式外部定義的變數)。
- 全域性變數在程式碼的任何位置都可以使用
- 在全域性作用域下 var 宣告的變數 是全域性變數
- 特殊情況下,==在函式內不使用 var 宣告的變數也是全域性變數(不建議使用)==
2.2 區域性變數
在區域性作用域下宣告的變數叫做區域性變數(在函式內部定義的變數)
- 區域性變數只能在該函式內部使用
- 在函式內部 var 宣告的變數是區域性變數
- ==函式的形參實際上就是區域性變數==
2.3 全域性變數和區域性變數的區別
- 全域性變數:在任何一個地方都可以使用,只有在瀏覽器關閉時才會被銷燬,因此比較佔記憶體
- 區域性變數:只在函式內部使用,當其所在的程式碼塊被執行時,會被初始化;當代碼塊執行結束後,就會被銷燬,因此更節省記憶體空間
### 3 - 作用域鏈
只要是程式碼都一個作用域中,寫在函式內部的區域性作用域,未寫在任何函式內部即在全域性作用域中;如果函式中還有函式,那麼在這個作用域中就又可以誕生一個作用域;==根據在**[內部函式可以訪問外部函式變數]**的這種機制,用鏈式查詢決定哪些資料能被內部函式訪問,就稱作作用域鏈==
案例分析1:
```js
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();
作用域鏈:採取就近原則的方式來查詢變數最終的值。
var a = 1;
function fn1() {
var a = 2;
var b = '22';
fn2();
function fn2() {
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); //a的值 ?
console.log(b); //b的值 ?
}
}
}
fn1();
4 - 預解析
4.1 預解析的相關概念
JavaScript 程式碼是由瀏覽器中的 JavaScript 解析器來執行的。JavaScript 解析器在執行 JavaScript 程式碼的時候分為兩步:預解析和程式碼執行。
-
預解析:在當前作用域下, JS 程式碼執行之前,瀏覽器會預設把帶有 var 和 function 宣告的變數在記憶體中進行提前宣告或者定義。
-
程式碼執行: 從上到下執行JS語句。
預解析會把變數和函式的宣告在程式碼執行之前執行完成。
<script>
// 1問
console.log(num);
// 2問
console.log(num); // undefined 坑 1
var num = 10;
// 相當於執行了以下程式碼
// var num;
// console.log(num);
// num = 10;
// 3問
function fn() {
console.log(11);
}
fn();
// 4問
fun(); // 報錯 坑2
var fun = function() {
console.log(22);
}
// 函式表示式 呼叫必須寫在函式表示式的下面
// 相當於執行了以下程式碼
// var fun;
// fun();
// fun = function() {
// console.log(22);
// }
// 1. 我們js引擎執行js 分為兩步: 預解析 程式碼執行
// (1). 預解析 js引擎會把js 裡面所有的 var 還有 function 提升到當前作用域的最前面
// (2). 程式碼執行 按照程式碼書寫的順序從上往下執行
// 2. 預解析分為 變數預解析(變數提升) 和 函式預解析(函式提升)
// (1) 變數提升 就是把所有的變數宣告提升到當前的作用域最前面 不提升賦值操作
// (2) 函式提升 就是把所有的函式宣告提升到當前作用域的最前面 不呼叫函式
</script>
4.2 變數預解析
預解析也叫做變數、函式提升。
變數提升(變數預解析): 變數的宣告會被提升到當前作用域的最上面,變數的賦值不會提升。
console.log(num); // 結果是多少?
var num = 10; // ?
結果:undefined
注意:變數提升只提升宣告,不提升賦值
4.3 函式預解析
函式提升: 函式的宣告會被提升到當前作用域的最上面,但是不會呼叫函式。
fn();
function fn() {
console.log('列印');
}
結果:控制檯列印字串 --- ”列印“
注意:函式宣告代表函式整體,所以函式提升後,函式名代表整個函式,但是函式並沒有被呼叫!
4.4 函式表示式宣告函式問題
函式表示式建立函式,會執行變數提升,此時接收函式的變數名無法正確的呼叫:
fn();
var fn = function() {
console.log('想不到吧');
}
結果:報錯提示 ”fn is not a function"
解釋:該段程式碼執行之前,會做變數宣告提升,fn在提升之後的值是undefined;而fn呼叫是在fn被賦值為函式體之前,此時fn的值是undefined,所以無法正確呼叫
4.5 預解析案例
<script>
// 預解析案例
// 案例1
// 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();
// // 案例2
// 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();
// // 案例3
// 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();
// 案例4
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;
// // 相當於 var a = 9; b = 9; c = 9; b 和 c 直接賦值 沒有var 宣告 當 全域性變數看
// // 集體宣告 var a = 9, b = 9, c = 9;
// console.log(a);
// console.log(b);
// console.log(c);
// }
// f1();
// console.log(c);
// console.log(b);
// console.log(a);
</script>
5 - 物件
5.1 物件的相關概念
-
什麼是物件?
在 JavaScript 中,物件是一組無序的相關屬性和方法的集合,所有的事物都是物件,例如字串、數值、陣列、函式等。
物件是由屬性和方法組成的。-
屬性:事物的特徵,在物件中用屬性來表示(常用名詞)
-
方法:事物的行為,在物件中用方法來表示(常用動詞)
引數 說明 形參 形式上的引數 函式定義的時候傳遞的引數 當前並不知道是什麼 實參 實際上的引數 函式呼叫的時候傳遞的引數 實參是傳遞給形參的
-
-
為什麼需要物件?
儲存一個值時,可以使用變數,儲存多個值(一組值)時,可以使用陣列。
如果要儲存一個人的完整資訊呢?
例如,將“張三瘋”的個人的資訊儲存在陣列中的方式為:
var arr = [‘張三瘋’, ‘男', 128,154];
上述例子中用陣列儲存資料的缺點是:資料只能通過索引值訪問,開發者需要清晰的清除所有的資料的排行才能準確地獲取資料,而當資料量龐大時,不可能做到記憶所有資料的索引值。
為了讓更好地儲存一組資料,物件應運而生:物件中為每項資料設定了屬性名稱,可以訪問資料更語義化,資料結構清晰,表意明顯,方便開發者使用。
使用物件記錄上組資料為:
var obj = { "name":"張三瘋", "sex":"男", "age":128, "height":154 }
JS中的物件表達結構更清晰,更強大。
5.2 建立物件的三種方式
5.1.1 利用字面量建立物件
就是花括號 { } 裡面包含了表達這個具體事物(物件)的屬性和方法;{ } 裡面採取鍵值對的形式表示 ;多個屬性或者方法中間用逗號隔開的;方法冒號後面跟的是一個匿名函式
-
鍵:相當於屬性名
-
值:相當於屬性值,可以是任意型別的值(數字型別、字串型別、布林型別,函式型別等)
程式碼如下:
var star = { name : 'pink', age : 18, sex : '男', sayHi : function(){ alert('大家好啊~'); } };
上述程式碼中 star即是建立的物件。
-
物件的使用
-
物件的屬性
- 物件中儲存具體資料的 "鍵值對"中的 "鍵"稱為物件的屬性,即物件中儲存具體資料的項
-
物件的方法
- 物件中儲存函式的 "鍵值對"中的 "鍵"稱為物件的方法,即物件中儲存函式的項
-
訪問物件的屬性
-
物件裡面的屬性呼叫 : 物件.屬性名 ,這個小點 . 就理解為“ 的 ”
-
物件裡面屬性的另一種呼叫方式 : 物件[‘屬性名’],注意方括號裡面的屬性必須加引號
示例程式碼如下:
console.log(star.name) // 呼叫名字屬性 console.log(star['name']) // 呼叫名字屬性
-
-
呼叫物件的方法
-
物件裡面的方法呼叫:物件.方法名() ,注意這個方法名字後面一定加括號
示例程式碼如下:
star.sayHi(); // 呼叫 sayHi 方法,注意,一定不要忘記帶後面的括號
-
-
變數、屬性、函式、方法總結
屬性是物件的一部分,而變數不是物件的一部分,變數是單獨儲存資料的容器
- 變數:單獨宣告賦值,單獨存在
- 屬性:物件裡面的變數稱為屬性,不需要宣告,用來描述該物件的特徵
方法是物件的一部分,函式不是物件的一部分,函式是單獨封裝操作的容器
- 函式:單獨存在的,通過“函式名()”的方式就可以呼叫
- 方法:物件裡面的函式稱為方法,方法不需要宣告,使用“物件.方法名()”的方式就可以呼叫,方法用來描述該物件的行為和功能。
// 1.利用物件字面量建立物件 {}
// var obj = {}; // 建立了一個空的物件
var obj = {
uname: '張三瘋',
age: 18,
sex: '男',
sayHi: function() {
console.log('hi~');
}
}
// (1) 裡面的屬性或者方法我們採取鍵值對的形式 鍵 屬性名 : 值 屬性值
// (2) 多個屬性或者方法中間用逗號隔開的
// (3) 方法冒號後面跟的是一個匿名函式
// 2. 使用物件
// (1). 呼叫物件的屬性 我們採取 物件名.屬性名 . 我們理解為 的
console.log(obj.uname);
// (2). 呼叫屬性還有一種方法 物件名['屬性名']
console.log(obj['age']);
// (3) 呼叫物件的方法 sayHi 物件名.方法名() 千萬別忘記新增小括號
obj.sayHi();
5.1.2 利用 new Object 建立物件
-
建立空物件
var andy = new Object();
通過內建建構函式Object建立物件,此時andy變數已經儲存了創建出來的空物件
-
給空物件新增屬性和方法
-
通過物件操作屬性和方法的方式,來為物件增加屬性和方法
示例程式碼如下:
andy.name = 'pink'; andy.age = 18; andy.sex = '男'; andy.sayHi = function(){ alert('大家好啊~'); }
注意:
- Object() :第一個字母大寫
- new Object() :需要 new 關鍵字
- 使用的格式:物件.屬性 = 值;
-
5.1.3 利用建構函式建立物件
-
建構函式
-
建構函式:是一種特殊的函式,主要用來初始化物件,即為物件成員變數賦初始值,它總與 new 運算子一起使用。我們可以把物件中一些公共的屬性和方法抽取出來,然後封裝到這個函式裡面。
-
建構函式的封裝格式:
function 建構函式名(形參1,形參2,形參3) { this.屬性名1 = 引數1; this.屬性名2 = 引數2; this.屬性名3 = 引數3; this.方法名 = 函式體; }
-
建構函式的呼叫格式
var obj = new 建構函式名(實參1,實參2,實參3)
以上程式碼中,obj即接收到建構函式創建出來的物件。
-
注意事項
- 建構函式約定首字母大寫。
- 函式內的屬性和方法前面需要新增 this ,表示當前物件的屬性和方法。
- 建構函式中不需要 return 返回結果。
- 當我們建立物件的時候,必須用 new 來呼叫建構函式。
-
其他
建構函式,如 Stars(),抽象了物件的公共部分,封裝到了函式裡面,它泛指某一大類(class)
建立物件,如 new Stars(),特指某一個,通過 new 關鍵字建立物件的過程我們也稱為物件例項化
-
-
new關鍵字的作用
- 在建構函式程式碼開始執行之前,建立一個空物件;
- 修改this的指向,把this指向創建出來的空物件;
- 執行函式的程式碼
- 在函式完成之後,返回this---即創建出來的物件
5.3 遍歷物件
for...in 語句用於對陣列或者物件的屬性進行迴圈操作。
其語法如下:
for (變數 in 物件名字) {
// 在此執行程式碼
}
語法中的變數是自定義的,它需要符合命名規範,通常我們會將這個變數寫為 k 或者 key。
<script>
// 遍歷物件
var obj = {
name: 'pink老師',
age: 18,
sex: '男',
fn: function() {}
}
// console.log(obj.name);
// console.log(obj.age);
// console.log(obj.sex);
// for in 遍歷我們的物件
// for (變數 in 物件) {
// }
for (var k in obj) {
console.log(k); // k 變數 輸出 得到的是 屬性名
console.log(obj[k]); // obj[k] 得到是 屬性值
}
// 我們使用 for in 裡面的變數 我們喜歡寫 k 或者 key
</script>
5.4 物件小結
1.物件可以讓程式碼結構更清晰
2.物件複雜資料型別object
3.本質:物件就是一組無序的相關屬性和方法的集合
4.建構函式泛指某一大類,比如蘋果,不管是紅色蘋果還是綠色蘋果,都統稱為蘋果。
5.物件例項特指一個事物,比如這個蘋果、正在給你們講課的pink老師。
6.for...in語句用於對物件的屬性進行迴圈操作。
JS內建物件
學習目標:
能夠說出什麼是內建物件
能夠根據文件查詢指定API的使用方法
能夠使用Math物件的常用方法
能夠使用Date物件的常用方法
能夠使用Array物件的常用方法
能夠使用String物件的常用方法
1.內建物件
- JavaScript 中的物件分為3種:自定義物件 、內建物件、 瀏覽器物件
- 前面兩種物件是JS 基礎 內容,屬於 ECMAScript; 第三個瀏覽器物件屬於我們JS 獨有的, 我們JS API 講解
- 內建物件就是指 JS 語言自帶的一些物件,這些物件供開發者使用,並提供了一些常用的或是最基本而必要的功能(屬性和方法)
- 內建物件最大的優點就是幫助我們快速開發
- JavaScript 提供了多個內建物件:Math、 Date 、Array、String等
2.查文件
2.1 MDN
學習一個內建物件的使用,只要學會其常用成員的使用即可,我們可以通過查文件學習,可以通過MDN/W3C
來查詢。
Mozilla 開發者網路(MDN)提供了有關開放網路技術(Open Web)的資訊,包括 HTML、CSS 和全球資訊網及
HTML5 應用的 API。
MDN: https://developer.mozilla.org/zh-CN/
2.2 如何學習物件中的方法
-
查閱該方法的功能
-
檢視裡面引數的意義和型別
-
檢視返回值的意義和型別
-
通過 demo 進行測試
3. Math 物件
3.1 Math概述
Math 物件不是建構函式,它具有數學常數和函式的屬性和方法。跟數學相關的運算(求絕對值,取整、最大值
等)可以使用 Math 中的成員。
Math.PI // 圓周率
Math.floor() // 向下取整
Math.ceil() // 向上取整
Math.round() // 四捨五入版 就近取整 其他數字都是四捨五入,但是.5特殊 它往大了取,即 -3.5 結果是 -3
Math.abs() // 絕對值
Math.abs('-1')//隱式轉換 會把字串型 -1 轉換為數字型
Math.abs('pink')//NaN
Math.max()/Math.min() // 求最大和最小值
注意:上面的方法必須帶括號
案例:封裝自己的數學物件
利用物件封裝自己的數學物件 裡面有 PI 最大值和最小值
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
var myMath = {
PI: 3.14159,
max: function() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (max < arguments[i])
max = arguments[i];
}
return max;
},
min: function() {
var min = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (min > arguments[i])
min = arguments[i];
}
return min;
},
}
console.log(myMath.PI);
console.log(myMath.max(1, 4, 8));
console.log(myMath.min(1, 4, 8));
</script>
</head>
<body>
</body>
</html>
3.2 隨機數方法 random()
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Math/random
random() 方法可以隨機返回一個小數,其取值範圍是 [0,1),左閉右開 0 <= x < 1
得到一個兩數之間的隨機整數
function getRandomInt(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min)) + min; //不含最大值,含最小值
}
得到一個兩數之間的隨機整數,包括兩個數在內
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
案例:猜數字遊戲
程式隨機生成一個 1~ 10 之間的數字,並讓使用者輸入一個數字,
-
如果大於該數字,就提示,數字大了,繼續猜;
-
如果小於該數字,就提示數字小了,繼續猜;
-
如果等於該數字,就提示猜對了, 結束程式。
案例分析
① 隨機生成一個1~10 的整數 我們需要用到 Math.random() 方法。
② 需要一直猜到正確為止,所以一直迴圈。
③ 用while 迴圈合適更簡單。
④ 核心演算法:使用 if else if 多分支語句來判斷大於、小於、等於。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
// 猜數字遊戲
// 1.隨機生成一個1~10 的整數 我們需要用到 Math.random() 方法。
// 2.需要一直猜到正確為止,所以需要一直迴圈。
// 3.while 迴圈更簡單
// 4.核心演算法:使用 if else if 多分支語句來判斷大於、小於、等於。
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var random = getRandom(1, 10);
while (true) { // 死迴圈
var num = prompt('你來猜? 輸入1~10之間的一個數字');
if (num > random) {
alert('你猜大了');
} else if (num < random) {
alert('你猜小了');
} else {
alert('你好帥哦,猜對了');
break; // 退出整個迴圈結束程式
}
}
// 要求使用者猜 1~50之間的一個數字 但是隻有 10次猜的機會
</script>
</head>
<body>
</body>
</html>
4. 日期物件
4.1 Date 概述
- Date 物件和 Math 物件不一樣,他是一個建構函式,所以我們需要例項化後才能使用
- Date 例項用來處理日期和時間
4.2 Date()方法的使用
1. 獲取當前時間必須例項化
var now = new Date();
console.log(now);
2. Date() 建構函式的引數
- 如果括號裡面有時間,就返回引數裡面的時間。例如日期格式字串為‘2019-5-1’,可以寫成new Date('2019-5-1') 或者 new Date('2019/5/1')
- 如果Date()不寫引數,就返回當前時間
- 如果Date()裡面寫引數,就返回括號裡面輸入的時間
引數常用的寫法:
-
數字型:2019, 10, 01
-
字串型:'2019-10-1 8:8:8'
<script>
var date1 = new Date(2019, 10, 1);
console.log(date1); //返回的是 11月 不是 10月
var date2 = new Date('2019-10-1 8:8:8');
console.log(date2);
</script>
4.3 日期格式化
我們想要 2019-8-8 8:8:8 格式的日期,要怎麼辦?
需要獲取日期指定的部分,所以我們要手動的得到這種格式。
方法名 | 說明 | 程式碼 |
---|---|---|
getFullYear() | 獲取當年 | dObj.getFullYear() |
getMonth() | 獲取當月(0-11) | dObj.getMonth() |
getDate() | 獲取當天日期 | dObj.getDate() |
getDay() | 獲取星期幾(週日0 到週六6) | dObj.getDay() |
getHours() | 獲取當前小時 | dObj.getHours() |
getMinutes() | 獲取當前分鐘 | dObj.getMinutes() |
getSeconds() | 獲取當前秒鐘 | dObj.getSeconds() |
注:getMonth()的值為0-11,getDay()為週日0-週六6
案例: 輸出當前日期
請寫出這個格式的日期:2019年8月8日 星期四
// 格式化日期 年月日
var date = new Date();
console.log(date.getFullYear()); // 返回當前日期的年 2019
console.log(date.getMonth() + 1); // 月份 返回的月份小1個月 記得月份+1 呦
console.log(date.getDate()); // 返回的是 幾號
console.log(date.getDay()); // 3 週一返回的是 1 週六返回的是 6 但是 週日返回的是 0
// 我們寫一個 2019年 5月 1日 星期三
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
console.log('今天是:' + year + '年' + month + '月' + dates + '日 ' + arr[day]);
案例: 輸出當前時間
寫一個函式,格式化日期物件,成為 HH:mm:ss 的形式 比如 00:10:45
// 格式化日期 時分秒
var date = new Date();
console.log(date.getHours()); // 時
console.log(date.getMinutes()); // 分
console.log(date.getSeconds()); // 秒
// 要求封裝一個函式返回當前的時分秒 格式 08:08:08
function getTimer() {
var time = new Date();
var h = time.getHours();
h = h < 10 ? '0' + h : h;
var m = time.getMinutes();
m = m < 10 ? '0' + m : m;
var s = time.getSeconds();
s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s;
}
console.log(getTimer());
4.4 獲取日期的總的毫秒形式
Date 物件是基於1970年1月1日(世界標準時間)起的毫秒數
我們經常利用總的毫秒數(時間戳)來計算時間,因為它更精確
得到毫秒數的方法
// 例項化Date物件
var now = new Date();
// 1. 用於獲取物件的原始值
console.log(date.valueOf());
console.log(date.getTime());
// 2. 簡單寫可以這麼做
var now = + new Date();
// 3. HTML5中提供的方法,有相容性問題
var now = Date.now();
案例:倒計時效果
做一個倒計時效果
案例分析
① 核心演算法:輸入的時間減去現在的時間就是剩餘的時間,即倒計時 ,但是不能拿著時分秒
相減,比如 05 分減去25分,結果會是負數的。
② 用時間戳來做。使用者輸入時間總的毫秒數減去現在時間的總的毫秒數,得到的就是剩餘時
間的毫秒數。
③ 把剩餘時間總的毫秒數轉換為天、時、分、秒 (時間戳轉換為時分秒)
轉換公式如下:
- d = parseInt(總秒數/ 60/60 /24); // 計算天數
- h = parseInt(總秒數/ 60/60 %24) // 計算小時
- m = parseInt(總秒數 /60 %60 ); // 計算分數
- s = parseInt(總秒數%60); // 計算當前秒數
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script>
// 倒計時效果
// 1.核心演算法:輸入的時間減去現在的時間就是剩餘的時間,即倒計時 ,但是不能拿著時分秒相減,比如 05 分減去25分,結果會是負數的。
// 2.用時間戳來做。使用者輸入時間總的毫秒數減去現在時間的總的毫秒數,得到的就是剩餘時間的毫秒數。
// 3.把剩餘時間總的毫秒數轉換為天、時、分、秒 (時間戳轉換為時分秒)
// 轉換公式如下:
// d = parseInt(總秒數/ 60/60 /24); // 計算天數
// h = parseInt(總秒數/ 60/60 %24) // 計算小時
// m = parseInt(總秒數 /60 %60 ); // 計算分數
// s = parseInt(總秒數%60); // 計算當前秒數
function countDown(time) {
var nowTime = +new Date(); // 返回的是當前時間總的毫秒數
var inputTime = +new Date(time); // 返回的是使用者輸入時間總的毫秒數
var times = (inputTime - nowTime) / 1000; // times是剩餘時間總的秒數
var d = parseInt(times / 60 / 60 / 24); // 天
d = d < 10 ? '0' + d : d;
var h = parseInt(times / 60 / 60 % 24); //時
h = h < 10 ? '0' + h : h;
var m = parseInt(times / 60 % 60); // 分
m = m < 10 ? '0' + m : m;
var s = parseInt(times % 60); // 當前的秒
s = s < 10 ? '0' + s : s;
return d + '天' + h + '時' + m + '分' + s + '秒';
}
console.log(countDown('2021-4-4 11:00:00'));
var date = new Date();
console.log(date);
</script>
</head>
<body>
</body>
</html>
5. 陣列物件
5.1 陣列物件的建立
建立陣列物件的兩種方式
- 字面量方式
- new Array()
<script>
// 建立陣列的兩種方式
// 1. 利用陣列字面量
var arr = [1, 2, 3];
console.log(arr[0]);
// 2. 利用new Array()
// var arr1 = new Array(); // 建立了一個空的陣列
// var arr1 = new Array(2); // 這個2 表示 陣列的長度為 2 裡面有2個空的陣列元素
var arr1 = new Array(2, 3); // 等價於 [2,3] 這樣寫表示 裡面有2個數組元素 是 2和3
console.log(arr1);
</script>
5.2 檢測是否為陣列
- instanceof 運算子,可以判斷一個物件是否屬於某種型別
- Array.isArray()用於判斷一個物件是否為陣列,isArray() 是 HTML5 中提供的方法,ie9以上版本支援
var arr = [1, 23];
var obj = {};
console.log(arr instanceof Array); // true
console.log(obj instanceof Array); // false
console.log(Array.isArray(arr)); // true
console.log(Array.isArray(obj)); // false
5.3 新增刪除陣列元素的方法
方法名 | 說明 | 返回值 |
---|---|---|
unshift(引數1...) | 向陣列的開頭新增一個或更多元素,注意修改原陣列 | 並返回新的長度 |
push(引數1...) | 末尾新增一個或多個元素,注意修改原陣列 | 並返回新的長度 |
shift() | 刪除陣列的第一個元素,陣列長度減1無引數、修改原陣列 | 並返回第一個元素的值 |
pop() | 刪除陣列最後一個元素,把陣列長度減1無引數、修改原陣列 | 返回它刪除的元素的值 |
程式碼示例:
<script>
// 新增刪除陣列元素方法
// 1. push() 在我們陣列的末尾 新增一個或者多個數組元素 push 推
var arr = [1, 2, 3];
// arr.push(4, 'pink');
console.log(arr.push(4, 'pink'));
console.log(arr);
// (1) push 是可以給陣列追加新的元素
// (2) push() 引數直接寫 陣列元素就可以了
// (3) push完畢之後,返回的結果是 新陣列的長度
// (4) 原陣列也會發生變化
// 2. unshift 在我們陣列的開頭 新增一個或者多個數組元素
console.log(arr.unshift('red', 'purple'));
console.log(arr);
// (1) unshift是可以給陣列前面追加新的元素
// (2) unshift() 引數直接寫 陣列元素就可以了
// (3) unshift完畢之後,返回的結果是 新陣列的長度
// (4) 原陣列也會發生變化
// 3. pop() 它可以刪除陣列的最後一個元素
console.log(arr.pop());
console.log(arr);
// (1) pop是可以刪除陣列的最後一個元素 記住一次只能刪除一個元素
// (2) pop() 沒有引數
// (3) pop完畢之後,返回的結果是 刪除的那個元素
// (4) 原陣列也會發生變化
// 4. shift() 它可以刪除陣列的第一個元素
console.log(arr.shift());
console.log(arr);
// (1) shift是可以刪除陣列的第一個元素 記住一次只能刪除一個元素
// (2) shift() 沒有引數
// (3) shift完畢之後,返回的結果是 刪除的那個元素
// (4) 原陣列也會發生變化
</script>
案例: 篩選陣列
有一個包含工資的陣列[1500, 1200, 2000, 2100, 1800],要求把陣列中工資超過2000的刪除,剩餘的放到新數組裡面
var arr = [1500, 1200, 2000, 2100, 1800];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (arr[i] < 2000) {
//newArr[newArr.length] = arr[i];之前的做法
newArr.push(arr[i]);
}
}
console.log(newArr);
5.4 陣列翻轉
方法名 | 說明 | 是否修改原陣列 |
---|---|---|
reverse() | 顛倒陣列中元素的順序,無引數 | 該方法會改變原來的陣列 返回新陣列 |
<script>
var arr = [1, 64, 9, 6];
var newArr = arr.reverse();
console.log(newArr);
</script>
5.5 陣列排序sort
方法名 | 說明 | 是否修改原陣列 |
---|---|---|
sort() | 對陣列的元素進行排序 | 該方法會改變原來的陣列 返回新陣列 |
注:var arr = [1, 64, 9, 16]; arr.sort();返回的為[1,16,64,9]
正確寫法程式碼示例:
var arr = [1, 64, 9, 6];
arr.sort(function(a, b) {
return b - a; // 降序
// return a - b; // 升序
});
console.log(arr);
5.6 陣列索引方法
方法名 | 說明 | 是否修改原陣列 |
---|---|---|
indexOf() | 陣列中查詢給定元素的第一個索引 | 如果存在返回索引號 如果不存在,則返回-1。 |
lastIndexOf() | 在陣列中的最後一個的索引 | 如果存在返回索引號 如果不存在,則返回-1。 |
<script>
// 返回陣列元素索引號方法 indexOf(陣列元素) 作用就是返回該陣列元素的索引號 從前面開始查詢
// 它只返回第一個滿足條件的索引號
// 它如果在該數組裡面找不到元素,則返回的是 -1
// var arr = ['red', 'green', 'blue', 'pink', 'blue'];
var arr = ['red', 'green', 'pink'];
console.log(arr.indexOf('blue'));
// 返回陣列元素索引號方法 lastIndexOf(陣列元素) 作用就是返回該陣列元素的索引號 從後面開始查詢
var arr = ['red', 'green', 'blue', 'pink', 'blue'];
console.log(arr.lastIndexOf('blue')); // 4
</script>
案例: 陣列去重(重點案例)
有一個數組[‘c’, ‘a’, ‘z’, ‘a’, ‘x’, ‘a’, ‘x’, ‘c’, ‘b’],要求去除陣列中重複的元素。
案例分析
① 目標:把舊數組裡面不重複的元素選取出來放到新陣列中,重複的元素只保留一個,放到新陣列中去重。
② 核心演算法:我們遍歷舊陣列,然後拿著舊陣列元素去查詢新陣列,如果該元素在新數組裡面沒有出現過,我們就新增,
否則不新增。
③ 我們怎麼知道該元素沒有存在? 利用 新陣列.indexOf(陣列元素) 如果返回時 -1 就說明 新數組裡面沒有改元素
舊陣列[‘c’, ‘a’, ‘z’, ‘a’, ‘x’, ‘a’, ‘x’, ‘c’, ‘b’]
新陣列 [ ]
<script>
// 陣列去重 ['c', 'a', 'z', 'a', 'x', 'a', 'x', 'c', 'b'] 要求去除陣列中重複的元素。
// 1.目標: 把舊數組裡面不重複的元素選取出來放到新陣列中, 重複的元素只保留一個, 放到新陣列中去重。
// 2.核心演算法: 我們遍歷舊陣列, 然後拿著舊陣列元素去查詢新陣列, 如果該元素在新數組裡面沒有出現過, 我們就新增, 否則不新增。
// 3.我們怎麼知道該元素沒有存在? 利用 新陣列.indexOf(陣列元素) 如果返回時 - 1 就說明 新數組裡面沒有改元素
// 封裝一個 去重的函式 unique 獨一無二的
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'])
var demo = unique(['blue', 'green', 'blue'])
console.log(demo);
</script>
5.7 陣列轉換為字串
方法名 | 說明 | 返回值 |
---|---|---|
toString() | 把陣列轉換成字串,逗號分隔每一項 | 返回一個字串 |
join('分隔符') | 方法用於把陣列中的所有元素轉換為一個字串 | 返回一個字串 |
<script>
// 陣列轉換為字串
// 1. toString() 將我們的陣列轉換為字串
var arr = [1, 2, 3];
console.log(arr.toString()); // 1,2,3
// 2. join(分隔符)
var arr1 = ['green', 'blue', 'pink'];
console.log(arr1.join()); // green,blue,pink
console.log(arr1.join('-')); // green-blue-pink
console.log(arr1.join('&')); // green&blue&pink
</script>
5.8 課下查詢
方法名 | 說明 | 返回值 |
---|---|---|
concat() | 連線兩個或多個數組 不影響原陣列 | 返回一個新的陣列 |
slice() | 陣列擷取slice(begin,end) | 返回被擷取專案的新陣列 |
splice() | 陣列刪除splice(第幾個開始,要刪除個數) | 返回被刪除專案的新陣列 注意,這個會影響原陣列 |
slice()包括begin ,不包括end
slice() 和 splice() 目的基本相同,建議同學們重點看下 splice()
splice() 可以刪除/插入/替換元素
const months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at index 1
console.log(months);
// expected output: Array ["Jan", "Feb", "March", "April", "June"]
months.splice(4, 1, 'May');
// replaces 1 element at index 4
console.log(months);
// expected output: Array ["Jan", "Feb", "March", "April", "May"]
months.splice(4, 0, 'June');
console.log(months);
// expected output: Array ["Jan", "Feb", "March", "April", "June", "May"]
// splice作用: 刪除元素/插入元素/替換元素
// 刪除元素: 第二個引數傳入你要刪除幾個元素(如果沒有傳,就刪除後面所有的元素)
// 替換元素: 第二個引數, 表示我們要替換幾個元素, 後面是用於替換前面的元素
// 插入元素: 第二個引數, 傳入0, 並且後面跟上要插入的元素
let letters = ['a', 'b', 'c', 'd']
// letters.splice(1, 3, 'm', 'n', 'l', 'x')
this.letters.splice(1, 0, 'x', 'y', 'z')
6. 字串物件
6.1 基本包裝型別
為了方便操作基本資料型別,JavaScript 還提供了三個特殊的引用型別:String、Number和 Boolean。
基本包裝型別就是把簡單資料型別包裝成為複雜資料型別,這樣基本資料型別就有了屬性和方法。
// 下面程式碼有什麼問題?
var str = 'andy';
console.log(str.length);
按道理基本資料型別是沒有屬性和方法的,而物件才有屬性和方法,但上面程式碼卻可以執行,這是因為 js 會把
基本資料型別包裝為複雜資料型別,其執行過程如下 :
// 1. 生成臨時變數,把簡單型別包裝為複雜資料型別
var temp = new String('andy');
// 2. 賦值給我們宣告的字元變數
str = temp;
// 3. 銷燬臨時變數
temp = null;
6.2 字串的不可變
指的是裡面的值不可變,雖然看上去可以改變內容,但其實是地址變了,記憶體中新開闢了一個記憶體空間。
var str = 'abc';
str = 'hello';
// 當重新給 str 賦值的時候,常量'abc'不會被修改,依然在記憶體中
// 重新給字串賦值,會重新在記憶體中開闢空間,這個特點就是字串的不可變
// 由於字串的不可變,在大量拼接字串的時候會有效率問題
var str = '';
for (var i = 0; i < 100000; i++) {
str += i;
}
console.log(str); // 這個結果需要花費大量時間來顯示,因為需要不斷的開闢新的空間
6.3 根據字元返回位置
字串所有的方法,都不會修改字串本身(字串是不可變的),操作完成會返回一個新的字串。
方法名 | 說明 |
---|---|
indexOf('要查詢的字元', 開始的位置) | 返回指定內容在原字串中的位置,如果找不到就返回-1,開始的位置是index索引號 |
lastIndexOf() | 從後往前找,只找第一個匹配的 |
<script>
// 字串物件 根據字元返回位置 str.indexOf('要查詢的字元', [起始的位置])
var str = '改革春風吹滿地,春天來了';
console.log(str.indexOf('春'));//2
console.log(str.indexOf('春', 3)); // 從索引號是 3的位置開始往後查詢,返回8
</script>
案例:返回字元位置
查詢字串"abcoefoxyozzopp"中所有o出現的位置以及次數
案例:思路
查詢字串"abcoefoxyozzopp"中所有o出現的位置以及次數
① 核心演算法:先查詢第一個o出現的位置
② 然後 只要indexOf 返回的結果不是 -1 就繼續往後查詢
③ 因為indexOf 只能查詢到第一個,所以後面的查詢,利用第二個引數,當前索引加1,從而繼續查詢
<script>
// 查詢字串"abcoefoxyozzopp"中所有o出現的位置以及次數
// 核心演算法:先查詢第一個o出現的位置
// 然後 只要indexOf 返回的結果不是 -1 就繼續往後查詢
// 因為indexOf 只能查詢到第一個,所以後面的查詢,一定是當前索引加1,從而繼續查詢
var str = "oabcoefoxyozzopp";
var index = str.indexOf('o');
var num = 0;
// console.log(index);
while (index !== -1) {
console.log(index);
num++;
index = str.indexOf('o', index + 1);
}
console.log('o出現的次數是: ' + num);
// 課後作業['red', 'blue', 'red', 'green', 'pink','red'], 求 red 在陣列中出現的位置和次數
</script>
<script>
// 課後作業 ['red', 'blue', 'red', 'green', 'pink','red'], 求 red 出現的位置和次數
var array = new Array('red', 'blue', 'red', 'green', 'pink', 'red');
var num = 0;
var index = array.indexOf('red');
while (index !== -1) {
console.log(index + ' ');
index = array.indexOf('red', index + 1);
num++;
}
console.log(num + '次數');
</script>
6.4 根據位置返回字元(重點)
方法名 | 說明 | 使用 |
---|---|---|
charAt(index) | 返回指定位置的字元(index字串的索引號) | str.charAt(0) |
charCodeAt(index) | 獲取指定位置處字元的ASCII碼(index索引號) | str.charCodeAt(0) |
str[index] | 獲取指定位置處字元 | HTML5,IE8+支援和charAt()等效 |
案例:返回字元位置
判斷一個字串 'abcoefoxyozzopp' 中出現次數最多的字元,並統計其次數。
案例:核心演算法
判斷一個字串 'abcoefoxyozzopp' 中出現次數最多的字元,並統計其次數。
有一個物件 來判斷是否有該屬性 物件['屬性名']
<script>
var o = {
age: 18
}
if (o['age']) {
console.log('裡面有該屬性');
} else {
console.log('沒有該屬性');
}
</script>
① 核心演算法:利用 charAt() 遍歷這個字串
② 把每個字元都儲存給物件, 如果物件沒有該屬性,就為1,如果存在了就 +1
③ 遍歷物件,得到最大值和該字元
判斷一個字串 'abcoefoxyozzopp' 中出現次數最多的字元,並統計其次數。
物件 o { }
程式碼:
// 判斷一個字串 'abcoefoxyozzopp' 中出現次數最多的字元,並統計其次數。
// o.a = 1
// o.b = 1
// o.c = 1
// o.o = 4
// 核心演算法:利用 charAt() 遍歷這個字串
// 把每個字元都儲存給物件, 如果物件沒有該屬性,就為1,如果存在了就 +1
// 遍歷物件,得到最大值和該字元
var str = 'abcoefoxyozzopp';
var o = {};
for (var i = 0; i < str.length; i++) {
var chars = str.charAt(i); // chars 是 字串的每一個字元
if (o[chars]) { // o[chars] 得到的是屬性值
o[chars]++;
} else {
o[chars] = 1;
}
}
console.log(o);
// 2. 遍歷物件
var max = 0;
var ch = '';
for (var k in o) {
// k 得到是 屬性名
// o[k] 得到的是屬性值
if (o[k] > max) {
max = o[k];
ch = k;
}
}
console.log(max);
console.log('最多的字元是' + ch);
6.5 字串操作方法(重點)
方法名 | 說明 |
---|---|
concat(str1,str2,str3...) | concat()方法用於連線兩個或多個字串。拼接字串,等效於+,+更常用 |
substr(start[,length]) | 從start位置開始(索引號),length取的個數 擷取字串 重點記住這個 |
slice(start,end) | 從start位置開始,擷取到end位置,end取不到(他們倆都是索引號),返回新的字串 |
substring(start,end) | 從start位置開始,擷取到end位置,end取不到 基本和slice相同 但是不接受負值 |
程式碼:
// 字串操作方法
// 1. concat('字串1','字串2'....)
var str = 'andy';
console.log(str.concat('red'));
// 2. substr('擷取的起始位置', '擷取幾個字元');
var str1 = '改革春風吹滿地';
console.log(str1.substr(2, 2)); // 第一個2 是索引號的2 從第幾個開始 第二個2 是取幾個字元
6.6 替換字串中的字元replace()方法
replace() 方法用於在字串中用一些字元替換另一些字元。
其使用格式如下:
replace(被替換的字串, 要替換為的字串);//它只會替換第一個字元
// 1. 替換字元 replace('被替換的字元', '替換為的字元') 它只會替換第一個字元
var str = 'andyandy';
console.log(str.replace('a', 'b'));
// 有一個字串 'abcoefoxyozzopp' 要求把裡面所有的 o 替換為 *
var str1 = 'abcoefoxyozzopp';
while (str1.indexOf('o') !== -1) {
str1 = str1.replace('o', '*');
}
console.log(str1);
6.7 切分字串為陣列split()方法
split()方法用於切分字串,它可以將字串切分為陣列。在切分完畢之後,返回的是一個新陣列。
例如下面程式碼:
var str = 'a,b,c,d';
console.log(str.split(',')); // 返回的是一個數組 [a, b, c, d]
// 2. 字元轉換為陣列 split('分隔符') 前面我們學過 join 把陣列轉換為字串
var str2 = 'red, pink, blue';
console.log(str2.split(','));
var str3 = 'red&pink&blue';
console.log(str3.split('&'));
6.8 課下查閱
- toUpperCase() //轉換大寫
- toLowerCase() //轉換小寫
作業
給定一個字串,如:“abaasdffggghhjjkkgfddsssss3444343”,問題如下:
1、 字串的長度
2、 取出指定位置的字元,如:0,3,5,9等
3、 查詢指定字元是否在以上字串中存在,如:i,c ,b等
4、 替換指定的字元,如:g替換為22,ss替換為b等操作方法
5、 擷取指定開始位置到結束位置的字串,如:取得1-5的字串
6、 找出以上字串中出現次數最多的字元和出現的次數
7、 遍歷字串,並將遍歷出的字元兩頭新增符號“@”
JS簡單資料型別與複雜型別
- 簡單型別與複雜型別
- 堆和棧
- 簡單型別的記憶體分配
- 複雜型別的記憶體分配
- 簡單型別傳參
- 複雜型別傳參
1. 簡單型別與複雜型別
簡單型別又叫做基本資料型別或者值型別,複雜型別又叫做引用型別。
- 值型別:簡單資料型別/基本資料型別,在儲存時變數中儲存的是值本身,因此叫做值型別
string ,number,boolean,undefined,null,bigInt,symbol
注:簡單資料型別null 返回的是一個空的物件 object,如果有個變數我們以後打算儲存為物件,暫時沒想好放啥,這個時候就給null
- 引用型別:複雜資料型別,在儲存時變數中儲存的僅僅是地址(引用),因此叫做引用資料型別
通過 new 關鍵字建立的物件(系統物件、自定義物件),如 Object、Array、Date等
引用型別統稱為 Object
型別,如果細分的話,分為以下 5 個:
Object
Array
Date
RegExp
Function
2. 堆和棧
堆疊空間分配區別:
1、棧(作業系統):由作業系統自動分配釋放存放函式的引數值、區域性變數的值等。其操作方式類似於資料結構中的棧;
簡單資料型別存放到棧裡面
2、堆(作業系統):儲存複雜型別(物件),一般由程式設計師分配釋放,若程式設計師不釋放,由垃圾回收機制回收。
複雜資料型別存放到堆裡面
注意:JavaScript中沒有堆疊的概念,通過堆疊的方式,可以讓大家更容易理解程式碼的一些執行方式,便於將來學習其他語言。
3. 簡單型別的記憶體分配
- 值型別(簡單資料型別): string ,number,boolean,undefined,null,bigInt,symbol
- 值型別變數的資料直接存放在變數(棧空間)中
4. 複雜型別的記憶體分配
- 引用型別(複雜資料型別):通過 new 關鍵字建立的物件(系統物件、自定義物件),如 Object、Array、Date等
- 引用型別變數(棧空間)裡存放的是地址,真正的物件例項存放在堆空間中
5. 簡單型別傳參
函式的形參也可以看做是一個變數,當我們把一個值型別變數作為引數傳給函式的形參時,其實是把變數在棧
空間裡的值複製了一份給形參,那麼在方法內部對形參做任何修改,都不會影響到的外部變數。
function fn(a) {
a++;
console.log(a);
}
var x = 10;
fn(x);
console.log(x);
6. 複雜型別傳參
函式的形參也可以看做是一個變數,當我們把引用型別變數傳給形參時,其實是把變數在棧空間裡儲存的堆地
址複製給了形參,形參和實參其實儲存的是同一個堆地址,所以操作的是同一個物件。
function Person(name) {
this.name = name;
}
function f1(x) { // x = p
console.log(x.name); // 2. 這個輸出什麼 ?
x.name = "張學友";
console.log(x.name); // 3. 這個輸出什麼 ?
}
var p = new Person("劉德華");
console.log(p.name); // 1. 這個輸出什麼 ?
f1(p);
console.log(p.name); // 4. 這個輸出什麼 ?