文章目錄
- 一、JavaScript基礎
- 1.變量(重點)
- 1-1 定義變量及賦值
- 1-2 變量的命名規則和命名規范
- 判斷數據類型:
- 2.數據類型轉換
- 2-1 其他數據類型轉成數值
- 2-2 其他數據類型轉成字符串
- 2-3 其他數據類型轉成布爾
- 3.函數
- 3-1函數定義階段
- 3-2函數調用階段
- 3-3 調用上的區別
- 3-4 函數的參數
- 3-5 函數的定義域
- 4.對象
- 4-1 創建對象
- 4-2 數據類型之間存儲的區別
- 5.數組
- 5-1 數組的常用方法
- 6.字符串
- 6-1 字符串的常用方法
- 6-2 json字符串(主要用來前后端交流)
- 6-3 模板字符串
- 7.數字
- 7-1 數字的常用方法
- 8.時間對象
- 8-1創建時間對象
- 8-2 時間對象的常用方法
- 8-3 倒計時計時器
- 8-4 間隔定時器
- 二、BOM
- 1. 獲取瀏覽器窗口的尺寸
- 2. 瀏覽器的彈出層
- 3.瀏覽器的地址信息
- 4. 瀏覽器的常見事件
- 5. 瀏覽器的歷史記錄
- 6. 瀏覽器本地存儲
- 6-1 loclocalStorage:永久存儲
- 6-2 sessionStorage:臨時存儲
- 三、DOM
- 1. 獲取一個元素
- 2. 操作元素屬性
- 2-1 操作原生屬性
- 2-2 自定義屬性
- 3. 操作元素文本內容
- 4. 操作元素樣式
- 5. 操作元素類名
- 6. DOM節點
- 6-1 元素節點
- 6-2 屬性節點
- 6-3 文本節點
- 6-4 獲取節點的方式
- 6-5 節點操作
- 6-6 節點屬性
- 6-7 獲取元素尺寸
- 6-8 獲取元素偏移量
- 6-9 獲取可視窗口的尺寸
- 7. 事件
- 7-1 初識事件
- 7-2 事件解綁
- 7-3 事件類型
- 7-4 事件對象
- 7-5 事件委托
- 8. 正則表達式
- 8-1 元字符
- 8-2 邊界符
- 8-3 限定符
- 8-4 特殊符號
- 8-5 捕獲exec
- 8-6 正則與字符串方法
- 9. this指向
- 四、ES6
- 1. ES6定義變量
- 2. ES6的箭頭函數
- 3. ES6的解構賦值
- 4. ES6的展開運算符
- 5. ES6模塊化語法
- 五、面向對象
- 1. 對象基礎
- 1-1 創建對象
- 1-2 屬性訪問
- 2. 構造函數
- 2-1 基本用法
- 2-2 new關鍵字的作用
- 2-3 注意事項
- 3. 原型(Prototype)
- 3-1 原型鏈機制
- 3-2 原型相關方法
- 4. ES6 Class
- 4-1 類定義
- 4-2 繼承
- 5. 繼承
- 5-1 構造函數繼承
- 5-2 原型鏈繼承
- 5-3 組合繼承(經典繼承)
- 5-4 ES6類繼承
- 六、ajax
- 1. 基本用法
- 1-1 創建 `XMLHttpRequest `對象
- 1-2 配置請求
- 1-3 發送請求
- 1-4 處理響應
- 2. 封裝ajax
- 七、Promise
- 1. Promise基本語法
- 2. Promise的生命周期
- 3. 鏈式調用
- 4.Promise靜態方法
- 5.Promise 與 async/await
- 6. Fetch
- 6-1 基本使用方法
- 6-2 響應對象屬性
- 6-3 解析不同格式的響應
- 6-4 網絡錯誤處理
- 7. jsonp
一、JavaScript基礎
1.變量(重點)
-
變量指的是在程序中保存數據的一個容器
語法:var 變量名 = 值
1-1 定義變量及賦值
//定義一個變量
var num//給一個變量賦值
num = 100//定義一個變量的同時給其賦值
var num2 = 200
- 注意:
- 一個變量名只能存儲一個值
- 當再次給一個變量賦值的時候,前面一次的值就沒有了
- 變量名稱區分大小寫(
js
嚴格區分大小寫)
1-2 變量的命名規則和命名規范
-
規則:必須需遵守的
- 一個變量名稱可以由**數字、字母、英文下劃線(__)、美元符號($)**組成
- 嚴格區分大小寫
- 不能由數字開頭
- 不能是保留字或者關鍵字
- 不要出現空格
-
規范:建議遵守
- 變量名盡量有意義(語義化)
- 遵循駱駝命名規則,有多個單詞組成的時候,從第二個單詞開始首字母大寫
- 不要使用中文
-
判斷數據類型:
-
使用
typeof
關鍵字來進行判斷//第一種使用方式 var n1 = 100 console.log(typeof n1)//第二種使用方式 var s1 = 'abc' console.log(typeof(s1))
-
2.數據類型轉換
- 數據類型之間的轉換,比如數字轉成字符串,字符串轉成布爾,布爾轉成數字等
2-1 其他數據類型轉成數值
-
Number(變量)
可以把一個變量強制轉換成數值類型
可以轉換小數,會保留小數
可以轉換成布爾值
以下都是:遇到不可轉換的都會返回
NaN
-
parseInt(變量)
從第一位開始檢查,是數字就轉換,直到一個不是數字的內容
開頭不是數字就直接返回
NaN
不認識小數點,只能保留整數
-
parseFloat(變量)
從第一位開始檢查,是數字就轉換,直到一個不是數字的內容
開頭不是數字就直接返回
NaN
認識一次小數點
2-2 其他數據類型轉成字符串
-
變量.toString()
有一些數據類型不能用
toString()
方法,如:undefined
和null
-
String(變量)
所有數據類型都能用
-
使用加法運算
字符串拼接:有一方是字符串就會拼接
加法運算:只有兩邊都是數字才會進行數學運算
2-3 其他數據類型轉成布爾
-
Boolean(變量)
在js中,只有
''
、0
、null
、undefined
、NaN
,這些是false
,其他都是true
3.函數
-
對于
js
來說,函數就是把任意一段代碼放在一個盒子里面 -
代碼:
//這個是我們以前寫的一段代碼 for (var i = 0 ; i < 10 ; i++) {console.log(i) }//函數,這個 {} 就是那個“盒子” function fu() {//這個函數我們以前寫的代碼for (var i = 0 ; i < 10 ; i++) {console.log(i)} }
3-1函數定義階段
聲明式
-
使用
function
這個關鍵字來聲明一個函數 -
語法:
function fn() {//一段代碼 } //function:聲明函數的關鍵字 //fn:函數的名字,自己定義 //():必須寫,放參數的位置 //{} : 就是放一段代碼的位置也就是剛剛說的“盒子”
賦值式
-
其實就是使用
var
關鍵字一樣 -
首先使用
var
定義一個變量,把一個函數當做值直接復制給這個變量就可以了 -
語法:
var fn = function() {//一段代碼 }
3-2函數調用階段
調用一個函數
- 函數調用就是直接謝
函數名()
即可
//聲明式函數 function fn() {console.log("我是fn函數") }//調用函數 fn()//賦值式函數 var f1 = function(){console.log("我是f1函數") }//調用函數 f1()
- 注意:定義完一個函數以后,如果沒有調用函數,那么寫在{}里面的代碼沒有意義,只有調用以后才會執行
3-3 調用上的區別
- 聲明式函數:調用可以在定義之前或者定義之后
- 賦值式函數:調用只能在定義之后
3-4 函數的參數
-
參數分為兩種形參和實參
//聲明式 function fn(形參) {一段代碼 }fn(實參)//賦值式一樣的位置,寫在"()"里面
3-5 函數的定義域
-
訪問規則
- 首先,在自己的作用域內部查找,如果有,就直接拿來用
- 如果沒有,就去上一級作用于查找,如果有,就拿來用
- 以此類推
- 如果一直沒有這個變量就會直接報錯
var num = 100function fn() {var num2 = 200function fn2() {var num3 = 300console.log(num3)//300console.log(num2)//200console.log(num)//100console.log(a)//都沒有就是直接報錯}fn2() }fn()
- 變量的訪問規則也叫做作用域的查詢機制
- 作用域的查找機制只能是向上查找不能向下找
function fn() {var num = 100 } fn()console.log(num)//發現自己作用域沒有,自己就是全局作用域,沒有上一級了,直接報錯
-
賦值規則
- 先在自己作用域內部查找,有就直接賦值
- 沒有就去上一級作用域內部查找,有就直接賦值
- 以此類推
- 如果一直找到全局作用域都沒有,那么就把這個變量定義為全局變量,再給他賦值
-
4.對象
-
對象是一個復雜數據類型
-
存儲了一些基本數據類型的一個集合
var obj = {num : 100,str : 'hello world',boo : true }
-
這里的
{}
和函數中的{}
不一樣 -
函數里面的是寫代碼的,而對象里面是寫一些數據的
-
對象就是一個鍵值對的集合
-
{}
里面的每一個鍵都是一個成員
4-1 創建對象
-
字面量的方式創建一個對象
//創建一個空對象 var obj = {}//向對象中添加成員 obj.name = 'jack' obj.age = 18
-
內置構造函數的方式創建對象
//創建一個空對象 var obj = new Object()//向對象中添加成員 obj.name = 'jack' obj.age = 18
Object
是js
內置給我們的構造函數,用于創建一個對象使用的
4-2 數據類型之間存儲的區別
- 我們的存儲空間分成兩種棧和堆
- 棧:主要存儲基本數據類型的內容
- 堆:主要存儲復雜數據類型的內容
基本數據類型在內存中的存儲情況
var num = 100
,在內存中的存儲情況- 直接在
棧空間
內有存儲一個數據
復雜數據類型在內存中的存儲情況
-
下面這個對象的存儲
var obj = {name : "java",age : 18,gender : '男' }
-
復雜數據類型的存儲
- 在堆里面開辟一個存儲空間
- 把數據存儲到存儲空間內
- 把存儲空間的地址賦值給棧里面的變量
5.數組
5-1 數組的常用方法
-
push() :在數組的末尾添加一個或多個元素,并返回新的長度
-
pop() :刪除數組的最后一個元素,并返回該元素的值
-
unshift() :在數組的開頭添加一個或多個元素,并返回新的長度
-
shift() :刪除數組的第一個元素,并返回該元素的值
-
splice() :從數組中添加或刪除元素
//splice() -> 刪除元素: var arr = [1 , 2 , 3 , 4] var ressplice = arr.splice(1 , 2) //第一個參數是要開始刪除的位置下標 //第二個參數是要刪除元素的個數 //ressplice表示返回值,是刪除元素組成的集合//splice() -> 增加元素: var arr1 = [1 , 2 , 3 , 4] var ressplice1 = arr.splice(1 , 0 , "zhangsan" , "lisi") //后面兩個參數是增加的元素 //前面兩個表示在第一個元素的位置不刪除元素,但是在這個位置增加兩個元素
-
sort() :對數組的元素進行排序
//不能直接用arr.sort()的用法 arr.sort(function(a , b){return a - b //表示從小到大排序//return b - a 表示從大到小排序 })
-
reverse() :顛倒數組中元素的順序
以上方法都會對原數組造成影響
-
concat() :連接兩個或多個數組,并返回新的數組,并不會改變原來的數組
-
slice() :從數組中截取一部分,并返回新的數組,并不會影響原數組
var arr = [1 , 2 , 3 , 4] var arr2 = arr.slice(0 , 2) //[1 , 2] ,截取的數組是左閉右開 //-1表示最后一個數,可以用負數表示
-
indexOf() :返回數組中指定元素的第一個索引,-1就表示找不到
-
lastIndexOf() :返回數組中指定元素的最后一個索引,-1就表示找不到
-
join() :將數組的所有元素連接成一個字符串
arr.join()//默認會用“,”隔開 arr.join("|")//會用“|”隔開,里面可以是任意字符
-
forEach() :對數組的每個元素執行一次指定的函數
//forEach()遍歷 var arr = ["aaa" , "bbb" , "ccc"] //回調函數 arr.forEach(function(item , index , arr) {console.log(item , index , arr) }) //item : 表示數組里面的值 //index : 表示當前位置的索引 //arr : 表示數組,每次都會重新將數組打印一遍
-
map() :對數組的每個元素執行一次指定的函數,并返回一個新的數組
var arr = [1 , 2 , 3 , 4] //回調函數 var arr1 = arr.map(function(item) {return item * item }) console.log(arr1) //表示將arr數組中每個數的平方加入到arr1數組中
-
filter() :對數組的每個元素執行一次指定的函數,并返回一個新的數組,該數組只包含滿足條件的元素(只會返回
true
和false
)var arr = [1 , 2 , 3 , 4] //回調函數 var arr1 = arr.filter(function(item) {return item > 2 }) console.log(arr1) //只包含[3 , 4] ,把1 和 2都過濾掉了
-
every() :對數組的每個元素執行一次指定的函數,如果所有元素都滿足條件,則返回 true
var arr = [1 , 2 , 3 , 4] //回調函數 var arr1 = arr.every(function(item) {return item > 2 }) console.log(arr1) //返回false,因為前面兩個數不滿足 //[3 , 4 , 5]返回true,因為所有的元素都滿足條件
-
some() :對數組的每個元素執行一次指定的函數,如果有任意一個元素滿足條件,則返回 true
-
reduce() :對數組的每個元素執行一次指定的函數,并返回一個值
var arr = [1 , 2 , 3 , 4 , 5]var arr1 = arr.reduce(function(prev , item){return prev + item } , 0) console.log(arr1)//輸出15,表示所有數字累加 //prev表示每次計算后的結果,開始數據為后面的寫入數據為0,(也可以寫"",這樣就表示字符串的拼接操作) //item表示當前數組的值
-
reduceRight() :對數組的每個元素執行一次指定的函數,并返回一個值,該值是從右到左計算的
-
find() :返回數組中第一個滿足條件的元素
-
findIndex() :返回數組中第一個滿足條件的元素的索引
-
fill() :用指定的值填充數組的指定位置
-
copyWithin() :將數組的一部分復制到另一個位置
6.字符串
6-1 字符串的常用方法
-
charAt():返回指定位置的字符
-
charCodeAt():返回指定位置的字符的 Unicode 編碼
-
fromCharCode():將 Unicode 編碼轉換為字符
-
toUpperCase():將字符串轉換為大寫
-
toLowerCase():將字符串轉換為小寫
-
substr(開始索引,長度):返回指定位置的子字符串
-
substring(開始索引,結束索引):返回指定位置的子字符串(左閉右開,不能用負數)
-
slice(開始索引,結束索引):返回指定位置的子字符串(左閉右開,可以使用負數)
-
replace():替換字符串中的指定字符
var str = "asdfsdafdsaf" var str1 = str.replace("a" , "*") //第一個參數"a"表示要修改的字符 //第二個參數"*"表示將原來的字符修改成這個 //注意不能全部修改只能修改第一次出現的,并不是把所有的"a"改成"*",只能改第一個
-
split():將字符串分割為數組
var str = "a|b|c|d" console.log(str.split("|")) //表示將原來的字符串按照"|"進行分割形成一個新數組["a" , "b" , "c" , "d"]
-
indexOf():返回指定字符在字符串中第一次出現的位置
var str = "adsafdsaf" console.log(str.indexOf("a")) //返回第一次出現"a"的下標 console.log(str.indexOf("a" , 1)) //表示從索引1開始往后查的第一個"a"的下標,在1前面的不用算
-
lastIndexOf():返回指定字符在字符串中最后一次出現的位置
-
concat():連接字符串
-
trim():去除字符串兩端的空格
-
trimStart() 和 trimLeft() :去掉首空格
-
trimEnd() 和 trimRight() : 去掉尾空格
6-2 json字符串(主要用來前后端交流)
json字符串的格式:'{"key" : 110 , "key" : "110"}'
- 里面用了" ",最外面就要用’ ’
- key值必須要用" "包裹
- value值隨便,如果是字符串就用"",如果是數字就直接寫
- 不能有多余的”,“ 只能是數據之間用逗號隔開
-
json字符串轉為對象
var str = '{"name" : "nb" , "age" : 18}' var obj = JSON.parse(str) console.log(obj)
-
對象轉為json字符串
var obj = {name "tiechui"} var str = JSON.stringify(obj) console.log(obj , str)
6-3 模板字符串
普通字符串用單引號或雙引號來表示,而模板字符串用``來表示
var name = "aaa\
bbb\
ccc
"
//普通字符串想要換行輸入就要加上"\"var name1 = `aaa
bbb
ccc`
//模板字符串就可以直接換行var myname = "xie"
var str = `my name is ${myname} ${10 + 20} ${10 > 20 ? 'aaa' : 'bbb'}`
//這種寫法會把${}里面的數據自動解析,如myname會自動寫成xie
7.數字
7-1 數字的常用方法
-
toFixed():保留幾位小數,返回的是字符串
var price = 123.4567var sum = price.toFixed(2) - 0 + 100 //因為返回的是字符串,所以要先減去0,變成數字再加上100 console.log(sum.toFixed(2))//223.46 //表示結果取兩位小數
-
Math.random():隨機數
//0-10 不包含10 var res = Math.floor(Math.random() * 10)//0-10 包含10 var res = Math.floor(Math.random() * (10 + 1))//10-20 不包含20 var res = Math.floor(Math.random() * 10) + 10//10-20 包含20 var res = Math.floor(Math.random() * (10 + 1)) + 10
-
Math.round():四舍五入取整
-
Math.ceil():向上取整
-
Math.floor():向下取整
-
Math.abs():絕對值
-
Math.pow():冪
-
Math.sqrt():開方
-
Math.max():最大值
-
Math.min():最小值
-
Math.PI:圓周率
-
Math.E:自然對數的底數
8.時間對象
8-1創建時間對象
//不傳參數,表示當前的北京時間
var date = new Date()
console.log(date);//自動轉為字符串//new Date傳參
//1個參數 毫秒數
var date1 = new Date(1000)
console.log(date1);//1970-1-1 08:00:01
//都是從1970年1月1日開始計算的,因為中國是東八區,所以是8小時
//2個參數 年 月
var date2 = new Date(2020,10)//月份是從0開始的
console.log(date2);//2020-11-01 08:00:00
//3個參數 年 月 日
var date3 = new Date(2020,10,10)
console.log(date3);//2020-11-10 08:00:00
//后面的時 分 秒依次類推//new Date傳字符串
var date8 = new Date('2020-11-10 10:10:10')
console.log(date8);//2020-11-10 10:10:10
var date9 = new Date('2020/11/10 10:10:10')
console.log(date9);//2020-11-10 10:10:10
8-2 時間對象的常用方法
-
getFullYear() 獲取年份
-
getMonth():獲取月份
返回的數字是0-11 ,對應的月份是1-12月
-
getDate():獲取日期
-
getDay():獲取星期
周日對應的是0 周一到周六:1-6
-
getHours():獲取小時
-
getMinutes():獲取分鐘
-
getSeconds():獲取秒
-
getMilliseconds():獲取毫秒
-
getTime():獲取時間戳
是距離1970-1-1 00:00:00的毫秒數,本身不是, 返回的是一串隨機數
//時間戳轉換為時間對象
var date10 = new Date(1605070610100)
-
setFullYear():設置年份
-
setMonth():設置月份
-
setDate():設置日期
-
setHours():設置小時
-
setMinutes():設置分鐘
-
setSeconds():設置秒
-
setMilliseconds():設置毫秒
-
setTime():設置時間戳
8-3 倒計時計時器
-
語法:
setTimeout(需要執行的函數,多長時間后執行)
var timerId = setTimeout(function() {console.log("我執行了") } , 1000) console.log(timerId) //1clearTimeout(timerId) //表示清除計時器timerId
- 時間是按照毫秒計算的,1000毫秒就是一秒鐘
- 所以會在頁面打開一秒鐘以后執行函數
- 只執行一次,之后就不執行了
- 返回值是當前這個定時器是頁面中第幾個定時器
8-4 間隔定時器
- 語法:
setInterval(需要執行的函數,每隔多長時間執行)
- 跟上面類似,只是會每隔一段時間執行這個函數
- 清除計時器用
clearInterval(返回值)
二、BOM
BOM
:瀏覽器對象模型- 就是一些操作瀏覽器的一些能力
- 我們可以操作的內容:
- 獲取一些瀏覽器的相關信息(窗口的大小)
- 操作瀏覽器進行頁面跳轉
- 獲取當前瀏覽器地址欄的信息
- 操作瀏覽器的滾動條
- 瀏覽器的信息(瀏覽器的版本)
- 讓瀏覽器出現一個彈出框(
alert/confirm/prompt
)
BOM
的核心就是window
對象window
是瀏覽器內置的一個對象,里面包含了操作瀏覽器的方法
1. 獲取瀏覽器窗口的尺寸
-
innerHeight
和innerWidth
-
這兩個方法分別是用來獲取瀏覽器窗口的高度和寬度(包含滾動條)
//獲取瀏覽器的高度 //window可以省略 var windowHeight = window.innerHeight console.log(windowHeight)//獲取瀏覽器的寬度 var windowWidth = window.innerWidth console.log(windowWidth)
2. 瀏覽器的彈出層
- alert:彈出一個警告框
- confirm:彈出一個確認框
- prompt:彈出一個提示框
3.瀏覽器的地址信息
- location.href:跳轉頁面
- location.reload():刷新頁面
4. 瀏覽器的常見事件
-
window.onload:頁面加載完成后觸發
-
window.onresize:頁面大小發生改變時觸發
-
window.onscroll:頁面滾動時觸發
-
window.document.documentElement.scrollTop和window.document.body.scrollTop:都是測量離頂部的距離(window可以省略)
-
window.scrollTo() :
- window.scrollTo(0 , 0) :表示回到(0,0)這個位置
- window.scrollTo({left:0 , top:0}) :也表示回到頂部
-
window.open(“網址”):在一個新的頁面打開,原來的頁面不變
-
window.close():只能是關閉自己的頁面
5. 瀏覽器的歷史記錄
window
中有一個對象叫做history
- 是專門用來存儲歷史記錄信息的
history.back
-
history.back
是用來回退歷史記錄的,就是回到前一個頁面window.history.back()
- 前提是你要有刪一條記錄,不然就是一直在這個頁面,也不會回退
history.forword
-
history.forword
是去到下一個歷史記錄里面,也就是去到下一個頁面window.history.forword()
- 前提是你要之前有過回退操作,不然的話你現在就是最后一個頁面,沒有下一個
6. 瀏覽器本地存儲
6-1 loclocalStorage:永久存儲
//增
localStorage.setItem("age" , "14")
//存數據, 兩個參數, 第一個是鍵, 第二個是值
//只能存儲字符串,如果要存儲對象,那么可以使用`JSON`字符串
//如果之前的鍵已經存在,那么會覆蓋原來的值,也就是修改//取
localStorage.getItem("age")//刪
localStorage.removeItem("age") //清空
localStorage.clear()
6-2 sessionStorage:臨時存儲
//增
sessionStorage.setItem("age" , "14")
//取
sessionStorage.getItem("age")
//刪
sessionStorage.removeItem("age")
//清空
sessionStorage.clear()
sessionStorage:關閉頁面數據就會消失
三、DOM
DOM(Document Object Model)
:文檔對象模型- 其實就是操作
html
中標簽的一些能力 - 我們可以操作哪些內容
- 獲取一個元素
- 移除一個元素
- 創建一個元素
- 向頁面里面添加一個元素
- 給元素綁定一些事件
- 獲取元素的屬性
- 給元素添加一些
css
樣式 - …
DOM
的核心對象就是document
對象document
對象是瀏覽器內置的一個對象,里面存儲著專門用來操作元素的各種方法DOM
:頁面中的標簽,我們通過js
獲取以后,就把這個對象叫做DOM對象
1. 獲取一個元素
-
document.documentElement:rem,獲取的就是html
-
document.head:獲取head
-
document.body:獲取body
-
getElementById:根據id獲取元素
-
getElementsByClassName:根據class獲取元素
獲取到的是一個偽數組,可以使用Array.from()將這個偽數組轉為真正的數組
-
getElementsByTagName:根據標簽名獲取元素
他會將這個代碼里面的所有的這個標簽都獲取下來
-
getElementsByName:根據取得的元素的name屬性值獲取元素
-
querySelector:根據選擇器獲取元素
//都是根據之前寫style樣式的方式獲取 var items = document.querySelector(".newItem") var items = document.querySelector("#box") //注意:這個只能獲取第一次出現的對象 //下面那個就可以獲取所有的指定對象
-
querySelectorAll:根據選擇器獲取元素
2. 操作元素屬性
2-1 操作原生屬性
<body><div id = "box">hello</div><input type = "text" id = "password"><script>box.innerHTML = "world" //這個會將id為box的div里面的內容改為"world"password.type = "password" //這個會將id為password的文本框改為密碼框</script>
</body>
注意:這些都是通過
id
來修改里面的屬性
2-2 自定義屬性
<body><ul><li>111</li><li>222</li><li>333</li><li>444</li></ul><div id = "box" nb = "222"></div><script>//自定義屬性有兩種方式//第一種//setAttribute(設置屬性)、getAttribute(獲取屬性的值)、removeAttribute(刪除屬性)var itmes = document.getElementsByTagName("li")for (var i = 0 ; i < itmes.length ; i++) {itmes[i].setAttribute("index" , i)//這樣給每個li的標簽都添加了一個名為"index"的屬性,并且值為"i"}//第二種方法(比較推薦,主流,主要是為了方便區分自己定義的屬性和原生屬性)//他會以"data-*****"的方式出現,便于區分var oitmes = document.getElementsByTagName("li")for (var i = 0 ; i < oitmes.length ; i++) {oitmes[i].dataset.index = i //這樣給每個li的標簽都添加了一個名為"data-index"的屬性,并且值為"i"}//想要刪除這個屬性的話用下面的方法delete box.dataset.nb</script>
</body>
注意:一般都是用下面的方法,比較常用
3. 操作元素文本內容
innerHTML
:獲取元素內部的內容,包括標簽innerText
:獲取元素內部的內容,不包括標簽value
:獲取表單元素的值
4. 操作元素樣式
-
行內元素
//只能行內樣式方法,style --讀寫 box.style.width = 100px console.log(box.style["background-color"]) //不能直接"."要使用[] console.log(box.style.backgroundColor) //或者使用駝峰命名法
-
內部樣式,外部樣式
//內部樣式,外部樣式,行內getComputedStyle 獲取,不能賦值寫樣式 var obox = document.getElementById("box") var res = getComputedStyle(obox)["background-color"] var res = getComputedStyle(obox).backgroundColor
注意:只能獲取,不能修改樣式,但是上面那種方式可以修改樣式
5. 操作元素類名
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>.item{width: 100px;height: 100px;background-color: red;color: black;border-radius: 10px;}</style>
</head>
<body><div id = "box" class = "item item1 item2">hello world</div><button id = "btn">click</button><script>//.className 可以獲取到元素的所有樣式//.className 可以設置元素的樣式console.log(box.className)box.className = "item item1"//這樣會覆蓋前面的樣式box.className += " item2"//注意要有空格,否則會跟前面的樣式合并//classList 是一個類數組對象,里面存放著元素的所有樣式console.log(box.classList)box.classList.add("item3")//添加樣式box.classList.remove("item1")//移除樣式// box.classList.toggle("item")//切換樣式,如果有就移除,如果沒有就添加btn.onclick = function(){box.classList.toggle("item")}</script>
</body>
</html>
6. DOM節點
DOM
的節點一般分為常用的三大類元素節點、文本節點、屬性節點- 什么是分類,比如我們在獲取元素的時候,通過各種方法獲取到的我們叫做元素節點(標簽節點)
- 比如我們標簽里面寫的文字,那么就是文本節點
- 寫在每一個標簽上的屬性,就是屬性節點
6-1 元素節點
- 我們通過
getElement...
獲取到的都是元素節點
6-2 屬性節點
- 我們通過
getAttribute
獲取到的就是屬性節點
6-3 文本節點
- 我們通過
innerText
獲取到的就是元素的文本節點
6-4 獲取節點的方式
-
childNodes
和children
childNodes屬性返回指定節點的子節點集合
children屬性返回指定節點的子元素集合
-
firstChild
和firstElementChild
firstChild屬性返回指定節點的第一個子節點
firstElementChild屬性返回指定節點的第一個子元素 -
lastChild
和lastElementChild
lastChild屬性返回指定節點的最后一個子節點
lastElementChild屬性返回指定節點的最后一個子元素 -
previousSibling
和previousElementSibling
previousSibling屬性返回指定節點的前一個兄弟節點
previousElementSibling屬性返回指定節點的前一個兄弟元素 -
nextSibling
和nextElementSibling
nextSibling屬性返回指定節點的后一個兄弟節點
nextElementSibling屬性返回指定節點的后一個兄弟元素 -
parentNode
和parentElement
parentNode屬性返回指定節點的父節點
parentElement屬性返回指定節點的父元素
<body><div id="box">kerWin<p>111</p><!-- 我是注釋 --></div><script>// 1.\n// kerWin// \n// 2.<p>111</p>// 3.\n// 4.<!-- 我是注釋 -->// 5.\n//childNodes屬性 vs children屬性//childNodes屬性返回指定節點的子節點集合//children屬性返回指定節點的子元素集合console.log(box.childNodes)//返回所有節點console.log(box.children)//返回所有元素//firstChild vs firstElementChild//firstChild屬性返回指定節點的第一個子節點//firstElementChild屬性返回指定節點的第一個子元素console.log(box.firstChild)//返回第一個節點console.log(box.firstElementChild)//返回第一個元素//lastChild vs lastElementChild//lastChild屬性返回指定節點的最后一個子節點//lastElementChild屬性返回指定節點的最后一個子元素console.log(box.lastChild)//返回最后一個節點console.log(box.lastElementChild)//返回最后一個元素//previousSibling vs previousElementSibling//previousSibling屬性返回指定節點的前一個兄弟節點//previousElementSibling屬性返回指定節點的前一個兄弟元素console.log(box.previousSibling)//返回前一個兄弟節點console.log(box.previousElementSibling)//返回前一個兄弟元素//nextSibling vs nextElementSibling//nextSibling屬性返回指定節點的后一個兄弟節點//nextElementSibling屬性返回指定節點的后一個兄弟元素console.log(box.nextSibling)//返回后一個兄弟元素console.log(box.nextElementSibling)//返回后一個兄弟元素//parentNode vs parentElement//parentNode屬性返回指定節點的父節點//parentElement屬性返回指定節點的父元素console.log(box.parentNode)//返回父節點console.log(box.parentElement)//返回父元素</script></script>
</body>
</html>
6-5 節點操作
-
創建節點
//createElement("節點"):創建節點 var odiv = document.createElement("div") //可以對節點進行任意操作 odiv.className = "aaa" odiv.id = "aaa"
-
插入節點
//appendChild()方法將一個節點添加到指定父節點的子節點列表的末尾 box.appendChild(odiv) //box.insertBefore(要插入的節點,誰的前面) //表示在box里面的"誰的前面"插入一個節點 box.insertBefore(odiv , box1)
-
刪除節點
//刪除節點 box.removeChild(box1) //刪除自己以及自己的后代 box.remove()
-
替換節點
//replaceChild()方法用一個新節點替換指定父節點的一個子節點 //replaceChild(新節點,指定節點) box.replaceChild(obox,box1)
-
復制節點
//cloneNode()方法復制一個節點 //cloneNode(true)復制節點及其所有子節點 var obox2 = obox.cloneNode(true) box.appendChild(obox2)
6-6 節點屬性
nodeType | nodeName | nodeValue | |
---|---|---|---|
元素節點 | 1 | 大寫標簽名 | null |
屬性節點 | 2 | 屬性名 | 屬性值 |
文本節點 | 3 | #text | 文本內容 |
6-7 獲取元素尺寸
- offsetWith和offsetHeight
offsetWith
:獲取的元素內容 + padding + border的寬度offsetHeight
:獲取的元素內容 + padding + border的高度
- clientWidth和clienHeight
clienWidth
:獲取的是元素內容 + padding的寬度clientHeight
:獲取的是元素內容 + padding的高度
注意:
- 獲取到的尺寸是沒有單位的數字
- 當元素在頁面中不占未知的時候,獲取到的是
0
6-8 獲取元素偏移量
-
offsetLeft和offsetTop
offsetLeft
:獲取的是元素距離左側的距離offsetTop
:獲取的是元素距離頂部的距離
注意:
參考點: 是定位父級
如果父級元素都沒有定位,偏移量相對于body
-
clientLeft和clientTop
clientLeft
:距離左邊框的距離clienTop
:距離上邊框的距離
6-9 獲取可視窗口的尺寸
-
innerWidth和innerHeight
-
document.documentElement.clientWidth和document.documentElement.clientHeight
注意:
第一個:訪問的尺寸含有滾動條的寬度
第二個:訪問的尺寸不包含滾動條的寬度
7. 事件
-
一個事件由什么東西組成
- 觸發誰的事件:事件源
- 觸發什么事件:事件類型
- 觸發以后做什么:事件處理函數
var odiv = document.querySelector("div")odiv.onclick = function() {console.log("你點擊了div") } //誰來觸發事件 => odiv => 這個事件的事件源就是odiv //觸發什么事件 => onclick => 這個事件類型就是click //觸發之后做什么 => function(){} => 這個事件的處理函數 //每次點擊div的時候都會調用里面的函數
7-1 初識事件
-
dom0 類型 --后面會覆蓋前面的
box.onclick = function() {alert("1111") }
-
dom2 類型 – 綁定多個事件處理函數,按照順序執行
box2.addEventListener("click",function() {alert("1111") })box2.addEventListener("click",function() {alert("2222") })
7-2 事件解綁
-
dom0 類型 --dom節點.onclick = null
box.onclick = null
-
dom2 類型 --dom節點.removeEventListener(“click”,function() {})
function handler() {console.log("1111")//解綁事件this.removeEventListener("click", handler) } //事件觸發 btn.addEventListener("click" , handler)
7-3 事件類型
- 鼠標事件
click
:單擊執行dblclick
:雙擊執行contextmenu
:右鍵菜單事件mousedown
:鼠標按下事件mouseup
:鼠標抬起事件mousemove
:鼠標移動事件mouseenter
:鼠標移入事件(在孩子節點里面移入移出不會觸發)mouseleave
:鼠標移出事件(在孩子節點里面移入移出不會觸發)mouseover
:鼠標移入事件(在孩子節點里面移入移出會觸發)mouseout
:鼠標移出事件(在孩子節點里面移入移出會觸發)
- 鍵盤事件
keydown
:鍵盤按下事件keyup
:鍵盤抬起事件keypress
:鍵盤按下事件
- input事件
focus
:獲取焦點事件blur
:失去焦點事件change
:改變事件,當獲取焦點和失去焦點的時候里面的內容不一樣才會觸發input
:輸入事件,輸入內容不一樣就觸發select
:選擇事件submit
:提交事件reset
:重置事件
- 觸摸事件(只對移動端有效)
touchstart
:觸摸開始事件touchend
:觸摸結束事件touchmove
:觸摸移動事件touchcancel
:觸摸取消事件
7-4 事件對象
-
瀏覽器給了我們一個黑盒子,叫做
window.event
,就是對事件信息的所有描述-
比如點擊事件
-
你點在了
(0,0)
位置,那么你得到的這個事件對象里面對應的就會有這個點位的屬性 -
你點在了
(10,10)
位置,那么你得到的這個事件對象里面對應的就會有這個點位的屬性odiv.onclick = function() {console.log(window.event.x軸坐標信息)console.log(window.event.y軸坐標信息) }
-
-
鼠標事件
-
clientX,clientY:距離瀏覽器可視窗口的左上角的坐標值
-
pageX,pageY:距離頁面文檔流的左上角的坐標值
-
offsetX,offsetY:距離出發元素的左上角的坐標值
注意:如果當前元素里面還有子元素,那么點擊這個子元素也會有值,只是這個值是距離自己子元素左上的值
-
-
stopPropagation:阻止事件傳播
fanction fn(evt) {evt.stopPropagation }
-
阻止默認行為
document.oncontextmenu = function() {console.log("右鍵單擊")return false }
7-5 事件委托
- 就是把我要做的事情委托給別人來做
- 因為我們的冒泡機制,點擊子元素的時候,也會同步觸發父元素的相同事件
- 所以我們就可以把子元素的事件委托給父元素來做
事件觸發
-
點擊子元素的時候,不管子元素有沒有點擊事件,只要父元素有點擊事件,那么就可以觸發父元素的點擊事件
<body><ul><li>1</li><li>2</li><li>3</li></ul><script>var oul = document.querySelector("ul")oul.addEventListener("click" , function(e) {console.log("我是ul的點擊事件,我被觸發了")})</script> </body>
- 像上面的代碼,當你點擊ul的時候肯定會被觸發
- 但是當你點擊li的時候,也會觸發
target
-
target
這個屬性是事件對象里面的屬性,表示你點擊的目標 -
當你觸發點擊事件的時候,你點擊在哪個元素上,
target
就是哪個元素 -
這個
target
也不兼容,在IE
下要使用srcElement
<body><ul><li>1</li><li>2</li><li>3</li></ul><script>var oul = document.querySelector("ul")oul.addEventListener("click" , function(e) {e = e || window.eventvar target = e.target || e.srcElementconsole.log(target)})</script> </body>
- 上面的代碼,當你點擊
ul
的時候,target
就是ul
- 當你點擊在
li
上面的時候,target
就是li
- 上面的代碼,當你點擊
8. 正則表達式
-
字面量 //
var reg1 = /abc/;
-
**構造函數 **
var reg2 = new RegExp('abc');
例子:
<script>// 正則表達式//js復雜類型// 1. 字面量 //var reg1 = /abc/;console.log(reg1);// 2. 構造函數 var reg2 = new RegExp('abc');console.log(reg2);//失去焦點時觸發onblurmytext.onblur = function() {console.log(mytext.value);//test : 測試是否匹配console.log(reg1.test(mytext.value));} </script>
8-1 元字符
-
\d
: 匹配一個數字字符。等價于 [0-9]。\d\d
:表示就要包含兩個數字字符里面的內容可以是字符串數字,也可以是數字
-
\D
:匹配一個非數字字符。等價于 ![0-9]。 -
\s
:匹配一個空白字符,包括空格、縮進 、制表符、換頁符和換行符。 -
\S
:匹配一個非空白字符。等價于 ![\s]。 -
\w
:匹配包括下劃線的任何單詞字符。等價于’[A-Z、a-z、0-9、_ ]'。 -
\W
:匹配任何非單詞字符。等價于 ‘![A-Za-z0-9_]’。 -
.
: 匹配任意內容(換行符不算)注意:要全是換行符才不算,如:
\n\n\n
,返回false如果是
ab\ncd
,返回的還是true -
\
:轉義字符像上面那個如果寫成
\.
就表示一個普通的.
,而不是元字符
<body><script>// 1. \d :匹配一個數字字符。等價于 [0-9]。var reg = /\d/console.log(reg.test('1')) // trueconsole.log(reg.test('a')) // falseconsole.log(reg.test('1a')) // trueconsole.log(reg.test('a1')) // true// 2. \D :匹配一個非數字字符。等價于 [^0-9]。var reg = /\D/console.log(reg.test('1')) // falseconsole.log(reg.test('a')) // true// 3. \s :匹配一個空白字符,包括空格、制表符、換頁符和換行符。var reg = /\s/console.log(reg.test(' ')) // trueconsole.log(reg.test('\t')) // true// 4. \S :匹配一個非空白字符。等價于 [^\s]。var reg = /\S/console.log(reg.test(' ')) // falseconsole.log(reg.test('a')) // true// 5. \w :匹配包括下劃線的任何單詞字符。等價于'[A-Za-z0-9_]'。var reg = /\w/console.log(reg.test('a')) // trueconsole.log(reg.test('1')) // true// 6. \W :匹配任何非單詞字符。等價于 '[^A-Za-z0-9_]'。var reg = /\W/console.log(reg.test('a')) // falseconsole.log(reg.test('1')) // false// 7. . :匹配任意內容(換行符不算)var reg = /zo*/console.log(reg.test('z')) // trueconsole.log(reg.test('zo')) // true// 8. \ :轉義字符var reg = /\./console.log(reg.test('.')) // trueconsole.log(reg.test('a')) // false</script>
</body>
8-2 邊界符
^
:匹配輸入字符串的開始位置。$
:匹配輸入字符串的結束位置。
<body><script>// 1. ^ :匹配輸入字符串的開始位置。var reg = /^\d/console.log(reg.test('aab')) // falseconsole.log(reg.test('1b')) // true// 2. $ :匹配輸入字符串的結束位置。var reg = /\d$/console.log(reg.test('aab')) // falseconsole.log(reg.test('a1')) // true// 3. ^開頭結尾$var reg = /^\d$/console.log(reg.test('aab')) // falseconsole.log(reg.test('1')) // true</script>
</body>
8-3 限定符
-
*
:匹配前面的子表達式零次或多次。 -
+
:匹配前面的子表達式一次或多次。 -
?
:匹配前面的子表達式零次或一次。 -
{n}
:n 是一個非負整數。匹配確定的 n 次。 -
{n,}
:n 是一個非負整數。至少匹配n 次。 -
{n,m}
:最少匹配 n 次且最多匹配 m 次。注意:他只能修飾他前面的一個字符,對于再前面的,表示固定的
<body><script>// 1. * :匹配前面的子表達式零次或多次。var reg = /zo*/console.log(reg.test('z')) // trueconsole.log(reg.test('zo')) // true// 2. + :匹配前面的子表達式一次或多次。var reg = /zo+/console.log(reg.test('z')) // falseconsole.log(reg.test('zo')) // trueconsole.log(reg.test('o')) // false// 3. ? :匹配前面的子表達式零次或一次。var reg = /zo?/console.log(reg.test('z')) // trueconsole.log(reg.test("zozo")) // trueconsole.log(reg.test("zo")) // trueconsole.log(reg.test("o")) // false// 4. {n} :n 是一個非負整數。匹配確定的 n 次。var reg = /zo{2}/console.log(reg.test('z')) // falseconsole.log(reg.test("zo")) // falseconsole.log(reg.test("zoo")) // trueconsole.log(reg.test("zooo")) // true// 5. {n,} :n 是一個非負整數。至少匹配n 次。var reg = /zo{2,}/console.log(reg.test('z')) // falseconsole.log(reg.test("zo")) // falseconsole.log(reg.test("zoo")) // true// 6. {n,m} :最少匹配 n 次且最多匹配 m 次。var reg = /zo{2,3}/console.log(reg.test('z')) // falseconsole.log(reg.test("zo")) // false</script>
</body>
8-4 特殊符號
-
()
:整體 -
|
:或注意:他表示是他左右兩邊的整體字符,不是一個
var reg = /abc | ddd/
表示含有abc或者ddd字符串
-
[]
:字符集。匹配包含的任一字符。[0-9]:表示匹配數字0、1、2、3、4、5、6、7、8、9中的任意一個字符
-
[^]
:排除字符集。匹配未包含的任何字符。
<body><script>// 1. () :匹配括號內的表達式,也表示一個組。var reg = /(abc){2}/console.log(reg.test('abc')) // falseconsole.log(reg.test('abcabc')) // true// 2. | :表示或。var reg = /abc|cba/console.log(reg.test('abc')) // trueconsole.log(reg.test('cba')) // trueconsole.log(reg.test('ab')) // false// 3. [] :字符集。匹配包含的任一字符。var reg = /[abc]/console.log(reg.test('a')) // trueconsole.log(reg.test('b')) // trueconsole.log(reg.test('d')) // false// 4. [^] :排除字符集。匹配未包含的任何字符。var reg = /[^abc]/console.log(reg.test('a')) // falseconsole.log(reg.test('b')) // falseconsole.log(reg.test('d')) // true</script>
</body>
8-5 捕獲exec
語法:reg.exec(“字符串”)
標識符:(他是寫在正則表達式的外面的,如:/\d/g
)
g
:表示全局匹配。i
:表示不區分大小寫。m
:表示多行匹配。u
:表示使用unicode碼的模式進行匹配。y
:表示粘性匹配。
8-6 正則與字符串方法
-
字符串.replace()
: 替換與正則表達式匹配的子串。var str = 'asdfadafdsaf' //正則表達式后面加了一個"g",表示所有的,全局的 var newstr = str.replace(/a/g , "*") console.log(newstr) //*sdf*d*fds*f
-
字符串.search()
: 檢索與正則表達式相匹配的值。不管是不是全局都只能檢索到第一個出現的字符
var str = 'asdfadafdsaf' var newstr = str.search(/a/g) //如果是表達式里面沒出現的就是-1 console.log(newstr) //0 console.log(str.search(/ax/)) //-1
-
字符串.match()
: 找到一個或多個正則表達式的匹配。var datestr = "time is from 2029-01-01 to 2029-12-31" console.log(datestr.match(/\d{4}-\d{1,2}-\d{1,2}/g)) //["2029-01-01", "2029-12-31"]
9. this指向
改變this指向:
-
call
:執行函數,并改變this指向為函數的第一個參數注意:支持多個參數
-
apply
:執行函數,并改變this指向為函數的第一個參數注意:只支持兩個參數,第二個參數是一個數組
-
bind
:改變this指向為函數的第一個參數,不會自動執行函數注意:支持多個參數,還要手動執行
<body><button id="btn">click</button><script>// call apply bindvar name = "111"var obj1 = {name : "obj1",getName :function(a , b ,c) {console.log("getName1" , this.name)console.log("參數" , a, b, c)}}var obj2 = {name : "obj2",getName :function(a , b ,c) {console.log("getName2" , this.name)console.log("參數" , a, b, c)}}// call 方法// 語法:函數.call(誰調用我,參數1,參數2,參數3,...)// 作用:改變函數的this指向// 返回值:函數的返回值obj1.getName.call(obj2, 1, 2, 3)// apply 方法// 語法:函數.apply(誰調用我,[參數1,參數2,參數3,...])// 作用:改變函數的this指向// 返回值:函數的返回值obj1.getName.apply(obj2, [1, 2, 3])// bind 方法// 語法:函數.bind(誰調用我,參數1,參數2,參數3,...)// 作用:改變函數的this指向// 返回值:函數var fun1 = obj1.getName.bind(obj2, 1, 2, 3)console.log(fun1)//函數fun1()//手動執行btn.onclick = handler.bind(window)function handler() {console.log(1111 , this)}</script>
</body>
四、ES6
1. ES6定義變量
let和const關鍵字
let
和const
與var
的區別:let
和const
不允許重復聲明變量let
和const
必須先聲明定義才可以使用let
和const
的塊級作用域只要是{}
里面的都是,而var
只有函數里面才是
let
和const
的區別:let
可以只聲明不賦值,而const
必須要賦值,const
是定義一個常量,是不能更改的- 注意:
const
定義一個對象,然后改變對象里面的元素內容是可以的,因為堆棧問題,cosnt
只是存儲的一個地址,地址并沒有改變,對象里面的內容是存在堆里面
2. ES6的箭頭函數
語法:
var test = () => {}
可以省略
function
,變成=>
-
只有一個參數時,可以省略
()
-
函數體只有一句話或者只有返回值的時候,可以省略
{}
-
函數體只有一句
return
時,可以省略return
-
注意如果返回的是一個對象類型的時候,省略了
return
和{}
,要在對象的{}
的外面加上一個()
,防止把對象的{}
當成了函數的 -
沒有
arguments
arguments:是函數里面的一個偽數組,當你定義函數而沒有設置形參的時候,而你調用函數時,傳入了參數,想要獲取這個參數就可以用
arguments[0]、arguments[1]....
獲取 -
箭頭函數沒有
this
,或者說箭頭函數的this
是父級作用域的
3. ES6的解構賦值
-
快速的從對象和數組中獲取里面的成員
var arr = ['a' , 'b' , 'c'] //注意只能是按照順序取出 let [x , y , z] = arr console.log(x , y , z) // a b c//快速換值 var a = 10 var b = 20 var [a , b] = [b , a]//這樣a=20,b=10var obj = {name : 'zhangsan',age : 20 ,location : 'jiangxi' } //這里要一一對應,不然拿不出來,前面的key要一樣 //這里最后的location:mylocation就是重命名,將location的名字改為mylocation,那之前的location就不能調用了 let {name , age , location:mylocation} = obj console.log(name , age , mylocation) //這里就不能用location了,因為沒有被定義//復雜對象類型 var obj = {name: '張三',age: 18,location: {city: '北京',province: '北京' },hobbies: ['唱', '跳', 'rap']}var {name, age, location: {city, province}, hobbies: [hobby1, hobby2, hobby3]} = obj console.log(name, age, city, province, hobby1, hobby2, hobby3);//張三 18 北京 北京 唱 跳 rap
4. ES6的展開運算符
-
...
:展開運算符(不管是數組還是對象都可以展開)在對象里面,如果key和value一樣可以省略value,比如:{name:name};這樣可以簡寫成{name}
var a = [1 , 2 , 3] var b = [4 , 5 , 6] var c = [...a , ...b] console.log(c)//[1, 2, 3, 4, 5, 6]var obj1 = {name : '張三' ,age : 18 ,sex : '男' }//只是展開obj1里面的內容存到obj2中,如果有的內容一樣那么就會被覆蓋 var obj2 = {...obj1 , name : '李四' ,hobby : '唱歌' }console.log(obj2);//{name: "李四", age: 18, sex: "男", hobby: "唱歌"}
5. ES6模塊化語法
-
export導出
// 方式1:聲明時導出 export const name = 'Alex'; export function sum(a, b) { return a + b; }// 方式2:統一導出 const PI = 3.14; const multiply = (x, y) => x * y; export { PI, multiply };// 方式3:重命名導出(用as重命名可以避免不同js里面的函數或者變量名相同的情況) export { PI as π, multiply as mul };// 一個模塊只能有一個默認導出 export default class Calculator {// ... }// 或 const utils = { /* ... */ }; export default utils;
-
import導入
//1. 導入命名導出 import { sum, PI } from './math.js'; import { sum as add, PI as π } from './math.js'; // 重命名 import * as math from './math.js'; // 整體導入//2.導入默認導出 import Calculator from './calculator.js'; import calc from './calculator.js'; // 任意命名
注意:
文件擴展名:瀏覽器中需明確寫
.js
擴展名路徑規范:
- 相對路徑:
./
或../
- 絕對路徑:以
/
開頭- 第三方模塊:直接寫包名(需配置)
嚴格模式:模塊自動啟用嚴格模式
瀏覽器使用:需添加
type="module"
<script type="module" src="app.js"></script>
跨域限制:需配置CORS或使用本地服務器
五、面向對象
1. 對象基礎
1-1 創建對象
// 字面量創建
const obj = { name: 'John',sayHi() {console.log(`Hi, ${this.name}`);}
};// new Object() 創建
const obj2 = new Object();
obj2.age = 30;
1-2 屬性訪問
// 點語法
console.log(obj.name);// 方括號語法
console.log(obj['name']);
2. 構造函數
2-1 基本用法
function Person(name, age) {this.name = name;this.age = age;this.introduce = function() {console.log(`I'm ${this.name}, ${age} years old`);};
}const p1 = new Person('Alice', 25);
2-2 new關鍵字的作用
- 創建新空對象
- 綁定this到新對象
- 自動返回新對象
2-3 注意事項
- 首字母要大寫
- 構造函數不寫
return
- 構造函數不能當成普通函數使用
3. 原型(Prototype)
3-1 原型鏈機制
function Animal(name) {this.name = name;
}
//用prototype這個可以節省空間
Animal.prototype.eat = function() {console.log(`${this.name} is eating`);
};const cat = new Animal('Mimi');
cat.eat(); // 通過原型鏈查找方法//對象.__proto__ === 構造函數.prototype
3-2 原型相關方法
// 檢查原型
console.log(Object.getPrototypeOf(cat) === Animal.prototype);// 設置原型
const dog = { name: 'Buddy' };
Object.setPrototypeOf(dog, Animal.prototype);
4. ES6 Class
4-1 類定義
class Rectangle {//構造器函數constructor(height, width) {this.height = height;this.width = width;}// 方法get area() {return this.calcArea();}calcArea() {return this.height * this.width;}// 靜態方法static info() {console.log('This is a Rectangle class');}
}
4-2 繼承
class Square extends Rectangle {constructor(side) {super(side, side);}
}
5. 繼承
5-1 構造函數繼承
function student(name , age , classroom) {//這里就是屬性繼承,方法沒法繼承Person.call(this , name , age)this.classroom = classroom
}
5-2 原型鏈繼承
function Parent() {this.name = 'Parent';
}Parent.prototype.sayName = function() {console.log(this.name);
};function Child() {}
Child.prototype = new Parent();const child = new Child();
5-3 組合繼承(經典繼承)
function Parent(name) {this.name = name;
}function Child(name, age) {Parent.call(this, name); // 繼承屬性this.age = age;
}
//方法繼承
//Child.prototype = Object.create(Parent.prototype);
//Child.prototype.constructor = Child;
Child.prototype = new Parent()
5-4 ES6類繼承
class Vehicle {constructor(wheels) {this.wheels = wheels;}say() {console.log('aa')}
}//extends繼承
class Car extends Vehicle {constructor(wheels, brand) {//super繼承父類里面的元素super(wheels);this.brand = brand;}//覆蓋say() {//super.say()//調用父類方法console.log('bb')}
}
六、ajax
-
核心作用:在不重新加載整個頁面的情況下,與服務器交換數據并更新部分網頁內容
-
主要特點:
- 異步通信
- 基于現有的 Web 標準(HTML, CSS, JavaScript, XML/JSON)
- 提升用戶體驗
-
傳統
Web
vsAJAX
應用傳統 Web 應用 AJAX 應用 同步請求(阻塞) 異步請求(非阻塞) 整頁刷新 局部更新 頻繁的服務器請求 按需獲取數據
1. 基本用法
1-1 創建 XMLHttpRequest
對象
let xhr = new XMLHttpRequest(); // 現代瀏覽器
// 兼容舊版 IE(<= IE6):
// let xhr = new ActiveXObject("Microsoft.XMLHTTP");
1-2 配置請求
xhr.open(method, url, async);
// method: "GET", "POST" 等
// url: 請求地址
// async: 是否異步(默認 true:異步,false:同步)
注意:如果是
true
,表示異步可以后面的代碼執行了在調用onreadystatechange
函數,但是如果是false
,如果后面的代碼已經執行了,那么onreadystatechange
函數就不會執行了,除非將這個函數放在xhr.send()
的前面才會調用這個函數再執行后面的代碼異步效率更高,一般都是異步,用
true
1-3 發送請求
/*get:偏向獲取數據post:偏向提交數據put:偏向更新數據(全部)delete:偏向刪除信息patch:偏向部分修改主要還是前面兩個
*/
xhr.send(); // GET 請求
xhr.send(data); // POST 請求(可發送表單數據等)
1-4 處理響應
//注冊事件,接受服務器返回的數據
xhr.onreadystatechange = function() {//readyState 0-4:請求未發送 1:請求已發送 2:請求已接收 3:請求處理中4:請求已完成//status 200-300//status 404:請求的資源不存在 500:服務器內部錯誤if (xhr.readyState === 4 && xhr.status === 200) {// 處理響應數據console.log(xhr.responseText); // 文本格式console.log(xhr.responseXML); // XML 格式}
};
//這個不用判斷readyState是否為4,因為他已經要是4才能執行這個函數
xhr.onload = function(){if(xhr.status == 200) {console.log(xhr.responseText)} else if (xhr.status == 404) {console.error('請求的資源不存在')} else if (xhr.status == 500) {console.error('服務器內部錯誤')}}
常見的HTTP狀態碼
- 200: 成功
- 404: 未找到頁面
- 500: 服務器內部錯誤
2. 封裝ajax
//將一個對象函數轉化為查詢字符串如:a = 1 & b = 2 & c = 3這種形式
function queryStringify(obj) {let str = ''for (let k in obj) str += `${k}=${obj[k]}&`return str.slice(0, -1)
}//封裝ajax
function ajax(options) {let defaultoptions = {url : '',method : 'get' ,async : true,data : {} ,headers : {'Content-Type' : 'application/json'} ,success : function () {},error : function () {}}//將傳入的參數和默認參數合并let {url , method, async, data, headers, success, error} = {...defaultoptions,...options}//判斷請求方式和數據類型來修改data//headers['Content-Type']?.indexOf('json') > -1:判斷headers中是否有Content-Type并且值為json,這里面的問號表示可選鏈操作符,意思是如果headers中沒有Content-Type,那么就不會執行后面的indexOf方法,不會報錯if(typeof data === 'object' && headers['Content-Type']?.indexOf('json') > -1 && method === 'post') {data = JSON.stringify(data)} else {data = queryStringify(data)}//如果是get請求,那么就將數據拼接在url后面if(/^get$/i.test(method) && data) url += `?${data}` //發送請求const xhr = new XMLHttpRequest()xhr.open(method, url, async)xhr.onload = function() {if(!/^2\d{2}$/.test(xhr.status)) {error(`錯誤狀態碼:${xhr.status}`) //如果狀態碼不是2開頭的,就執行error函數return}//執行解析try {let res = JSON.parse(xhr.responseText)success(res)} catch (err) {error("解析失敗!因為后端返回的結果不是json格式字符串")}}//設置請求頭內的信息for (let k in headers) xhr.setRequestHeader(k, headers[k])//發送請求if(/^get$/i.test(method)) {xhr.send()} else {xhr.send(data)}
}//promise封裝ajax
function pajax(options) {return new Promise((resolve , reject) => {ajax({...options,success(res) {resolve(res)} ,error(err) {reject(err) }})})
}// export {ajax , pajax}
// export default ajax
七、Promise
-
promise
是一個ES6的語法,用來解決回調地獄的問題回調地獄:就是指回調函數里面嵌套了回調函數,一直嵌套下去,有很多層
1. Promise基本語法
// 回調地獄示例
doSomething(function(result) {doSomethingElse(result, function(newResult) {doThirdThing(newResult, function(finalResult) {console.log('Final result: ' + finalResult);}, failureCallback);}, failureCallback);
}, failureCallback);// Promise 是一個構造函數,自己身上有all、reject、resolve 這幾個眼熟的方法,原型上有then、catch等同樣很眼熟的方法。
// 既然是構造函數,那就可以用new關鍵字生成實例,
// 而該構造函數接受一個參數,是函數,并且有兩個參數,分別是resolve和reject。
// 分別表示異步操作執行成功后的回調函數和異步操作執行失敗后的回調函數。
// 實例生成后,可以用then方法分別指定res和rej回調函數。
let q = new Promise(function(resolve , reject){// 異步任務setTimeout(() => {// 異步任務成功resolve('成功的數據');// 異步任務失敗// reject('失敗的數據');}, 1000);
})//q是promise的對象
q.then((res) => {//兌現承諾,執行這個函數console.log(res);
}).catch((err) => {//拒絕承諾,執行這個函數console.log(err);
})
2. Promise的生命周期
- 一個 Promise 有以下三種狀態:
狀態 | 描述 |
---|---|
pending | 初始狀態,既不是成功也不是失敗 |
fulfilled | 操作成功完成 |
rejected | 操作失敗 |
- 狀態轉換:
pending -> fulfilled
pending -> rejected
3. 鏈式調用
Promise 鏈的特點:
- 每個 then() 返回新 Promise
- 返回值會自動包裝成 Promise
- 可以傳遞值到下一個 then()
let q = new Promise(function(resolve , reject) {...
})q.then(res => {return pajax({})
}).then(res => {return pajax({})
}).catch(err => {console.log(...)
})
4.Promise靜態方法
方法 | 描述 |
---|---|
Promise.all(iterable) | 所有成功時返回結果數組,任何一個失敗立即拒絕 |
Promise.allSettled(iterable) | 所有 Promise 完成后返回結果數組(ES2020) |
Promise.race(iterable) | 采用第一個完成(成功/失敗)的 Promise 結果 |
Promise.any(iterable) | 采用第一個成功的 Promise 結果(ES2021) |
Promise.resolve(value) | 返回已解決的 Promise |
Promise.reject(reason) | 返回已拒絕的 Promise |
示例:Promise.all
const promises = [fetch('/api/data1'),fetch('/api/data2'),fetch('/api/data3')
];Promise.all(promises).then(results => {// results 是按順序的結果數組}).catch(error => {// 任一請求失敗立即進入此處});
5.Promise 與 async/await
-
async/await
是一個es7的語法 -
語法:
async function fn() {const res = await promise對象return res }
-
這個可以把異步代碼寫的看起來像同步代碼
-
只要是一個promise對象,那么我們就可以用
async/await
來寫 -
只能影響
async
里面的代碼,函數外面的無法影響 -
如果需要在內部捕獲錯誤可以用
try/catch
例子:
// Promise 鏈式調用
function getData() {return fetchData().then(data => processData(data)).then(result => saveResult(result)).catch(handleError);
}// async/await 版本
async function getData() {try {const data = await fetchData();const processed = await processData(data);return await saveResult(processed);} catch (error) {handleError(error);}
}
6. Fetch
- Fetch API 提供了現代網絡請求解決方案,替代傳統的 XMLHttpRequest。
6-1 基本使用方法
-
GET
請求:默認是get請求fetch('https://api.example.com/data').then(response => response.json()).then(data => console.log(data)).catch(error => console.error('Error:', error));
-
POST
請求fetch('https://api.example.com/data', {method: 'POST',headers: {'Content-Type': 'application/json',},//注意這里要按照fetch的格式,是body傳入數據,而不是用data//而且傳入的數據格式要嚴格按照上面寫的格式傳入body: JSON.stringify({name: 'John',age: 30}) });
6-2 響應對象屬性
fetch(url).then(response => {console.log(response.status); // HTTP 狀態碼console.log(response.statusText); // 狀態文本console.log(response.headers); // 響應頭console.log(response.ok); // 狀態碼 200-299 時為 true
});
6-3 解析不同格式的響應
// JSON
response.json()// 文本
response.text()// Blob(二進制數據)
response.blob()// FormData
response.formData()// ArrayBuffer
response.arrayBuffer()
6-4 網絡錯誤處理
fetch(url).then(res => {if (res.ok) {//這里拿不到本來的數據,要先返回json數據,然后到下一個then才能拿到數據,返回的是狀態碼return res.json();} else {//拒絕請求return Promise.reject({status : res.status ,statusText : res.statusText})}}).then(res => {//這里才可以拿到數據console.log(res)}).catch(error => {console.error('Fetch error:', error);});
7. jsonp
-
Jsonp
是json
的一種"使用模式",可以讓網頁從別的域名(網站)獲取資料,即跨域讀取數據。 -
因為同源策略,才需要這個特殊的技術
const script = document.createElement('script') script.src = './kerwin.txt'//這里是要傳的地址 document.body.appendChild(script)
-
jsonp
原理:動態創建script標簽,src屬性指向沒有跨域限制,指向一個接口,接口返回的格式一定是***()函數表達式,函數的參數就是接口返回的數據 -
注意:
-
后端接口形式必須***(),需要后端配合
-
jsonp缺點:
-
獲取了數據之后刪除
//因為它獲取數據是每次都插入了一個script標簽,然后獲取數據,獲取完數據之后就可以將這個標簽刪除了,直接用onload刪除 script.onload = function () {script.remove() }
-
只能
get
請求,不能post
、put
、delete
-
-