目錄
1.0如果想將JavaScript寫到一對head標籤中,並且需要在JavaScript代碼中操作界面上的元素,就必須要加上:
47.0 JavaScript isPrototypeOf屬性
1.0如果想將JavaScript寫到一對head標籤中,並且需要在JavaScript代碼中操作界面上的元素,就必須要加上:
window.onload = function () {
操作界面元素的JavaScript代碼
}
2.0 JavaScript常用的輸出方式
語法 | 注意 |
alert(需要輸出的內容) |
1.0如果輸出的是非數字要加雙引號或單引號括起來; 2.0JavaScript嚴格區分大小寫 3.0每一句JavaScript代碼後面都要添加一個英文的分號 |
confirm(需要輸出的內容) | |
prompt(需要輸出的內容) |
語法 | 注意 |
document.write(需要輸出的內容) | 1.0如果輸出的是非數字要加雙引號或單引號括起來; |
語法 | 注意 |
console.log(需要輸出的內容) | 普通輸出 |
console.warn(需要輸出的內容) | 警告輸出 |
console.error(需要輸出的內容) | 錯誤輸出 |
3.0JavaScript中的常量
類型 | 解釋 |
整型常量 | 正數,如1 , 22 , 55 , 56 |
實型常量 | 小數,如1.2 , 223.3 |
字符串常量 | 字符串常量就是用雙引號或單引號括起來的內容,如"123", "abc" |
布爾常量 | 布爾常量即真和假 true和false |
自定義常量 | 在ES6中新增的, const 常量名 = 常量值 自定義常量被定義後就不可以再更改. |
4.0JavaScript的變量
類型 | 解釋 | 語法 |
變量 | 變量表示一些可以被更改的數據 |
變量聲明: ES6之前 var 變量名; ES6之後 let 變量名; |
注: let聲明的變量是唯一的,如果重新定義同名的變量,會報錯. var 聲明的變量如果重新聲明,後面的會覆蓋前面的,不會報錯.
通過var定義的變量,可以先使用,後定義(預解析),let則不能先使用後定義.
5.0JavaScript的關鍵字和保留字
abstract | arguments | boolean | break | byte |
case | catch | char | class* | const |
continue | debugger | default | delete | do |
double | else | enum* | eval | export* |
extends* | false | final | finally | float |
for | function | goto | if | implements |
import* | in | instanceof | int | interface |
let | long | native | new | null |
package | private | protected | public | return |
short | static | super* | switch | synchronized |
this | throw | throws | transient | true |
try | typeof | var | void | volatile |
while | with | yield |
6.0JavaScript的標識符命名規則
只能有英文字母,阿拉伯數字,下劃線,美元符號組成,但不能以數字開頭,且嚴格區分大小寫,不能使用關鍵字和保留字作爲標識符.
7.0HTML和JavaScript的註釋
HTML |
<!-- --> |
JavaScript |
單行註釋 // 多行註釋 /* */ |
注:多行註釋不能嵌套多行註釋,多行註釋可以嵌套單行註釋;單行註釋可以嵌套單行註釋或多行註釋,但必須是同一行.
8.0檢測JavaScript的數據類型
typeof 需要檢測的數據 |
如: let res = tpyeof 123 將123的數據類型保存在res的變量中 |
9.0JavaScript基本數據類型
數據類型 | 解釋 |
Number數值類型 | 在JavaScript中 整數 和小數都屬於number數值類型注:NaN屬於Number類型 |
Boolean 布爾類型 | 在JavaScript中布爾類型只有false和true兩個取值 |
String 字符串類型 | 通過單引號或雙引號括起來的內容都屬於字符串類型 |
Undefined 未定義類型 | 在JavaScript中未定義類型比較特殊,只有一個取值undefined |
Null 空類型 |
注:NaN屬於Number類型
數據類型 | 解釋 |
Object 對象類型 |
10.0 基本數據類型轉換爲字符串類型
數據類型 | 轉換爲字符串類型String |
Number數值類型 |
變量名稱.toString() String(常量 or 變量) 常量/變量 + " "/' ' |
Boolean 布爾類型 |
變量名稱.toString() String(常量 or 變量) 常量/變量 + " "/' ' |
Undefined 未定義類型 |
String(常量 or 變量) 常量/變量 + " "/' ' |
Null 空類型 |
String(常量 or 變量) 常量/變量 + " "/' ' |
11.0 基本數據類型轉換爲數值類型
數據類型 | 轉換爲數值類型 |
String 字符串類型 |
Number(常量 or 變量) 注:如果字符串爲空/無數據/都爲空格,則轉換後的值爲0,字符串中有字母,這轉換後的數值爲NaN,字符串爲數字則正常轉換.
通過 +/- (正負號) 將字符串類型轉換爲數值類型,但對於純數字的字符串 - (負號)會改變數值的正負性 ,帶其他字符的字符串則被轉換爲 NaN 注: 常量字符串也可以通過這種方式轉換(如: let a = +"123" 常量字符串123,會被轉換爲數值123)
parseInt(需要轉換的字符串) or parseFloat(需要轉換的字符串) 該方法都是從左到右開始提取數字,遇到非數字則停止提取
|
Boolean 布爾類型 |
Number(常量 or 變量) true 轉換後爲 1 false 轉換後爲 0
通過 +/- (正負號) 將字布爾類型轉換爲數值類型, +(正號):true 被轉換爲 1 ; false 被轉換爲 0 -(負號)則相反
parseInt(布爾類型) or parseFloat(布爾類型),其被轉換爲 NaN |
Undefined 未定義類型 |
Number(常量 or 變量) 轉換之後爲 NaN
通過 +/- (正負號) 將未定義類型轉換爲數值類型, 其被轉換爲 NaN
parseInt(undefined) or parseFloat(undefined),其被轉換爲 NaN |
Null 空類型 |
Number(常量 or 變量) 轉換後爲 0
通過 +/- (正負號) 將空類型轉換爲數值類型, 其被轉換爲 0
parseInt(null) or parseFloat(null),其被轉換爲 NaN |
注:parseInt() or parseFloat() 無論括號中是何種數據類型,都會被當做字符串來處理
12.0基本數據類型轉換爲布爾類型 Boolean(常量 or 變量)
數據類型 | 轉換爲布爾類型 |
Number數值類型 |
Boolean(數值) 只有數值爲0,纔會被轉換爲false, 注:如果是NaN也會被轉換爲 false |
String字符串類型 |
Boolean(字符串),只要字符串有內容(空格也算內容),則被轉換爲true |
Undefined 未定義類型 |
Boolean(undefined),被轉換爲 false |
Null 空類型 |
Boolean(null), 被轉換爲 false |
注: 空字符串/0/undefined/null/NaN 都會被轉換爲 false,其它的都會被轉換爲 true.
13.0JavaScript算術運算符
任何數據與NaN進行運算結果都是NaN.
加法:任何數據與字符串相加,都會先把數據轉換成字符串類型,最後再做字符串拼接.
減法:任何數據與字符串相減,都會先把字符串轉換爲數值類型,再運算.
除法/乘法:與減法的注意點一樣.
取模: m%n = 餘數 如果 m>n 則正常取餘;如果 m<n 則結果是m;如果n爲0,則結果爲NaN; 注取餘結果的正負性取決於m.
14.0關係運算符注意點
null == 0 | false |
undefined == 0 | false |
null == undefined | true |
NaN == NaN | false |
注:要判斷某個數字是否爲NaN可以通過函數來判斷 如:
任何數據和NaN進行比較,返回值都是false |
== |
只會判斷取值是否相等,不會判斷數據類型是否相等,只要取值相等,返回值就位true |
=== | 不僅會判斷取值是否相等,並且會判斷數據類型是否相等,只有取值和數據類型都相等,返回值才爲true |
!= | 只會判斷取值是否相等,不會判斷數據類型是否相等,只要取值不相等,返回值就位true |
!== | 不僅會判斷取值是否相等,並且會判斷數據類型是否相等,取值或數據類型只要有一項不相等,返回值就爲true |
15.0JavaScript邏輯運算符
邏輯運算符名稱 | 語法 | 返回值 | 特點 |
邏輯與 && | 條件表達式A && 條件表達式B | true false |
一假則假
在邏輯與中,若參與運算的不是布爾類型,返回值有一個特點: 如果條件A不成立,那麼就返回條件A 如果條件A成立,無論條件B是否成立都返回條件B
邏輯與運算存在邏輯短路現象,當條件A爲假,則條件B就不參與運算了 |
邏輯或 || | 條件表達式A || 條件表達式B | true false |
一真則真
在邏輯或中,若參與運算的不是布爾類型,返回值有一個特點: 如果條件A成立,那麼就返回條件A 如果條件A不成立,無論條件B是否成立都返回條件B
邏輯或運算存在邏輯短路現象,當條件A爲真,則條件B就不參與運算了 |
邏輯非 ! | ! 條件表達式 | true false | 真變假,假變真 |
注:邏輯運算符的優先級是左結合性(從左到右的運算),邏輯運算符的優先級 && 高於 ||
16.JavaScript逗號運算符
逗號運算符的作用是用來簡化代碼
- 逗號運算符的結合性是左結合(從左到右的運算)
- 逗號運算符是所有運算符中優先級最低的運算符
- 逗號運算符的運算結果就是最後一個表達式的結果.
var a = ((1+1),(2+3),(5+5)); console.log(a); //輸出結果爲 10
17.0JavaScript三目運算符
條件表達式 ? 結果A : 結果B | 條件表達式爲真,則返回結果A,條件表達式爲假,則返回結果B |
18.0JavaScript數組
數組:引用數據類型(對象類型)
語法:let/var 變量名 = new Array(size) size:數組的長度.
創建數組的方式
let / var 變量名 = new Array(size) | 創建一個指定大小的數組 |
let / var 變量名 = new Array() | 創建一個空數組 |
let / var 變量名 = new Arrary(數據1,數據2,數據3, ...) | 創建一個帶數據的數組 |
let / var 變量名 = [] | 創建一個空數組 |
let / var 變量名 = [數據1,數據2,數據3, ...] | 創建一個帶數據的數組 |
數組解構賦值:
var ls = [1,2,3]; var a,b,c; [a,b,c] = ls; // a=1 b=2 c=3
注意:
1.在數組的解構賦值中,等號左邊的格式可以和等號右邊的格式不一樣,也能被完全解析
var a,b,c; [a,b,c] = [1,2,[3,4]]; // a=1 b=2 c=[3,4]
2.在數組的解構賦值中,等號左右兩邊的個數可以不一樣.
var a,b,c,d; [a,b] = [1,2,3,4,5]; // a=1 b=2 [a,b,c,d] = [1,2,3]; // a=1 b=2 c=3 d=undefined
3.在數組的解構賦值中,若右邊個數大於左邊的個數,可以給左邊的變量指定賦值.
var a,b,c,d; [a,b,c=666,d=123] = [1,2]; // a=1 b=2 c=666 d=123 [a,b,c=666,d=123] = [1,2,3]; // a=1 b=2 c=3 d=123 設置的默認值被覆蓋
4.在數組的解構賦值中,可以利用ES6新增加等擴展運算符來打包剩餘的數據. 注:擴展運算符只能寫在最後
擴展運算符 擴展運算符 ... var a,b; [a, ...b] = [1,2,3]; // a=1 b=[2,3]
注意點:
- 如果數組對應的索引中沒有存儲數據,默認存儲的是undefined;
- 訪問了數組中不存在的索引,不會報錯,會返回undefined;
- 當數組的存儲空間不夠用,數組會自動擴容
- 數組中可以存儲不同類的數據類型.
- 數組分配的存儲空間不一定是連續的.
19.0數組的增刪改查
-
修改
定義和用法
splice() 方法從數組中添加/刪除數據,然後返回被刪除的數組。
註釋:該方法會改變原始數組。
語法
array.splice(index,howmany,item1,.....,itemX)
參數 | 描述 |
---|---|
index | 必需。整數,規定添加/刪除項目的起始位置,使用負數可從數組結尾處規定位置。 |
howmany | 必需。要刪除/添加的數據數量。如果設置爲 0,則不會刪除/添加數據。 |
item1, ..., itemX | 可選。向數組添加的數據。 |
返回值
類型 | 描述 |
---|---|
Array | 如果存在被刪除的數據,返回被替的數據,如果沒有則返回一個空數組 |
var array = [1,2,3,5];
console.log(array.splice(0, 1)); // array[1] 返回被刪除的元素 原始數組變爲[2,3,5]
console.log(array.splice(10, 2)); // array[] 返回一個空數組 原始數組變爲[1,2,3,5]
說明
splice() 方法可刪除從 index 處開始的零個或多個元素,並且用參數列表中聲明的一個或多個值(item1, ..., itemX)來替換那些被刪除的元素。
2.在數組最後增加一條數據
定義和用法
push() 方法可向數組的末尾添加一個或多個元素,並返回新的長度。
語法
array.push(item1,item2 ..., itemX)
參數 | 描述 |
---|---|
item1 | 必需。要添加到數組的第一個元素。 |
item2 | 可選。要添加到數組的第二個元素。 |
itemX | 可選。可添加多個元素。 |
var array = [1,2,3];
console.log(array.push(123456)); //返回 4
返回值
返回數組array的新長度。
說明
push() 方法可把它的參數順序添加到 array 的尾部。它直接修改 array,而不是創建一個新的數組。push() 方法和 pop() 方法使用數組提供的先進後出棧的功能。
提示和註釋
註釋:該方法會改變數組的長度。
提示:要想數組的開頭添加一個或多個元素,可以使用 unshift() 方法。
3.在數組最前面增加數據
使用unshift() 方法 用法與push() 方法一樣,返回值也是新數組的長度.
4.刪除數組最後一條數據
使用pop()方法,返回值爲所刪除的數據
5.刪除數組最前面一條數據
使用shift()方法,返回值爲所刪除的數據
6.刪除數組指定索引數據
splice() 方法 splice(index,1) index 需要刪除的數據的索引下標
方法 | 描述 | 返回值 |
splice() | 在數組的指定位置,增加/刪除/替換數據 | 如果存在被刪除的數據,返回被刪除的數據,如果沒有則返回一個空數組 |
push() | 在數組末尾增加數據 | 返回數組的新長度 |
unshift() | 在數組最前面增加數據 | 返回數組的新長度 |
pop() | 刪除數組最後一條數據 | 返回值爲所刪除的數據 |
shift() | 刪除數組最前面一條數據 | 返回值爲所刪除的數據 |
7.清空數組
let array = [1,2,3,5,6,7,8];
/*方法一*/
array = [];
/*方法二*/
array.length = 0;
/*方法三*/
array.splice(0,array.length);
8.將數組轉換爲字符串
let array = [1,2,3,5,6];
let str = array.toString(); // 1,2,3,4,5,6
9.將數組轉換爲指定格式的字符串
let array = [1,2,3,5,6];
/*join()方法默認情況下無任何參數,實際上就是調用toString()方法*/
let str = array.join(); // 1,2,3,5,6
/*join()方法傳遞了參數,就會將傳遞的參數作爲元素和數組元素的連接符號*/
let str = array.join("*"); // 1*2*3*5*6
10.將兩個或多個數組拼接爲一個數組
注:數組不能使用加號+進行數組的拼接.
方法一:concat()方法用於數組的拼接.
語法:
array.concat(數組1,數組2,數組3...)
返回值:返回一個新數組,且不改變原來的數組.
方法二: ES6新增加的方法
擴展運算符(...):擴展運算符在解構賦值中(等號的左邊),表示將剩餘的數據打包成一個新的數組.
擴展運算符在等號的右邊,表示將數組中的所有數據解開,放到對應的位置中.
let array1 = [1,2,3];
let array2 = [7,8,9];
let array = [...array1, ...array2] // Array(6) [ 1, 2, 3, 7, 8, 9 ]
20.0 將數組反轉
reverse()方法:
let array = [1,2,3]; let str = array.reverse(); console.log(str); // Array(3) [ 3, 2, 1 ] console.log(array); // Array(3) [ 3, 2, 1 ]
注:reverse()方法會修改原有的數組
21.0 數組的切片
slice()方法:
array.slice(start,end)
參數 描述 start 必需。規定從何處開始選取。如果是負數,那麼它規定從數組尾部開始算起的位置。也就是說,-1 指最後一個元素,-2 指倒數第二個元素,以此類推。 end 可選。規定從何處結束選取。該參數是數組片斷結束處的數組下標。如果沒有指定該參數,那麼切分的數組包含從 start 到數組結束的所有元素。如果這個參數是負數,那麼它規定的是從數組尾部開始算起的元素。 返回值
返回一個新的數組,包含從 start 到 end (不包括該元素)的 array中的元素。
注:slice()方法不會修改原數組,而是返回一個新數組。如果想刪除數組中的一段元素,應該使用方法 array.splice()。
22.0 查找元素在數組中的位置
indexOf()方法
array.indexOf(value,startindex)
參數 描述 value 必需。規定需檢索的字符串值。 startindex 可選的整數參數。規定在字符串中開始檢索的位置。它的合法取值是 0 到 array.length - 1。如省略該參數,則將從字符串的首字符開始檢索。 返回值:如果數組中存在該元素,則返回該元素對應的位置,如果數組中不存在該元素,則返回 -1。
注:indexOf()方法默認從左到右查找,找到第一個符合條件的就會停止查找.lastIndexOf(value,startindex)方法默認從右到左查找
23.0 判斷數組是否包含某個元素
- 通過index(value)value和lastIndexOf(value)的結果來判斷,返回值爲-1則不存在.
- ES6方法:array.includes(value),返回值爲true或false
24.0 數組清零
fill() 方法用於將一個固定值替換數組的元素。
語法
array.fill(value, start, end)
參數
參數 描述 value 必需。填充的值。 start 可選。開始填充位置。 end 可選。停止填充位置 (默認爲 array.length) 返回值:返回一個數組,會改變原來的數組.
25.0 arguments的作用
保存所有傳遞給函數的實參
function getSum() {
// console.log(arguments);
let res = 0;
for(let i=0;i<arguments.length;i++){
res += arguments[i];
}
return res;
}
res = getSum(10,20,30);
console.log(res); // 60
26.0 函數擴展運算符
擴展運算符在等號的左邊,將剩餘數據全部打包到一個新數組中 注:只能寫在最後 |
|
擴展運算符在等號的右邊,將數組中的數據展開 |
|
擴展運算符在函數形參列表中,將傳遞給函數的所有實參打包到一個數組中 注:只能寫在形參列表的最後 |
|
27.0 函數默認形參
函數的默認形參爲:undefined
- 在ES6之前可以通過邏輯運算符給形參指定默認值
邏輯或 || | 條件表達式A || 條件表達式B | true false |
一真則真
在邏輯或中,若參與運算的不是布爾類型,返回值有一個特點: 如果條件A成立,那麼就返回條件A 如果條件A不成立,無論條件B是否成立都返回條件B
邏輯或運算存在邏輯短路現象,當條件A爲真,則條件B就不參與運算了 |
function getSum(a,b,c) {
a = a || 10;
b = b || 20;
console.log(a, b, c);
}
getSum(); // a = 10 b = 20 c = undefined
2. 在ES6之後
在ES6之後可以直接給形參指定默認值
function getSum(a=10,b=20,c) {
console.log(a, b, c);
}
getSum(); // a = 10 b = 20 c = undefined
注:在ES6之後函數形參的指定值還可以從其他函數中獲取
function getSum(a=10,b=20,c=getSum1()) {
console.log(a, b, c);
}
function getSum1(){
return "JavaScript";
}
getSum(); //a = 10 b = 20 c = JavaScript
28.0 匿名函數
定義:沒有名稱的函數
注:匿名函數不能只定義不使用
作爲其它函數的參數 |
|
作爲其它函數的返回值 |
|
作爲一個立即執行的函數 |
注:匿名函數如果要立即執行,就必須使用括號()將匿名函數包裹起來 |
29.0 箭頭函數 (ES6新增的函數)
ES6之前 |
支持預解析 |
不支持預解析 |
ES6之後 |
不支持預解析 |
注:
|
30.0 JavaScript變量作用域
- 通過var定義的變量,可以重複定義同名的變量,且後定義的會覆蓋先定義的.
- 通過let定義的變量,在"相同的作用域內",不可以重複定義同名的變量.
- 通過var定義的變量可以先使用後定義(預解析),但通過let定義的變量不可用先使用後定義.
- 無論是var/let定義的變量,在{}外面都是全局變量.
- 但將var定義的變量放到一個{}內,還是一個全局變量,將let定義的變量放到一個{}內,它是一個局部變量.
- 在JavaScript中,函數{}內的作用域爲局部作用域
- 在ES6中,只要{}沒有和函數結合在一起,都應該是塊級作用域
- 無論是塊級作用域還是局部作用域,省略了變量前的var/let,都會變成一個全局變量.
- 在塊級作用域中通過var定義的變量是全局變量,通過let定義的變量是局部變量,
- 在局部作用域中用var/let定義的變量是局部變量.
31.0JavaScript作用域鏈
ES6之前:
- 在ES6之前定義變量通過var
- 在ES6之前沒有塊級作用域,只有全局作用域和局部作用域
- 在ES6之前,函數大括號{}外的都是全局作用域
- 在ES6之前函數大括號{}內的都是局部作用域
ES6之前的作用域鏈
- 全局作用域,被稱爲0級作用域
- 定義函數開始的作用域就是1級,2級,3級...作用域
- JavaScript會將這些作用域鏈接成一個鏈條,這個鏈條就是作用域鏈 0--> 1 --> 2 -->3
- 除開0級作用域外,當前作用域級別等於上一層+1
變量在作用域鏈的查找規則
- 先在當前作用域中查找,如果找到則使用當前作用域中的
- 如果在當前作用域中沒有找到,就去上一級作用域中查找
- 以此類推,直到0級作用域爲止,如果0級作用域也找不到,則會報錯
ES6:
- ES6定義變量通過let
- ES6除了全局作用域,局部作用域,還新增加了塊級作用域
- ES6雖然新增加了塊級作用域,但通過let定義的變量,並沒有差異
ES6作用域鏈
- 全局作用域,被稱爲0級作用域
- 定義函數或者代碼塊都會開啓的作用域就是1級,2級,3級...作用域
- JavaScript會將這些作用域鏈接成一個鏈條,這個鏈條就是作用域鏈 0--> 1 --> 2 -->3
- 除開0級作用域外,當前作用域級別等於上一層+1
變量在作用域鏈的查找規則
- 先在當前作用域中查找,如果找到則使用當前作用域中的
- 如果在當前作用域中沒有找到,就去上一級作用域中查找
- 以此類推,直到0級作用域爲止,如果0級作用域也找不到,則會報錯
32.0 創建對象
給對象添加屬性 : 對象名稱.屬性名稱 = 值
給對象添加行爲: 對象名稱.行爲名稱 = 函數
let 對象名稱 = new Object(); |
|
let 對象名稱 = {}; |
|
let 對象名稱 = {屬性名稱:值, 行爲名稱:函數} |
|
33.0 JavaScript的函數和方法的區別
函數:函數是沒有和其它的類顯示的綁定在一起的.
方法:方法是顯示的和其它的類顯示的綁定在一起的.
區別:
- 函數可以直接調用;但方法不可用直接調用,只能通過對象來調用.
- 函數和方法內部都有一個this語句.(誰調用了當前的函數或方法,當前的this就是誰)
- 函數內部的this輸出的是window,方法內部的this輸出的是當前調用的那個對象
34.0 工廠函數
定義:工廠函數專門用於創建對象的函數,
function student(name,age) {
let obj = new Object();
obj.name = name;
obj.age = age;
obj.say = function () {
console.log("hello" + obj.name);
};
return obj;
}
let res1 = student("小明",18);
let res2 = student("張三",20);
console.log(res1);
console.log(res2);
35.0 構造函數
定義:構造函數和工廠函數一樣,都是專門用於創建對象的,構造函數本質上是工廠函數的簡寫.
構造函數與工廠函數的區別:
- 構造函數的函數名首字母必須大寫
- 構造函數只能通過new來調用
function Student(name,age) {
//系統默認在此處自動添加 let obj = new Object();
this.name = name;
this.age = age;
this.say = function () {
console.log("hello" + this.name);
}
// 系統自動在末尾添加 return this;
}
let res1 = new Student("小明",18);
let res2 = new Student("小米",20);
console.log(res1);
console.log(res2);
console.log(res1.say === res2.say); // false 不共用一個存儲空間
注:
- 當我們 let res1 = new Student("小明",18); 系統默認在構造函數裏面自動添加 let obj = new Object();
- 會自動將剛纔創建的對象賦值給this
- 會在構造函數的末尾自動添加return this;
function mysay() {
console.log("hello word");
}
function Student(name,age) {
this.name = name;
this.age = age;
this.say = mysay;
}
let res1 = new Student("小明",18);
let res2 = new Student("小米",20);
console.log(res1.say === res2.say); // true 共用一個存儲空間
優化一
let obj = {
say:function () {
console.log("hello word");
}
}; //創建一個對象,用於解決佔用全局命名匱乏的問題
function Student(name,age) {
this.name = name;
this.age = age;
this.say = obj.say;
}
let res1 = new Student("小明",18);
let res2 = new Student("小米",20);
console.log(res1.say === res2.say); // true 共用一個存儲空間
優化二
function Student(name,age) {
this.name = name;
this.age = age;
}
Student.prototype = {
say:function () {
console.log("hello word");
}
};
let res1 = new Student("小明",18);
let res2 = new Student("小米",20);
console.log(res1.say === res2.say); // true 共用一個存儲空間
prototype用於添加保存公共的函數或公共的變量
語法 object.prototype.name=value
object.prototype = {屬性:值,方法} 用逗號隔開
注:
- 存儲在prototype中的方法可以被對應的構造函數創建出來的所有對象共享prototype
- prototype中除了可以存儲方法,也可以存儲屬性
- prototype如果出現和構造函數同名的方法或屬性,對象在訪問的時候,訪問到的是構造函數中的方法或屬性.
prototype應用場景
- prototype中一般情況下用於存儲所有對象都擁有的一些共同屬性或方法,如果是對象特有的屬性或方法,則應該存儲在構造函數中
36.0 對象三角戀關係
- 每一個"構造函數"中都有一個默認屬性prototype, prototype屬性保存着一個對象,這個對象被稱之爲"原型對象"
- 每個"原型對象"中都有一個默認屬性constructor, constructor屬性指向當前原型對象對應的那個"構造函數"
- 通過構造函數創建出來的對象,被稱爲"實例對象",每個實例對象中都有一個默認屬性,該屬性被稱爲 __proto__, __proto__指向創建它的那個構造函數的原型對象
37.0 Function函數
- JavaScript中函數時引用類型(對象類型),既然是對象,那也是通過構造函數創建出來的,所有函數都是通過Function構造創建出來的對象.
- JavaScript中只要是函數就有prototype屬性,"Function函數"的prototype屬性指向"Function原型對象"
- JavaScript中只要是"原型對象"就會有constructor屬性,"Function原型對象"的constructor指向它對應的構造函數
38.0 Object函數
39.0 函數對象完整關係
注意點:
- Function函數時所有函數的祖先函數
- 所有構造函數都有prototype屬性
- 所有原型對象都有constructor屬性
- 所有函數都是對象
- 所有對象都有一個__proto__屬性
40.0原型鏈
注:在給一個對象設置不存在的屬性值的時候,不會去原型對象中查找,它會給當前對象新增加一個不存在的屬性.
function Student(name,age) { this.name = name; this.age = age; } Student.prototype = { constructor:Student, say:function () { console.log("hello word"); }, sex:"女", }; let res1 = new Student("小明",18); res1.sex = "男"; console.log(res1.sex); //男 console.log(res1.__proto__.sex); //女
41.0 JavaScript繼承性
方法一
語法:
構造函數名.prototype = new 被繼承的構造函數名;
構造函數名.prototype.constructor = 構造函數名
function Person() { this.name = null; this.age = 0; this.say = function () { console.log(this.name,this.age); } } Student.prototype = new Person(); //Student()構造函數繼承了Person()構造函數的name,age屬性和say()方法 Student.prototype.constructor = Student; function Student() { this.sex = null; this.score = 100; this.test = function () { console.log("test"); } } let zhang = new Student(); zhang.name = "zhang"; zhang.age = 18; zhang.say(); zhang.test();
方法二
注:bind方法,call方法,apply方法,都是用於修改函數或方法中的this的
bind方法,call方法,apply方法
方法 作用 語法 示例 bind修改函數或方法中this所指定的對象,並且會返回一個修改之後的新的函數,
bind方法除了可以修改this,還可以傳遞參數,但參數必須寫在this對象的後面.
let 新建對象名 = 對象名1.bind(對象名2,參數)
注:參數用逗號隔開
function text(a,b) { console.log(a, b); console.log(this); } let obj = { name :"張三", age:18, }; let fn = text.bind(obj,10,20); fn();
call
修改函數或方法中this所指定的對象,且會立刻調用修改之後的函數,
bind方法除了可以修改this,還可以傳遞參數,但參數必須寫在this對象的後面.
對象名1.call(對象名2,參數)
注:參數用逗號隔開
text.call(obj,10,200);
apply
修改函數或方法中this所指定的對象,且會立刻調用修改之後的函數,
apply方法除了可以修改this,還可以傳遞參數,但參數必須寫在this對象的後面,且通過數組的形式傳遞.
對象名1.apply(對象名2,[參數])
注:參數放到數組裏
text.apply(obj,[10,200]);
function Person(Myname,Myage) { this.name = Myname; this.age = Myage; this.say = function () { console.log(this.name,this.age); } } function Student(Myname,Myage,Myscore) { Person.call(this,Myname,Myage); //方法二彌補了方法一繼承時無法傳參的情況 this.sex = null; this.score = Myscore; this.test = function () { console.log("test"+this.score); } } let stu = new Student("張三",18,100); // 等價於如下語句 /* let stu = new Student(); stu.name = "張三"; stu.age = 18; stu.score = 100;*/ stu.say(); stu.test();
方法三
方法三:主要是用於解決方法二,無法繼承原型對象中的屬性和方法的問題.
注:要想使用Person原型對象中的屬性和方法,那麼就必須要將Student的原型對象修改爲Person的原型對象
function Person(Myname,Myage) { this.name = Myname; this.age = Myage; /*this.say = function () { console.log(this.name,this.age); }*/ } // 將say方法獨立出來 Person.prototype.say =function () { console.log(this.name,this.age); } ; // 將Student的原型對象修改爲Person的原型對象 Student.prototype = Person.prototype; Student.prototype.constructor = Student; function Student(Myname,Myage,Myscore) { Person.call(this,Myname,Myage); this.sex = null; this.score = Myscore; this.test = function () { console.log("test"+this.score); } } let stu = new Student("張三",18,100); /*stu.name = "張三"; stu.age = 18; stu.score = 100;*/ stu.say(); stu.test();
方法四
解決方法三由於修改了Person原型對象的constructor的屬性,所以破壞了Person的三角戀關係,由於Person和Student的原型對象都是同一個,所以給Student的元素添加方法,Person也會新增加方法.
function Person(Myname,Myage) { this.name = Myname; this.age = Myage; /*this.say = function () { console.log(this.name,this.age); }*/ } // 將say方法獨立出來 Person.prototype.say =function () { console.log(this.name,this.age); } ; Student.prototype = new Person(); //Student.prototype = Person.prototype; Student.prototype.constructor = Student; function Student(Myname,Myage,Myscore) { Person.call(this,Myname,Myage); this.sex = null; this.score = Myscore; this.test = function () { console.log("test"+this.score); } } Student.prototype.run=function () { console.log("run"); }; let per = new Person(); let stu = new Student("張三",18,100); /*stu.name = "張三"; stu.age = 18; stu.score = 100;*/ per.run(); //報錯
方法:
- 在子類的構造函數中通過call藉助父類的構造函數 Person.call(this,Myname,Myage);
- 將子類的原型函數對象修改爲父類的實例對象 Student.prototype = new Person(); Student.prototype.constructor = Student;
42.0JavaScript多態
強類型語言:一般編譯語言都是強類型語言,要求變量的定義要嚴格符合定義
弱類型語言:一般解釋語言都是弱類型語言,不會嚴格要求變量的使用要嚴格符合定義
多態在編程語言中的體現:父類型變量保存子類型對象,父類型變量當前保存的對象不同,產生的結果也不同.
43.0JavaScript類和對象
在ES6前通過構造函數來定義類,從ES6開始,通過關鍵字class來定義類
語法:
注:不能通過static直接定義靜態屬性(大多數瀏覽器不支持),需要通過 類名.屬性名 = 屬性值 Person.sex = "男"
class Person{ //實例屬性 name = "張三"; //不是Es6推薦的寫法 age = 18; //實例方法 say(){ console.log(this.name,this.age); } //靜態屬性/方法通過類名調用 如 Person.num Person.run() //靜態屬性 static num = 123; // 火狐瀏覽器不支持此方法 //靜態方法 static run(){ console.log("run"); } } let per = new Person(); //創建實例對象 per.say(); console.log(Person.num);//調用靜態屬性 console.log(Person.run());//調用靜態方法
class Person{ //當通過new創建對象的時候,系統會自動調用constructor constructor(myName,myAge){ this.name = myName; this.age = myAge; } say(){ console.log(this.name, this.age); } } let per = new Person("張三",18); per.say();
在原型對象中保存屬性和方法
方法一:
Person.prototype.sex = "男";
Person.prototype.hi = function () {
console.log("hello");
};
方法二:
44.0 JavaScriptES6繼承
語法 class 類名 extends 被繼承的類名{}
示例
class Person{
constructor(myName,myAge){
this.name = myName;
this.age = myAge;
}
say(){
console.log(this.name,this.age);
}
}
//以下代碼含義:告訴瀏覽器Student這個類將繼承Person這個類
class Student extends Person{
constructor(myName,myAge,myScore){
//在子類中通過call/apply方法藉助父類的構造函數
super(myName,myAge);//等效於 Person.call(this,myName,myAge);
this.score = myScore;
}
study(){
console.log("study");
}
}
let stu = new Student("小明",18,100);
console.log(stu);
stu.say() // 小明 18
45.0 獲取對象類型
實例對象名.constructor.name
示例
class Person{
constructor(myName,myAge){
this.name = myName;
this.age = myAge;
}
say(){
console.log(this.name,this.age);
}
}
let obj = new Object();
let arr = new Array();
let p = new Person();
console.log(typeof obj, typeof arr, typeof p); // Object Object Object
console.log(obj.constructor.name); // Object
console.log(arr.constructor.name); // Array
console.log(p.constructor.name); // Person
46.0 JavaScript instanceof關鍵字
instanceof關鍵字:用於判斷"對象",是否是指定構造函數的"實例"
語法: 實例對象名稱 instanceof 對象名稱
class Person{
constructor(myName){
this.name = myName;
}
}
class Student{
constructor(myAge){
this.age = myAge;
}
}
let per = new Person();
let stu = new Student();
console.log(per instanceof Person); // true
console.log(stu instanceof Person); // false
注意點:只要構造函數的原型對象出現在實例對象的原型鏈中都會返回true
function Person(myName,myAge) { this.name = myName; this.age = myAge } function Student(myName,myAge,myScore) { Person.call(this,myName,myAge); this.score = myScore; } Student.prototype = new Person(); Student.prototype.constructor = Student; let stu = new Student(); console.log(stu instanceof Person); //true
47.0 JavaScript isPrototypeOf屬性
isPrototypeOf屬性:用於判斷一個對象是否是另一個對象的原型
class Person{
constructor(myName,myAge){
this.name = myName;
this.age = myAge;
}
}
class Student{
constructor(myScore){
this.score = myScore;
}
}
let per = new Person();
console.log(Person.prototype.isPrototypeOf(per));//true
console.log(Student.prototype.isPrototypeOf(per)); //false
注意點:只要調用者在傳入對象的原型鏈上都會返回true
function Person(myName,myAge) { this.name = myName; this.age = myAge } function Student(myName,myAge,myScore) { Person.call(this,myName,myAge); this.score = myScore; } Student.prototype = new Person(); Student.prototype.constructor = Student; let per = new Person(); let stu = new Student(); console.log(Person.prototype.isPrototypeOf(stu));//true
48.0 判斷某一個對象是否擁有某一個屬性
注: in 只要類中或原型對象中有該屬性,就返回true
function Person(myName) {
this.name = myName;
}
function Teacher(myName,myPosition) {
Person.call(this,myName);
this.position = myPosition;
}
Teacher.prototype = new Person();
Teacher.prototype.constructor = Teacher;
class Student{
constructor(myScore){
this.score = myScore;
}
}
let per = new Person();
let stu = new Student();
let tea = new Teacher();
console.log("name" in per); //true
console.log("score" in stu); //true
console.log("name" in stu); //false
//存在繼承關係
console.log("name" in tea); // true
49.0 判斷某一個對象自身是否擁有某一個屬性
hasOwnProperty()方法只會去它的類中尋找屬性,不會去原型對象中去尋找
function Person(myName) {
this.name = myName;
}
function Teacher(myName,myPosition) {
Person.call(this,myName);
this.position = myPosition;
}
Teacher.prototype = new Person();
Teacher.prototype.constructor = Teacher;
Person.prototype.height = 180;
let per = new Person();
let tea = new Teacher();
console.log(per.hasOwnProperty("name")); //true
console.log(per.hasOwnProperty("height")); //false height爲類中原型對象的屬性
console.log(tea.hasOwnProperty("name")); //true
50.0對象的增刪改查
class Person{}
let per = new Person();
//添加屬性/方法
per.name = "張三"; // per["name"] = "張三"
per.say = function(){
console.log("hello");
};
per["run"] = function(){
console.log("run");
};
//刪除屬性/方法
delete per.name; // delete per["name"]
delete per.say; // delete per["say"]
//修改屬性/方法 ----> 同名屬性/方法的覆蓋 與添加屬性的方法一樣
//查詢屬性/方法 ----> 實例對象名.屬性名/方法名 實例對象名["屬性名/方法名"]
51.0 對象遍歷
在JavaScript中可以通過高級for循環來遍歷對象
語法:
for(let key for obj){}
class Person{
constructor(myName,myAge){
this.name = myName;
this.age = myAge;
this.run = function () {
console.log("run run");
}
}
//注意點:ES6定義類的格式,會將方法默認放到原型對象中
say(){
console.log(this.name, this.age);
}
}
let per = new Person("張三",18);
for(let key in per){
console.log(key); // name age run
console.log(per[key]); //代碼含義取出per對象中名稱叫做當前遍歷到的名稱的屬性或方法的值
console.log(per.key); //不能這樣寫 代碼含義是取出per對象中名稱爲key的屬性/或方法的值
}
52.0 對象的解構賦值
對象的解構賦值和數組的解構賦值,除了符號不一樣,其它的都一模一樣,數組的解構使用[] ,對象的解構賦值使用 {}
示例:
let obj = {
name:"zhang",
age:18,
}
let {name,age} = obj;
console.log(name, age); // zhang 18
let {name,age,height } = {name:"zhang",age:18};
console.log(name, age, height); //zhang 18 undefined
let {name,age,height = 1.70 } = {name:"zhang",age:18};
console.log(name, age, height); //zhang 18 1.70
let {age} = {name:"zhang",age:18};
console.log(age); //18
注意點:
- 在對象的解構賦值中,左邊的變量名稱必須和對象的屬性名稱一致,纔可以解構出數據
let {a,b} = {name:"張三",age:18};
console.log(a, b); // undefined undefined
解構賦值應用場景
函數傳參
let array = [1,2,3];
function sum([a,b,c]) {
return a+b+c;
}
let res = sum(array);
console.log(res); // 6
let obj = {
name:"zhang",
age:18,
};
function say({name,age}) {
console.log(name, age);
}
say(obj); //zhang 18
53.0 JavaScript的深拷貝和淺拷貝
深拷貝 |
修改新變量的值不會修改原有變量的值 默認情況下,基本數據類型都是深拷貝 |
淺拷貝 |
修改新變量的值會修改原有變量的值 默認情況下,引用類型都是淺拷貝 |
class Person{
constructor(myName,myAge){
this.name = myName;
this.age = myAge;
}
say(){
console.log(this.name, this.age);
}
}
// 淺拷貝
let per = new Person("zhang",18);
let per1 = per;
per1.name = "li";
console.log(per.name, per1.name); // li li
//深拷貝
let per2 = new Person();
per2.name = per.name; // li
per2.name = "xiao"; // xiao
console.log(per.name, per1.name, per2.name); //li li xiao
//將per的所有屬性拷貝到per2中
for(let key in per){
per2[key] = per[key];
console.log(per2[key]);
}
assign(p1,p2)方法,可以將p2中的所有屬性拷貝到p1中
//assign(p1,p2)方法,可以將p2中的所有屬性拷貝到p1中 let obj = new Object(); obj.name = "zhang"; obj.age = 18; let obj1 = new Object(); Object.assign(obj1,obj); console.log(obj1); //{name: "zhang", age: 18}
深拷貝
class Person{ name = "zhang"; cat = { age:18, }; score = [1,2,3]; } let per1 = new Person(); let per2 = new Object(); function depCopy(target,source) { //通過遍歷拿到source中的所有屬性 for(let key in source){ //取出當前遍歷到的屬性對應的取值 let sourceValue = source[key]; //console.log(sourceValue); //判斷當前取值是否爲引用數據類型 if(sourceValue instanceof Object){ //console.log(sourceValue.constructor); //console.log(new sourceValue.constructor); let subTarget = new sourceValue.constructor; target[key] = subTarget; depCopy(subTarget,sourceValue); }else { target[key] = sourceValue; } } } depCopy(per2,per1); console.log(per2);
54.0 數組高級API
傳統遍歷數組的方法
let array = [1,2,3,5,6,7,8]; //傳統遍歷數組的方法 for (let i=0;i<array.length;i++){ console.log(array[i]); } //在企業開發中不推薦使用for in循環來遍歷數組,for in循環一般用來遍歷對象的 for(let key in array){ console.log(key); } function Person() { this.name = "zhang"; this.age = 18; this.score = 100; } let per = new Person(); console.log(per); //對象中的屬性是無序 /* Person {name: "zhang", age: 18, score: 100} age: 18 name: "zhang" score: 100 __proto__: Object*/
利用ES6中推出的for of 循環來遍歷數組
let array = [1,2,3]; for(let value of array){ console.log(value); }
利用Array數組對象的forEarch方法來遍歷數組
forEarch方法會自動調用傳入的函數,每次調用都會將當前遍歷到的元素,當前遍歷到的索引,當前被遍歷的數組傳遞給這個函數
let array = [1,2,3]; array.forEach(function (currentValue,currentIndex,currentArray) { console.log(currentValue, currentIndex, currentArray); /* 1 0 (3) [1, 2, 3] 2 1 (3) [1, 2, 3] 3 2 (3) [1, 2, 3]*/ })
重寫forEach方法
let array = [1,2,3]; // 重寫forEach方法 Array.prototype.myForEach = function (fn) { for(let i=0;i<this.length;i++){ fn(this[i],i,this); } } array.myForEach(function (currentValue, currentIndex, currentArray) { console.log(currentValue, currentIndex, currentArray); })
數組的findIndex方法
findIndex方法:定製版的indexOf,找到返回索引,找不到返回-1
let array = [1,3,7,9]; let index = array.findIndex(function (currentValue, currentIndex, currentArray) { if(currentValue === 11) return true; }); console.log(index); // -1
數組的find方法
find返回找到的元素,找到則返回該元素,找不到返回undefined
let array = [1,2,3,7,8,9]; let value = array.find(function (currentValue, currentIndex, currentArray) { if(currentValue === 7) return true; }); console.log(value);
數組過濾(數組的filter方法)
filter方法:將滿足條件的元素添加到一個新的數組中
let array = [1,2,3,7,8,9,10]; // 將數組中是2的倍數是元素添加到newArray數組中 let newArray = array.filter(function (currentValue, currentIndex, currentArray) { if(currentValue % 2 === 0) return true; }); console.log(newArray); // [2,8,10]
數組映射(map方法)
map方法:將滿足條件的元素映射到一個新的數組中
let array = [1,2,3,7,8,9,10]; // 將數組中是2的倍數是元素映射到newArray數組中 let newArray = array.map(function (currentValue, currentIndex, currentArray) { if(currentValue % 2 === 0) return currentValue; }); console.log(newArray); //[undefined, 2, undefined, undefined, 8, undefined, 10]
刪除數組元素
- splice()
- delete array[index] 通過delete來刪除數組中的元素,數組的length屬性不會發生變化
數組排序
- array.sort()
如果 compareFunction(a, b) 小於 0 ,那麼 a 會被排列到 b 之前; 如果 compareFunction(a, b) 等於 0 , a 和 b 的相對位置不變。 如果 compareFunction(a, b) 大於 0 , b 會被排列到 a 之前。 compareFunction(a, b) 必須總是對相同的輸入返回相同的比較結果,否則排序的結果將是不確定的。 注:如果元素是字符串類型,那麼比較的是字符串的Unicode編碼,如果數組中元素是數組類型,如果需要升序排序,直接 return a-b;如果需要降序排序,直接return b - a;
let array = ["c","a","b"];
array.sort(function (a,b) {
if(a>b){
return 1;
}else if(a<b){
return -1;
}else {
return 0;
}
// return a-b; 數值類型
});
console.log(array);
按字符串長度排序
let array = ["22","1","123","12345","33","789123456"];
array.sort(function (str1,str2) {
// return str1.length - str2.length; // 升序
return str2.length - str1.length; //降序
});
console.log(array);
按對象的某一個屬性排序
let array = [
{name:"zs",age:18},
{name:"ls",age:20},
{name:"ww",age:15},
];
array.sort(function (a,b) {
return a.age - b.age; //按年齡升序排序
});
console.log(array);
55.0 字符串常用方法
- 獲取字符串長度 str.length
- 獲取某個字符 str[索引] / charAt(索引)
- 字符串查找 index lastIndex includes
index[value] | 返回value在字符串中的index |
astIndex[value] | 從字符串後面往回找,返回value在字符串中的index |
includes[value] | 找到則返回true,找不到則返回false |
- 字符串拼接 concat sr1.concat(str2) / str1 + str2
- 截取子字符串
str.slice(stratindex,endindex) | 不包括endindex 返回截取到的字符串 |
str.substring(stratindex,endindex) | |
str.substr(startindex,count) | count 截取的個數 返回截取到的字符串 |
字符串切割
let array = [1,2,3]; let str = array.join("-"); console.log(str); //1-2-3 let str1 = "1-2-3"; let array1 = str1.split("-"); console.log(array1); // ["1", "2", "3"]
判斷字符串是否以指定字符串開頭 ES6
let str = "www.baidu.com"; let res = str.startsWith("www"); console.log(res); // true
判斷字符串是否以指定字符串結尾 ES6
let str = "www.baidu.com"; let res = str.endsWith("com"); console.log(res); // true
字符串模板 ES6
- let str = "" ; 雙引號
- let str = '' ; 單引號
格式化輸出字符串(字符串模板)
let str = `` ; 反引號(Esc鍵下邊,數字鍵1左邊)
let name = "張三";
let age = 18;
str = `我的名字叫${name},我的年齡是${age}`;
console.log(str);
56.0 基本類型和基本包裝類型
基本數據類型:字符串類型,數值類型,布爾類型,空類型,未定義類型
常量:通過字面量創建的基本數據類型的數據都是常量
常量的特點:常量是不能被修改的,每次修改或拼接都生成一個新的.
基本類型特點:沒有屬性和方法
對象類型特點:有屬性有方法
基本包裝類型:String() Number() Boolean() Array() Funtion() Object() Data() RegExp()
JavaScript中提供了三種自帶的對象
本地對象 |
與宿主無關,無論在瀏覽器還是在服務器中都有對象, 它是ECMAScript標準中定義的類(構造函數) 在使用過程中需要手動new創建 如 String() Number() Boolean() Array() Funtion() Object() Data() RegExp()
|
內置對象 |
與宿主無關,在瀏覽器和服務器中都有對象 ECMAScript已經自動創建好對象 在使用過程中無需手動new創建 如:Global Math JSON |
宿主對象 |
對於鑲嵌到網頁中的JavaScript,其宿主對象就是瀏覽器,所以宿主對象就是瀏覽器提供的對象 包含: Window 和 Document 所有的DOM和BOM對象都屬於宿主對象 |
宿主:宿主是JavaScript的運行環境,JavaScript可以在瀏覽器中運行,也可以在服務器上運行(node.js)
Math.floor() | 向下取整 |
Math.ceil() | 向上取整 |
Math.round() | 四捨五入 |
Math.abs() | 絕對值 |
Math.random() | 生成隨機數 |