01、JavaScript基礎知識
JavaScript(縮寫:JS)是一種具有物件導向能力的、解釋型的程式語言,基於物件和事件驅動,具有相對安全性的客戶端指令碼語言。JavaScript是一門完備的 動態程式語言,當應用於 HTML 文件時,可為網站提供動態互動特性,是前端開發最主要、正式的程式語言。
ECMAScript 是由 ECMA 國際標準化組織 制定的一套指令碼語言的標準化規範,JavaScript算是他的實現,作為基礎語法規範,構成了JavaScript的核心。再加收瀏覽器提供的DOM(HTML網頁內容)操作API、瀏覽器BOM操作API,共同組成了 JavaScript。
1.1、語法規範
JS程式碼以行為單位,(半形)分號;
結尾。
?註釋://
- 單行註釋:
//
開頭。 - 多行註釋:
/*
多行註釋*/
(同css)
?程式碼風格:
- 區分大小寫,字母、數字、下劃線組成,不能數字開頭,不能是關鍵字。
- 小駝峰命名(推薦):
initialColor
?關鍵字: 內建的關鍵詞:如var、do、else、enum、eval、false、for、if、void、function、switch...
?語句塊:花括號 { 程式碼塊 }
1.2、引用方式
- 行內JS:元素標籤內部的JS程式碼。
- 內部JS:定義在
<script>
標籤裡的JS程式碼,可以放到head中、body中、body後,推薦body後,先載入html再執行JS。 - 外部JS(推薦):單獨的JS檔案,透過script標籤引入,
src
屬性指定JS檔案地址,此時標籤中寫的程式碼就無效了。 - 動態載入:透過DOM的API動態載入JS指令碼資源,用JS建立
<script>
標籤並引入資源。
<script> 屬性 |
描述 | 值/備註 |
---|---|---|
src | 外部資源地址,與嵌入指令碼程式碼不可同時使用 | <script src="js1.js" async></script> |
type | 定義指令碼語言型別,可空,預設為JavaScript型別 | 支援的MIME型別包括text/javascript、 text/ecmascript、 application/javascript 和application/ecmascript |
async | 非同步並行載入,只針對外部JS資源 | 多個async 指令碼載入完成的順序不確定 |
defer | 等HTML解析完成再執行JS,在DOMContentLoaded之前執行,只針對外部JS資源 | 多個指令碼資源順序載入 |
?指令碼載入策略:
- 如果指令碼無需等待頁面解析,且無依賴獨立執行,那麼應使用
async
。 - 如果指令碼需要等待頁面解析,且依賴於其它指令碼,應使用
defer
,將關聯的指令碼按所需順序置於 HTML 中。
<body>
<div>
<h1>基礎語法</h1>
<input type="button" value="行內JS" onclick="alert('Hello world!');"/>
<input type="button" value="外部JS呼叫" onclick="hello();"/>
</div><hr/>
</body>
<script>
console.log("內部js:網頁載入完成!");
</script>
<!-- 引入外部js檔案,設定了src屬性,script內部的程式碼就無效了 -->
<script src="../tstudy/js/js1.js" type="text/javascript" async></script>
02、變數申明var/let/const
變數,就是一個用於存放數值的容器,比如年齡=20
,“年齡”就是變數,“20”是他的樹值。JS是一種弱型別語言,不需要指明資料型別,用var
或 let
關鍵字申明即可。
?申明方式:
- 申明並賦值,1步完成:
var str="hello world";
- 先申明,再賦值,2步完成。
var str1; str1="hello world";
// 預設值為undefined
?動態資料型別:JavaScript 是一種“動態型別語言”,意味著一個變數可以被賦值為各種型別資料值,透過typeof
判斷資料型別。
let age;
console.log(age); //undefined
age =20;
console.log(typeof age); //number
age='年芳二十';
console.log(typeof age); //string
var | let (IE11 ES6) | const (IE11 ES6) | |
---|---|---|---|
說明 | 變數申明 | 變數申明 | 只讀常量申明:申明時必須初始化值,不可更改 |
作用域 | 全域性(整個文件)或整個函式體內 | 塊級作用域{} 包含的區域 |
塊級作用域{} |
命名規範 | 推薦:小駝峰命名 | 同var | 推薦:全大寫+下劃線,const MAX_SPEED |
預設值 | undefined |
undefined |
必須賦值 |
變數提升 | 提升所有var申明的變數,可以先使用後申明(不推薦),把var變數申明提升到程式碼頭部,⚠️注意不包括賦值 | 不會提升,順序執行:必須先申明,後使用。存在暫時性死區 let foo=(foo+55) 第二個foo未申明報錯 |
不會提升,順序執行:必須先申明,後使用。 |
全域性屬性 | 在全域性環境時,會成為頂級物件的屬性(不可配置屬性),作為全域性變數存在。var age=3; //this.age;window.age |
無 | 無 |
重複申明 | 可以重複申明,覆蓋前面的,有點太隨意了 | 不可重複申明,作用域內重複申明會報錯 ● 包括var、const申明的變數 ● 子塊可重新申明let,不同的作用域了 ● 子塊中用var變數會重複,var會提升 |
不可重複申明,會提示錯誤,同let |
申明多個 | 支援:var s1=1,st=2; |
支援:let s1,s2=2; |
支援:const s1=1,s2=2; |
效能 | 一般 | 一般 | 編譯器會做常量替換最佳化,提升程式碼效率 |
總結 | ?有點粗獷,不推薦 | ?更嚴謹,推薦使用 | ?不僅更嚴謹,效能還好,優先推薦!!! |
暫時性死區:由於沒有了變數提升,及塊級作用域,let、const變數只能在申明後才能用,在這之前不可用,稱為“暫時性死區”。
2.1、作用域
特別注意的是 var
作用域在整個文件或函式內,整個文件也可認為是一個特殊的頂級函式。
- 如下經典的for迴圈示例,
var
的變數提升導致輸出結果詭異。
for (var i = 1; i <= 5; i++) {
setTimeout(function () { //setTimeout為非同步執行函式
console.log(i); //輸出6 6 6 6 6
}, 0);
}
//換成let,則輸出:1 2 3 4 5
//換成const,輸出1,然後報錯 Assignment to constant variable
- var作用域在整個函式
function foo() {
var x = 1; //x作用域在foo函式體內,包括巢狀函式bar也可以訪問
function bar() {
var y = 2; //y作用域只在函式體bar
console.log(x); // 1
console.log(y); // 2
}
bar();
console.log(x); // 1 (`x` 在作用域內)
console.log(y); // Uncaught ReferenceError: y is not defined
}
foo();
console.log(x); // Uncaught ReferenceError: x is not defined
console.log(y); // Uncaught ReferenceError: y is not defined
- let作用域僅限
{}
塊,可以是函式的塊function{}
、迴圈的塊for{}
,或者就一個孤獨的塊{}
。
let s1;
let s1; //Uncaught SyntaxError: Identifier 's1' has already been declared
let x = 1; //後面塊內的 var x會被變數提升,導致重複變數定義報錯
{
var x = 2; //Uncaught SyntaxError: Identifier 'x' has already been declared
}
2.2、變數提升
變數提升:JS引擎是先解析程式碼,獲取所有被var
申明的變數,然後再逐行執行。只提升用var
顯示申明的變數,會把所有var的申明提升到全域性程式碼的頂部先執行,⚠️注意只提升申明,不包括賦值。
console.log(sname); //undefined 只提升了x的變數申明,值為預設值
var sname = "sam";
var x=1;
function print() {
console.log(sname); // sam
console.log(window.sname); //sam 全域性文件中申明的var變數,會作為 window 的全域性變數屬性
console.log(this.sname); //sam 這裡的this 指向 全域性物件window
}
print();
?隱式全域性變數:無申明變數(
str="hello";
),自動提升為隱式全域性變數(不論在什麼地方),類似var變數,除了沒有變數提升。so,?儘量不要這麼使用,在嚴格模式下('use strict';
)這樣寫是會報錯的。
x = 0; //未申明變數,成為隱式全域性變數
function f() {
y = 1; //當執行該函式時,未申明變數,成為隱式全域性變數
var z = 2; //z是函式內部申明的變數,作用域只在函式體內
}
f();
console.log(x, y); // 0 1
console.log(window.x, window.y); // 0 1
console.log(z); //Uncaught ReferenceError: z is not defined
2.3、解構賦值
解構賦值是ES6新增的語法,可以一次性給多個變數賦值,提高了程式設計效率,賦值操作更簡潔。具體方式就是:將屬性/值從物件/陣列中取出,賦值給其他變數的一種賦值方式。有兩種解構賦值的語法形式:
- 陣列解構:類似陣列的寫法,從陣列中按順序賦值,這裡陣列可以是其他可迭代資料。
- 物件解構:類似物件的寫法,從物件中按屬性名賦值。
//變數一個個賦值
let x1 = 1, x2 = 2, x3 = 3, x4 = 4;
// 用陣列解構賦值
let [y1, y2, y3, y4] = [1, 2, 3, 4];
[x1, x2] = [x2, x1]; //用來交換x1、x2的值,不用第三方變數
// 從物件解構賦值
let { c, d } = { a: 0, c: 1, d: 2 };
03、基礎資料型別
ECMAScript 有 6 種基本型別,Undefined
、Null
、Boolean
、Number
、String
、Symbol
(符號),其他就是都是Object物件型別了,如Array
、object
、Map
、Date
、function
等。
資料型別 | 描述 | |
---|---|---|
Number | 數值:整數、小數(浮點型) ● 都是64位浮點型別儲存的,最高精度17位,所以1和1.0是相等的。 ● 浮點數計算時(小數位)可能不準確,不建議用浮點數做判斷。 ● 儲存時會自動轉換整數的浮點數值,如1.0轉換為1。 |
let myAge = 17; |
Boolean | 布林型別:有兩個值true 、false |
let isFirstBlood=true; |
null | 空值關鍵字,表示空缺、空值,其型別為object,表示一個空物件的指標。undefined 繼承自null ,等值比較時返回true。 |
注意判斷object型別時須排除null。 |
Undefined | 未定義:只有一個值undefined ,表示未定義或不存在● 未賦值的變數預設為 undefined 。● 呼叫函式時未傳遞必須引數,則為 undefined 。● 函式沒有返回值,預設返回 undefined 。 |
|
String | 字串:單引號、雙引號括起來,用加號+ 連線字串。● 不可變:JS的字串一旦建立不可變,所有更改都會建立新的字串 ● 每一個字元元素是16 位的無符號整數值 |
|
Symbol ES6 | 符號型別,具有唯一性和不變性,常用於物件屬性名 | const fooSym = Symbol('foo') |
bigint | 新新增的資料型別(ES2020) | |
object物件 | 物件:引用型別,各種值的組合 | |
Array | 陣列物件 | var list1=[1,2,3]; |
JSON物件 | 物件:var jobj={name:"zhang",age:1}; |
|
function | 函式,本身也是物件 | function f1(){/*...*/} |
⚠️注意不要將基本型別中的布林值 true / false 與值為 true/false 的 Boolean 物件弄混了,基本型別Boolean是一個物件。
console.log(typeof 1); //number
console.log(typeof true); //boolean
console.log(typeof null); //object
console.log(typeof undefined); //undefined
console.log(typeof 'abc'); //string
console.log(null == undefined); //true 值比較
console.log(null === undefined); //false 恆等比較
//boolean
const x = new Boolean(false); //new Boolean()建立了基本型別Boolean的物件,就不是一個平平無奇的值型別了。
console.log(typeof x); //object
console.log(x.valueOf()); //false valueOf()方法獲取物件的基本資料的值
console.log(Boolean(undefined)); //false
console.log(Boolean(null)); //false
console.log(Boolean(NaN)); //false
console.log(Boolean(0)); //false
console.log(Boolean("")); //false
console.log(Boolean(1)); //true
console.log(Boolean(-100)); //true
console.log(Boolean("abc")); //true
3.1、Number數字
Number的屬性、方法:
屬性/方法 | 描述 | 示例 |
---|---|---|
?靜態屬性/方法 | ||
Number.NaN | NaN是一個特殊的Number值,即非數值(Not a Number) ● NaN和任何值都不相等,包括它自己,和任何值計算都為NaN ● Math 、parseInt 函式執行失敗會返回NaN |
同window.NaN |
Number.MAX_VALUE | 最大數值(靜態屬性),值接近於 1.79E+308 | |
Number.MIN_VALUE | 最接近 0 的正值,而不是最小的負值,約為 5E-324 | |
Number.isNaN() IE? | 判斷是否等於NaN,window.isNaN 是判斷是否非數值,坑! |
只有NaN才返回true |
Number.isInteger() IE? | 是否為整數 | |
Number.parseFloat() IE? | 解析浮點數,從第一個非空字元解析獲取數字,識別第一個小數點 | 同window.parseFloat() |
Number.parseInt() IE? | 解析整數,從第一個非空字元解析獲取數字,支援進位制引數 | 同window.parseInt() |
?建構函式 | ||
Number() | 轉換為數字(忽略空格)。Number()轉換資料不同於parseint、parseFloat,要求必須為合法數字,要求更嚴格,不成功便成仁。 | Number(true) //1 |
?例項屬性/方法 | ||
toFixed(小數位數) | 轉換為指定小數位數的字元,多了會四捨五入,不足用0補位 | n1.toFixed(2) |
toString() | 轉字串,引數可以指定基數(進位制) | n2.toString(2) //2進位制 |
?注意浮點數的精度:
0.1+0.2 //輸出 0.3000000000000000**4**
。由於浮點數的精度問題,永遠不要用浮點數值去做條件判斷。這種錯誤是由於IEEE 754標準導致的。
Number.parseFloat("123.4a5"); //123.4
Number.parseInt("123.4a5"); //123
//注意,兩個方法是不同的,全域性的window.isNaN()是判斷是否非數值。
window.isNaN("a") //true
Number.isNaN("a") //false //這屬於JS坑爹的設計,兩個含義完全不同
console.log(Number("")); //0
console.log(Number("123abc")); //NaN,不同於parseint、parseFloat
console.log(Number("12.12.12")); //NaN,不同於parseint、parseFloat
console.log(Number.parseFloat("12.12.12")); //12.12
let n1=1.336,n2=100;
n1.toFixed(2) //1.34
n2.toFixed(2) //100.00
window.parseFloat(string):從字串的第一位(空字元會被忽略)開始,如果是數字(正號+
、負號-
、數字0-9
、第一個小數點.
、科學計數法e/E
)則轉數字,直到非數字或結束。
console.log(parseFloat("123abc")); //123
console.log(parseFloat("abc123")); //NaN
console.log(parseFloat("11.11")); //11.11
console.log(parseFloat("11.11.33")); //11.11
window.parseint(string):同parseFloat,除了不識別小數點。
console.log(parseInt("123abc")); //123
console.log(parseInt("abc123")); //NaN
console.log(parseInt("11.11")); //11
3.2、String字串
String:字串物件,提供各種字串操作。
屬性/方法 | 描述 | 示例 |
---|---|---|
?建構函式 | ||
String() | 支援任意值轉換為字串,包括null 、undefined ,都是直接加引號,很粗暴!?可以用來判斷null、undefined |
String(null) //"null" |
?例項屬性/方法 | ||
length | 字串長度 | "abc".length; // 3 |
charAt(index) | 返回指定位置的字元 | |
indexOf(char) | 返回字元的索引位置,從前往後找,lastIndexOf 是從後往前找 |
s1.indexOf("12") |
substr(start,length?) | 擷取字串:指定起始位置、長度,無length 到結尾(下同) |
s1.substr(2) |
substring(start,end?) | 擷取字串:指定起始位置、結束位置 | |
slice(start,end?) | 擷取字串:起始位置、結束位置,同substring ,區別是支援負數(倒數),(slice /slaɪs/ 切片) |
str.slice(0,-1);//擷取0到倒數第二位置的字元 |
split(separator,limit?) | 按照分隔符分割字串為陣列 | (split /splɪt/ 分裂) |
trim() | 移除首尾的空白字元,返回新字元,不會改變原有字元。 | |
trimStart() | 同上,值移除開頭的空白字元,還有移除末尾的trimEnd () |
|
padStart(len,str) | 從頭補齊字元長度到len ,str為去替補的字元,沒有則空格 |
"12".padStart(5,'0') |
padEnd(len,str) | 補齊字元長度,從尾部開始 | |
replace(old, new) | 字元替換,str.replace("臺灣","臺灣省") ,支援正則和函式 |
|
repeat(n) | 建立一個重複n次的新字串 | "12".repeat(2) //1212 |
toLowerCase() | 字元轉小寫,大寫是toUpperCase() |
|
includes(str) | 判斷是否包含指定的字串 | |
startsWith(str) | 判斷是否以指定字元開頭,endsWith()判斷結尾 | |
search(str) | 字元搜尋或正則匹配搜尋 | |
match(regexp) | 正則匹配搜尋字元 |
?字串的不變性:字串一經建立不會改變。 let str="abc"; str="123";
- 這裡的不改變,不是字元變數
str
不能修改,是指字串"abc"
本身不可更改,修改str
會建立新的字元。所以,字元的操作都不會影響原來的字串值,而是建立新的字串。 - 字元連線建立新字元:字元的連線,如
+
,會建立新的字串。
?模板字串(IE?):${var}
+反引號 `` 包裝
板字串可以包含特定語法(${expression}
)的佔位符,由一個內建函式負責計算表示式並輸出最終的字串。
let x=1,y=2;
console.log(`sum: ${x} + ${y} = ${x+y}`); //sum: 1 + 2 = 3
?JavaScript 特殊/跳脫字元:在字串中使用的特殊符號
字元 | 描述 |
---|---|
\0 | Null 位元組 |
\b | 退格符 |
\f | 換頁符 |
\n | 換行符 |
\r | 回車符 |
\t | Tab (製表符) |
\v | 垂直製表符 |
\' | 單引號 |
\" | 雙引號 |
\\ | 反斜槓字元(\) |
3.3、型別( 隱式 )轉換
隱式型別轉轉換,是自動進行的,也叫自動型別轉換。
值 | 字串 | 數字 | 布林值 |
---|---|---|---|
undefined | "undefined" | NaN | false |
null | "null" | 0 | false |
true | "true" | 1 | true |
false | "false" | 0 | false |
""(空字元) | "" | 0 | false |
"1.5" | "1.5" | 1.5 | true |
"one" | "one" | NaN | true |
0 | "0" | 0 | false |
-1 | "-1" | -1 | true(非0數字都true) |
1 | "1" | 1 | true |
NaN | "NaN" | NaN | false |
[](空陣列) | 0 | true | |
[5]一個數字 | 裡面的數字5 | true | |
["a"][1,2]其他陣列 | NaN | true | |
{...}物件 | NaN | true |
?隱式轉換總結:
- 轉boolean:undefined、null、NaN、0、空字元轉bool都為false;非0數字(包括負數)、非空字元(包括”true“、”false“)、物件、空陣列[] 轉
boolean
都為true。 - 轉數字:非空字串都是數字(忽略空格)的轉對應數字,否則NaN;null、空字元轉數字為0。
- 轉字串:任意型別轉字串加引號,包括undefined、null。
- +運算:字串+任意型別(包括空字元)均轉換為字串;boolean、數字轉數值進行相加。
-
、*
、/
、%
運算:都是隱式轉換為數值運算。==、>、<
比較運算子:不同的值型別轉數字;都是字元比較碼值;如果存在物件,先轉換為原始值。
console.log("-1" - 1); // -2
console.log(2 > true); // true
console.log("one" + true); // onetrue
console.log("1.5" * 2); // 3
console.log("1.5" + 2); // 1.52
console.log([5] / 2); // 2.5
?顯示型別轉換就是呼叫各種方法、型別建構函式進行顯示的資料轉換。
- toString():基本每種資料型別都提供了toString()方法,轉換為字串,除開null和undefined不可使用,會報錯。
- 型別建構函式:Boolean()、Number()、String()的型別函式,都可以轉換對應資料型別。
- valueOf():valueOf()方法可以轉換物件為一個基本資料值。
- 其他如parseInt()、parseFloat()...等方法。
3.4、值型別與引用型別
⁉️堆和棧:
- 棧(stack):提供程式碼執行環境,並存放值型別、變數識別符號。速度快,空間有限(不同瀏覽器不同)。
- 堆(heap):存放引用型別資料,速度慢,空間大。
值型別(基本型別) | 物件/引用型別 | |
---|---|---|
資料型別 | undefined、null、Boolean、Number、String、Symbol | Array、object、window,function等 包裝型別:String、Number、Boolean; 單體內建物件:Global、Math |
儲存位置 | 儲存在棧中(變數識別符號、變數值),佔用空間固定 |
儲存在堆中,佔用空間不固定。變數識別符號儲存在棧區,值為地址指標,指向儲存在堆區的物件資料。 |
屬性方法 | 不能新增任何屬性、方法。 | 可以動態新增屬性和方法 |
複製 | 複製變數值 | 複製地址指標(變數值是物件的指標),指向同一物件 |
引數傳遞 | 值傳遞,不影響原有變數 | 引用地址傳遞,共用同一個物件 |
垃圾回收 | 函式執行完就回收了 | 沒有任何引用時,才會被垃圾回收機制收回 |
型別驗證 | typeof :typeof 0; //number |
instanceof :[] instanceof Array //true Object.prototype.toString.call({}) //[object Object] |
==比較 | 值型別是值比較 | 引用型別比較引用地址,所以要用恆等=== 比較 |
04、運算/運算子
4.1、➕算數運算子
運算子 | 描述 | 示例 |
---|---|---|
+ | 加 | |
- | 減 | |
* |
乘 | |
/ | 除 | |
% | 取餘數 | 6%3; //=0 |
** |
指數,冪運算,等同於Math.pow(a,b) | 3**2; //=Math.pow(3,2)=9 |
++ | 自加1,符號在前面的先運算,再賦值,在後面的反之 | x=++y; //y=1+y; x=y; x=y++; //x=y;y=1+y; |
-- | 自減1,同上 |
?運算子優先順序:
[ ++,--,!] > [*,/,% ] > [ +,- ]
var x=1; //經典面試題
console.log(x+x++ + ++x); //1+1+(1+2)=5
?+
加運算子會隱式轉換:+運算就是字元相加、數字相加兩種情況
- boolean、數字相加會隱式轉換為數值進行相加。
- 字串 + 非字串會隱式轉換為字串。
console.log(true+false); //1
console.log(true+3); //4
console.log(true+"1"); //true1
console.log("123"+123); //123123
console.log("123"+[1,2,3]); //1231,2,3
?-
,*
,/
,%
隱式轉換數值:都是數學運算轉數字。減、乘、除、取餘運算都是數學運算,會隱式轉換為數字再運算。
console.log("123"-"12"); //111
console.log("123"-12); //111
console.log("123"-1-true); //121
console.log("123"/true); //123
console.log("123"/2); //61.5
4.2、⏸️賦值運算子
運算子 | 描述 | 示例 |
---|---|---|
= | 賦值運算子,一個神聖的儀式 | |
+= | 加法賦值 | x+=y //x=x+y |
-= | 減法賦值 | x-=y //x=x-y |
*= | 乘法賦值 | x*=y //x=x*y |
/= | 除法賦值 | x/=y //x=x/y |
%= | 取餘賦值 | a%=3 //a=a%3 |
4.3、?比較運算子
運算子 | 描述 | 示例/備註 |
---|---|---|
>,<,>=,<= | 大於,小於,大於等於,小於等於 | |
== | 相等比較,比較變數的值,而不管其型別 | "1"==1; //true |
=== | 恆等比較,比較型別和值 | 無型別轉換 |
!= | != 不等於比較 |
|
!== | !== 不恆等比較 |
無型別轉換 |
比較運算子會隱式轉換為數值!
- 都是字元,轉為碼值進行比較,
- 兩個不同型別比較,隱式轉為數值,然後進行比較。
- 引用型別永遠不相等,雖然其內部的資料一模一樣,因為比較的是引用地址。
- 推薦恆等,由於
==
、!=
比較會隱式轉換,會遇到較多奇葩問題,在開發中,我們一般使用嚴格比較恆等===
!==
。 - NaN與任何值比較,都是false, Infinity 只等於它自身。
console.log(NaN==NaN); //false
- null 和 undefined, 他們直接相等,和其他原始型別比較,不相等。
console.log("123">"45"); //false 都是字元比較字元碼值
console.log("123">45); //true 轉換為數值比較
console.log("123"==123); //轉數值比較,true
console.log(""==false); //true 轉為數值比較
console.log("false"==false); //false 轉為數值比較
console.log("true"==true); //false 轉為數值比較
console.log([1,2,3]==[1,2,3]); //false,陣列是物件
4.4、❗邏輯運算子
運算子 | 描述 | 示例/備註 |
---|---|---|
! | ! 邏輯非運算子 |
!false //true |
&& | && 、|| 也叫短路運算子:從左往右判斷,符合要求就不繼續執行了邏輯與 && =同時滿足:返回第一個為false 的值,否則最後一個值 |
1 && 2 && 3 //返回3 1 && 2 && false && 3 //返回false |
|| | 邏輯或=滿足一個即可:返回第一個為true 的值,否則最後一個值 |
1 || 2 || false //返回1 |
邏輯運算子會隱式轉換為
boolean
值。
短路運算子&&
、||
常用來判斷都為真、至少有一個為真:
let user = { name: "sam", score: 98, age: 12 };
if (user.age <= 12 && user.score > 95)
console.log(`${user.name} 是一個少年天才!`);
4.5、⁉️其他運算子
運算子 | 描述 | 示例 |
---|---|---|
?: | 三元表示式:判斷條件 ?條件為真 :條件為假 |
age = 4 > 2 ? 4 : 2; //4 |
??= | 邏輯空賦值運算子: (x ??= y) 僅在 x 是(null 或 undefined) 時對其賦值y | x??="default"; |
?. || | 可選鏈運算子,不為空(null 或 undefined)時才執行。可以沒有 ||,返回undefined |
page=res?.data?.size ||1;obj?.[prop]; obj.func?.() |
void | 執行表示式,返回一個 undefined | void alert("void") |
&,|,~,^,<<,>> | 二進位制位的運算,32位數字的位運算 | |
delete | 刪除一個物件的屬性、陣列鍵值,刪除後會變為undefined | delete objt.pro |
typeof | 獲取資料型別,typeof (operand) ,括號省略。 |
typeof null; //object |
in | 判斷屬性是否在物件中 | "length" in [] //true |
instanceof | 判斷物件是否指定的型別,用於引用型別、自定義型別 | [] instanceof Array //true |
new | new Object() 建立物件例項 |
|
superIE? | 呼叫一個物件父類的函式,在子類中呼叫 | supper.print(); |
05、邏輯語句
if/switch條件判斷
if
條件語句,根據條件執行。if
可單獨使用,也可以跟else if
(0個或多個,中間)、else
(0個或1個,放最後)。
if (條件) { /*程式碼*/ }
else if(條件) { /*程式碼*/ }
else if(條件) { /*程式碼*/ }
else { /*程式碼*/ } //可以不要else部分,單獨if
switch
定值條件分支,值的判斷是用的===
恆等比較,多用於列舉值、固定的常量值。注意每一個case後需要用break,以防止穿透(繼續往後執行)。
switch (表示式) {
case 值1:
/*程式碼*/;
break; //返回,結束switch,防止無意義的穿透執行
case 值2:
case 值3: //可以多case合併一塊
/*程式碼*/;
break;
default: //前面的case都沒有命中時執行
/*程式碼*/
}
try.catch異常處理
用 try...catch...finally 語句捕獲異常,throw語句丟擲一個異常。
- JS程式碼如果發生了異常,則不會再執行後面的程式碼了,就需要做好異常捕獲處理。
finally
語句塊為可選,不管是否丟擲異常都會執行,常用來做一些清理收尾工作。throw
丟擲異常,可以是自定義的值、物件,可以用Error
物件包裝一個錯誤資訊。
function print(para) {
if (para <= 0) {
throw "引數para必須大於0(para= "+para+")";
throw new Error("引數para必須大於0(para= "+para+")");
}
console.log(para);
}
print(2); //如果這裡引數用-2,則會丟擲異常,這裡的異常沒人管,後面的程式碼就不會執行了
try{ //try包裝要執行的程式碼
print(-2);
}
catch(e){ //catch捕獲try中丟擲的異常並處理,引數為捕獲到的異常資訊,如果沒有異常則跳過catch語句
console.log("發生錯誤:" + e);
}
finally{
console.log("執行完畢!") //始終會被執行的程式碼,用於一些清理收尾工作
}
break/continue
- break:結束迴圈,停止本層迴圈,跳出本層迴圈,大家都別幹了!
- continue:結束本次迴圈,暫停本次迴圈,不執行後面的程式碼了,繼續下一次迴圈,我不想幹了,你們繼續!
while(true) { }
while
迴圈,先判斷,符合條件才執行,會迴圈的判斷條件 》執行,所以必須注意結束迴圈的控制,不然就是死迴圈了。
while(條件表示式){
/*迴圈程式碼*/
//條件控制程式碼,別忘了
}
do{ } while (true)
do...white
迴圈,先執行 》再判斷。同while,需注意迴圈的控制,避免死迴圈。
do{
/*迴圈程式碼*/
//條件控制程式碼,別忘了
}while(條件表示式)
for(i,i<n,i++){ }迴圈
迴圈執行邏輯控制語句:
for(初始化語句;判斷條件語句;控制條件語句){
/*迴圈程式碼*/
}
for(let i=1;i<=10;i++){ //迴圈1到10
if(i>6)
break; //跳出並結束迴圈
if(i%2==1)
continue; //如果是奇數,返回繼續下一次迴圈
console.log(i);
}
for(in){ }可列舉屬性
for...in迴圈,對一個物件(不僅僅是陣列)進行迴圈遍歷,遍歷其所有可列舉的屬性(索引下標、屬性),包括繼承來的。
let arr=[1,2];
arr.uname="arr";
arr.print=function(){console.log(this.length)};
for(let i in arr){
console.log(i+":"+arr[i]);
}
/*輸出:
0:1
1:2
uname:arr
print:function(){console.log(this.length)}
*/
❗慎用
for(in)
:for(in)是迴圈遍歷的是所有可列舉的(enumerable)屬性,對於陣列、可迭代集合一般使用for(of)
。
for(of) {}集合值迭代
for…of(IE?)語法是ES6新引入的語法,用於遍歷可迭代(iterable)物件,只遍歷陣列物件元素。包括字串String、陣列Array、集合Set、字典Map、arguments 物件、DOM NodeList 物件等。
和for...in
最大的區別就是,for...of
迭代的是集合的資料值,而不是可列舉屬性(索引)。
let arr=[1,2];
arr.uname="arr";
arr.print=function(){console.log(this.length)};
for(let i of arr){
console.log(i); //1 2
}
forEach()陣列方法
forEach 作用於陣列物件,用於遍歷陣列物件的每一個元素,並對每一個元素執行回撥(callback)函式。
語法:ArrayObject.forEach(callback(currentValue, index, arr), thisValue))
let arr = [1, 2];
arr.uname = "arr";
arr.print = function () { console.log(this.length) };
arr.forEach(function (item, index) {
console.log(index + ":" + item);
});
/*輸出:
0:1
1:2
*/
©️版權申明:版權所有@安木夕,本文內容僅供學習,歡迎指正、交流,轉載請註明出處!原文編輯地址-語雀