理解ES
- 全稱: ECMAScript
- js語言的規範
- 我們用的js是它的實現
- js的組成
- ECMAScript(js基礎)
- 擴充套件-->瀏覽器端
- BOM
- DOM
- 擴充套件-->伺服器端
- Node.js
ES5
- 嚴格模式
- 執行模式: 正常(混雜)模式與嚴格模式
- 使用:
-
在全域性或函式的第一條語句定義為: 'use strict'; 複製程式碼
-
如果瀏覽器不支援, 只解析為一條簡單的語句, 沒有任何副作用 複製程式碼
- 作用:
- 使得Javascript在更嚴格的條件下執行
- 消除Javascript語法的一些不合理、不嚴謹之處,減少一些怪異行為
- 消除程式碼執行的一些不安全之處,保證程式碼執行的安全
- 需要記住的幾個變化
- 宣告定義變數必須用var
- 禁止自定義的函式中的this關鍵字指向全域性物件
- 建立eval作用域, 更安全(eval是一個函式 解析出js程式碼進行執行,他內部的作用域是私有的 )
- 物件不能有重名的屬性
- JSON物件
- 作用: 用於在json物件/陣列與js物件/陣列相互轉換
- JSON.stringify(obj/arr) js物件(陣列)轉換為json物件(陣列)
- JSON.parse(json) json物件(陣列)轉換為js物件(陣列)
- Object擴充套件 ES5給Object擴充套件了好一些靜態方法, 常用的2個:
- Object.create(prototype[, descriptors]) : 建立一個新的物件
- 以指定物件為原型建立新的物件
- 指定新的屬性, 並對屬性進行描述
- value : 指定值
- writable : 標識當前屬性值是否是可修改的, 預設為true
- configurable: 標識當前屬性是否可以被刪除 預設為false
- enumerable: 標識當前屬性是否能用for in 列舉 預設為false
- get方法 : 用來得到當前屬性值的回撥函式
- set方法 : 用來監視當前屬性值變化的回撥函式 並且實參即為修改後的值
- Object.defineProperties(object, descriptors) : 為指定物件定義擴充套件多個屬性
物件本身的兩個方法 * get propertyName(){} 用來得到當前屬性值的回撥函式 * set propertyName(){} 用來監視當前屬性值變化的回撥函式
註釋:很重要,通過get獲得的新屬性不能直接修改 必須通過set
- Array擴充套件
- Array.prototype.indexOf(value) : 得到值在陣列中的第一個下標
- Array.prototype.lastIndexOf(value) : 得到值在陣列中的最後一個下標
- Array.prototype.forEach(function(item, index){}) : 遍歷陣列
- Array.prototype.map(function(item, index){}) : 遍歷陣列返回一個新的陣列
- Array.prototype.filter(function(item, index){}) : 遍歷過濾出一個子陣列
- Function擴充套件
強制繫結this的方法:call()和apply()區別?
傳入引數方式不一樣,call()一個一個傳 apply()要求放在一個陣列中傳
- Function.prototype.bind(obj)
- 將函式內的this繫結為obj, 並將函式返回
- Function.prototype.bind(obj)
- 面試題: 區別bind()與call()和apply()?
- fn.bind(obj) : 指定函式中的this, 並返回函式
- fn.call(obj) : 指定函式中的this,並呼叫函式
- Function.prototype.bind(obj) :
- 作用: 將函式內的this繫結為obj, 並將函式返回 傳參方式和call相同
- 面試題: 區別bind()與call()和apply()?
- 都能指定函式中的this
- call()/apply()是繫結完之後 傳參 立即呼叫函式
- bind()是將函式返回 不能立即執行
- Date擴充套件
- Date.now() : 得到當前時間值
ES6
- 2個新的關鍵字
-
let/const
-
塊作用域
-
不會預處理(預解析),沒有變數提升
-
不能重複定義
-
值不可變 應用:
- 迴圈遍歷加監聽
- 使用let取代var是趨勢
const
- 作用:
- 定義一個常量
- 特點:
- 不能修改
- 其它特點同let
- 應用:
- 儲存不用改變的資料
- 變數的解構賦值
-
將包含多個資料的物件(陣列)一次賦值給多個變數
-
資料來源: 物件/陣列
-
目標: {a, b}/[a, b]
- 理解:
- 從物件或陣列中提取資料, 並賦值給變數(多個)
- 物件的解構賦值 let {n, a} = {n:'tom', a:12}
- 陣列的解構賦值 let [a,b] = [1, 'atguigu'];
- 用途
- 給多個形參賦值
- 各種資料型別的擴充套件
-
字串
- 模板字串
- 作用: 簡化字串的拼接
- 模板字串必須用``
- 變化的部分使用${xxx}定義
- contains(str) : 判斷是否包含指定的字串
- startsWith(str) : 判斷是否以指定字串開頭
- endsWith(str) : 判斷是否以指定字串結尾
- repeat(count) : 重複指定次數
- 模板字串
-
數值擴充套件
- 二進位制與八進位制數值表示法: 二進位制用0b, 八進位制用0o
- Number.isFinite(i) : 判斷是否是有限大的數
- Number.isNaN(i) : 判斷是否是NaN
- Number.isInteger(i) : 判斷是否是整數
- Number.parseInt(str) : 將字串轉換為對應的數值
- Math.trunc(i) : 直接去除小數部分
-
物件
- 簡化的物件寫法
- 省略同名的屬性值
- 省略方法的function
let name = 'Tom'; let age = 12; let person = { name, age, setName (name) { this.name = name; } }; 複製程式碼
- Object.assign(target, source1, source2..) : 將源物件的屬性複製到目標物件上
- Object.is(v1, v2) : 判斷2個資料是否完全相等(底層通過字串的形式判斷) console.log(Object.is('abc', 'abc'));//true console.log(NaN == NaN);//false console.log(Object.is(NaN, NaN));//true console.log(0 == -0);//true console.log(Object.is(0, -0));//false
- __proto__屬性 : 隱式原型屬性 let obj2 = {}; obj2.proto = obj1; //obj1是obj2的父類
-
陣列
- Array.from(v) : 將偽陣列物件或可遍歷物件轉換為真陣列(通過標籤獲得的是偽陣列(document.getElementsByTagName('button')) 不能用普通陣列的方法遍歷,需要轉為真陣列)
- Array.of(v1, v2, v3) : 將一系列值轉換成陣列
- find(function(value, index, arr){return true}) : 找出第一個滿足條件返回true的元素
- findIndex(function(value, index, arr){return true}) : 找出第一個滿足條件返回true的元素下標
-
函式
- 箭頭函式
- 用來定義匿名函式
- 基本語法:
- 沒有引數: () => console.log('xxxx')
- 一個引數: i => i+2
- 大於一個引數: (i,j) => i+j
- 函式體不用大括號: 會預設返回結果(不用return)
- 函式體如果有多個語句, 需要用{}包圍, 若有需要返回的內容,需要手動返回(加上return)
- 使用場景: 多用來定義回撥函式
- 箭頭函式的特點: 1、簡潔 2、箭頭函式沒有自己的this,箭頭函式的this不是呼叫的時候決定的,而是在定義的時候處在的物件就是它的this 3、擴充套件理解: 箭頭函式的this看外層的是否有函式, 如果有,外層函式的this就是內部箭頭函式的this, 如果沒有,則this是window。
- 箭頭函式
點點點運算子(預設呼叫Iterator結構) * 形參的預設值 * 定義形參時指定其預設的值 * rest(可變)引數 * 通過形參左側的...來表達, 取代arguments的使用 但比arguments靈活,只能是最後部分形參引數 function add(...values) { let sum = 0; for(value of values) { sum += value; } return sum; } * 擴充套件運算子(...) * 可以分解出陣列或物件中的資料 let arr1 = [1,3,5]; let arr2 = [2,...arr1,6]; arr2.push(...arr1);
- set/Map容器結構
- 容器: 能儲存多個資料的物件, 同時必須具備操作內部資料的方法
- 任意物件都可以作為容器使用, 但有的物件不太適合作為容器使用(如函式)
- Set的特點: 儲存多個value, value是不重複 ====>陣列元素去重
- Map的特點: 儲存多個key--value, key是不重複, value是可以重複的
- API(方法)
- Set()/Set(arr) //arr是一維陣列
- add(value)
- delete(value)
- clear();
- has(value)
- size
- Map()/Map(arr) //arr是二維陣列
- set(key, value)
- delete(key)
- clear()
- has(key)
- size
- for--of迴圈
- 可以遍歷任何容器
- 陣列
- 物件
- 偽/類物件
- 字串
- 可迭代的物件
- Promise
-
解決
回撥地獄
(回撥函式的層層巢狀, 編碼是不斷向右擴充套件, 閱讀性很差) -
能以同步編碼的方式實現非同步呼叫
-
在es6之前原生的js中是沒這種實現的, 一些第三方框架(jQuery)實現了promise
-
ES6中定義實現API:
// 1. 建立promise物件 var promise = new Promise(function(resolve, reject){ // 做非同步的操作 if(成功) { // 呼叫成功的回撥 resolve(result); } else { // 呼叫失敗的回撥 reject(errorMsg); } }) // 2. 呼叫promise物件的then() promise.then(function( result => console.log(result), errorMsg => alert(errorMsg) )) 複製程式碼
1). 理解:
-
Promise物件: 代表了未來某個將要發生的事件(通常是一個非同步操作)
-
有了promise物件, 可以將非同步操作以同步的流程表達出來, 避免了層層巢狀的回撥函式(俗稱'回撥地獄')
-
ES6的Promise是一個建構函式, 用來生成promise例項 2). 使用promise基本步驟(2步):
-
建立promise物件 let promise = new Promise((resolve, reject) => { //初始化promise狀態為 pending //執行非同步操作 if(非同步操作成功) { resolve(value);//修改promise的狀態為fullfilled } else { reject(errMsg);//修改promise的狀態為rejected } })
-
呼叫promise的then() promise.then(function( result => console.log(result), errorMsg => alert(errorMsg) )) 3.) promise物件的3個狀態
-
pending: 初始化狀態
-
fullfilled: 成功狀態
-
rejected: 失敗狀態 4.) 應用:
-
使用promise實現超時處理
-
使用promise封裝處理ajax請求 let request = new XMLHttpRequest(); request.onreadystatechange = function () { } request.responseType = 'json'; request.open("GET", url); request.send();
Symbol
前言:ES5中物件的屬性名都是字串,容易造成重名,汙染環境 Symbol: 概念:ES6中的新增了一種原始資料型別symbol(已有的原始資料型別:String, Number, boolean, null, undefined, 物件) 特點: 1、Symbol屬性值對應的值是唯一的,解決命名衝突問題 2、Symbol值不能與其他資料進行計算,包括同字串拼串 3、for in, for of遍歷時不會遍歷symbol屬性。 使用: 1、呼叫Symbol函式得到symbol值 let symbol = Symbol(); let obj = {}; obj[symbol] = 'hello'; 2、傳參標識 let symbol = Symbol('one'); let symbol2 = Symbol('two'); console.log(symbol);// Symbol('one') console.log(symbol2);// Symbol('two') 3、內建Symbol值 * 除了定義自己使用的Symbol值以外,ES6還提供了11個內建的Symbol值,指向語言內部使用的方法。 - Symbol.iterator * 物件的Symbol.iterator屬性,指向該物件的預設遍歷器方法(後邊講)
Iterator遍歷器 概念: iterator是一種介面機制,為各種不同的資料結構提供統一的訪問機制 作用: 1、為各種資料結構,提供一個統一的、簡便的訪問介面; 2、使得資料結構的成員能夠按某種次序排列 3、ES6創造了一種新的遍歷命令for...of迴圈,Iterator介面主要供for...of消費。 工作原理: - 建立一個指標物件,指向資料結構的起始位置。 - 第一次呼叫next方法,指標自動指向資料結構的第一個成員 - 接下來不斷呼叫next方法,指標會一直往後移動,直到指向最後一個成員 - 每呼叫next方法返回的是一個包含value和done的物件,{value: 當前成員的值,done: 布林值} * value表示當前成員的值,done對應的布林值表示當前的資料的結構是否遍歷結束。 * 當遍歷結束的時候返回的value值是undefined,done值為false
iterator原生程式碼// 自定義iterator生成指標物件
function mockIterator(arr) {
let nextIndex = 0;
return {
next: function () {
return nextIndex<arr.length?{value: arr[nextIndex++], done: false}:{value: undefined, done: true}
}
}
}
let arr = [1,2,3,4,5];
let iteratorObj = mockIterator(arr);
console.log(iteratorObj.next());
console.log(iteratorObj.next());
console.log(iteratorObj.next());
es6已經將這種介面加在指定的資料型別上 原生具備iterator介面的資料(可用for of遍歷)
1、Array
2、arguments
3、set容器
4、map容器
5、String
。。。
使用三點運算子和解構賦值是預設使用iterator介面
複製程式碼
Generator函式 概念: 1、ES6提供的解決非同步程式設計的方案之一 2、Generator函式是一個狀態機,內部封裝了不同狀態的資料, 3、用來生成遍歷器物件 4、可暫停函式(惰性求值), yield可暫停,next方法可啟動。每次返回的是yield後的表示式結果 特點: 1、function 與函式名之間有一個星號 2、內部用yield表示式來定義不同的狀態 例如: function* generatorExample(){ let result = yield 'hello'; // 狀態值為hello yield 'generator'; // 狀態值為generator } 3、generator函式返回的是指標物件(接11章節裡iterator),而不會執行函式內部邏輯 4、呼叫next方法函式內部邏輯開始執行,遇到yield表示式停止,返回{value: yield後的表示式結果/undefined, done: false/true} 5、再次呼叫next方法會從上一次停止時的yield處開始,直到最後 6、yield語句返回結果通常為undefined, 當呼叫next方法時傳參內容會作為啟動時yield語句的返回值。
async函式(源自ES2017) 概念: 真正意義上去解決非同步回撥的問題,同步流程表達非同步操作 本質: Generator的語法糖 語法: async function foo(){ await 非同步操作; await 非同步操作; } 特點: 1、不需要像Generator去呼叫next方法,遇到await等待,當前的非同步操作完成就往下執行 2、返回的總是Promise物件,可以用then方法進行下一步操作 3、async取代Generator函式的星號*,await取代Generator的yield 4、語意上更為明確,使用簡單,經臨床驗證,暫時沒有任何副作用