ES新特性
1、let、const
塊級作用域
變量提升
最佳實踐:不使用var ,默認使用const ,明確會改的使用let。
2、解構
- 數組
const arr = [1,2,3]
const [a,b] = arr;
const [,,c] = arr;
使用…方式解構
const [a,...rest] = arr;
默認值
const [a,b,c,d = 12] = arr
- 對象
const obj = {
name:'zs',
age:18
}
const {name} = obj;
// 重命名
const {name:rename} = obj;
3、模板字符串
let str = `
i am
${name}
`
// 帶標籤的模板字符串
const str = console.log`hello world`
4、字符串的擴展方法
- includes()
- startsWith()
- endsWith()
5、參數默認值、 剩餘參數
… 操作符
function fn(…args){}
6、展開數組
const arr = [1,2,3];
console.log(...arr)
7、箭頭函數
不會改變this的指向。
箭頭函數不適用:
- 構造函數
- 沒有arguments
- 沒有this
8、對象字面量
const obj = {
foo:123,
method1(){
console.log('1')
},
//計算屬性名
[Math.random](){
}
}
9、Object
- Object.assign 多個對象複製到一個目標對象。
const source1 = {
a:123,
b:23
}
const target = {
a:123,
c:23
}
const res = Object.assign(target,source1)
- Object.is 判斷兩個值是否一樣
10、proxy
Object.defineProperty
proxy
const person = {
name:'ss',
age:19
}
const personProxy = new Proxy(person,{
get(target,key){
console.log(target,key)
return 100;
},
set(target,key,value){
console.log(target,key,value)
}
})
console.log(personProxy.name)
personProxy.sex = '女'
proxy的優勢:
- defineProperty只能監視屬性的讀寫,proxy可以監視delete、方法調用等
const person = {
name:'ss',
age:19
}
const personProxy = new Proxy(person,{
deleteProperty(target,property){
console.log('delete')
}
})
delete personProxy.age
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OffyGgUn-1593528494642)(./img/1.png)]
- proxy更好的監視數組
const list = []
const listProxy = new Proxy(list,{
set(target,property,value){
console.log(target,property,value)
target[property] = value;
return true//表示設置成功
}
})
listProxy.push(10)
11、reflect
統一的對象操作API
靜態類
內部封裝了一系列對對象的底層操作 。
const person = {
name:'ss',
age:19
}
const personProxy = new Proxy(person,{
get(target,key){
// ... 自定義邏輯
return Reflect.get(target,key)
},
set(target,key,value){
console.log(target,key,value)
}
})
console.log(personProxy.name)
personProxy.sex = '女'
Reflect.has
Reflect.deleteProperty
Reflect.ownkeys
12、promise
異步編程解決方案
13、class
// es5
function Person(name) {
this.name = name
}
Person.prototype.say = function(){}
// es6
class Person{
constructor(name){
this.name = name
}
say(){
}
}
const person = new Person('zhangsan');
- 靜態方法
class Person{
constructor(name){
this.name = name
}
// 實例方法
say(){
}
// 靜態方法
static create(name){
return new Person(name)
}
}
- 實例方法
- 類的繼承 – extends
class Person{
constructor(name){
this.name = name
}
say(){
console.log('父say')
}
}
class Student extends Person{
constructor(name,number){
super(name)
this.number = number
}
hello(){
super.say();
console.log('hello')
}
}
let stu = new Student('zhaosi',12342);
stu.hello();
14、set、map
Set 不允許重複
const set = new Set();
set.add(1).add(2).add(3)
// 遍歷
set.forEach(()=>{})
for(let i of set){
}
set.size
set.has()
set.delete()
set.clear()
const arr = [1,2,3,1,4,2]
const set1 = new Set(arr)
Array.from(set1)
const arr1 = [...set1]
Map
類似對象,
const obj = {
}
obj[true] = 'value'
obj[123] = 'value'
obj[{a:1}] = 'value'
Object.keys(obj)
const m = new Map()
const tom = {name:'tom'}
m.set(tom,99)
m.has()
m.delete()
m.clear()
m.forEach(()=>{})
15、Symbol
const a = Symbol()
console.log(a)
const obj = {
}
obj[Symbol('a')] = 123;
obj[Symbol('b')] = 445;
console.log(obj[Symbol('a')])
const a = Symbol.for('foo')
const b = Symbol.for('foo')
console.log(a===b)
const obj1 = {
[Symbol.toStringTag]:'XObject'
}
console.log(obj1.toString()) // [object XObject]
私有屬性
- 唯一性
- for…in \ Object.key() 獲取不到
- Object.getOwnPropertySymbol(obj)
16、for…of – 迭代器
const arr = [2,324,12,324,2,234]
for(let i of arr){
console.log(i)
if(i>188){
break
}
}
// arr.forEach() //無法中斷循環
// arr.some()
// arr.every()
// 遍歷set、map
可迭代接口 Iterable
實現Iterable接口,是使用for…of的前提
const arr = [1,23,321,421]
const iterator = arr[Symbol.iterator]()
iterator.next()
實現可迭代接口
const obj= {
store:['foo','bar','baz'],
[Symbol.iterator]:function(){
let index = 0;
const self = this;
return {
next:function(){
const res = {
value:self.store[index],
done:index>=self.store.length
}
index ++
return res;
}
}
}
}
for(let item of obj){
console.log(item)
}
*** 迭代器模式 ***
const todo = {
life:['s','d'],
learn:['e','w2'],
work:['dfa'],
each:function(cb){
const all = [].concat(this.life,this.learn,this.work)
for(const item of all){
cb(item)
}
},
[Symbol.iterator]:function(){
const all = [...this.life,...this.learn,...this.work]
let index = 0;
return {
next:function(){
return {
value:all[index],
done:index++>=all.length
}
}
}
}
}
//for(let item of to.life){}
//for(let item of to.learn){}
//for(let item of to.work){}
todo.each(function(item){
console.log(item)
})
for(let item of todo){
console.log(item)
}
17、生成器 generator
避免回調嵌套
function * foo(){
console.log('zcc')
return 100
}
const res = foo();
console.log(res)
res.next()
// 配合 yield
function * boo(){
console.log('111')
yield 100
console.log('222')
yield 200
console.log('333')
yield 300
}
const gen = boo();
gen.next()
生成器應用
// 案例 : 發號器
function * createID(){
let id = 1;
while(true){
yield id++
}
}
const id = createID();
id.next()
// 實現iterator方法
const todo = {
life:['s','d'],
learn:['e','w2'],
work:['dfa'],
[Symbol.iterator]:function * (){
const all = [...this.life,...this.learn,...this.work]
for(let item of all){
console.log(item)
}
}
}
for(let item of todo){
console.log(item)
}
18、ES Modules
模塊化
19、ES2016 ES2017
ES2016
- Array.prototype.includes
- 指數運算符
Math.pow()
** 2**10
ES2017
- Object.values()
- Object.entries()
- Object.getOwnPropertyDescriptors()
- String.prototype.padStart
- String.prototype.padEnd
- 函數參數中添加尾逗號
function foo(arg1,arg2,){
}
- async/await
TS
解決JS類型系統問題
-
強類型 VS 弱類型 (類型安全)
強類型有更強的類型約束。
強類型不允許隱式類型轉換。 -
靜態類型 VS 動態類型 (類型檢查)
變量聲明時就是明確的。-- 靜態類型
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-SCbTOyNS-1593528494643)(./img/2.png)] -
弱類型的問題
- 運行階段才能發現錯誤
- 類型不明確,造成函數功能發生改變
- 對對象索引發生錯誤
const obj = {}
obj[123] = 456
obj[123] // undefined
- 強類型的優勢
- 錯誤更早的暴露
- 代碼更智能,編碼更準確
- 重構更牢靠
- 減少不必要的類型判斷
flow(工具)
1、 JS的類型檢查器
通過類型註解的方式,檢查類型。
function sum(a:number,b:number){
return a + b
}
通過babel去除註解代碼。
2、 使用
yarn add flow-bin --dev // 安裝
yarn flow init //初始化配置文件
yarn flow
yarn flow stop //停止命令
3、 編譯移除註解
yarn add flow-remove-types --dev // 移除
yarn flow-remove-types . -d dist
// 或者 通過babel方式移除
yarn add @babel/core @babel/cli @babel/preset-flow --dev
yarn babel part01/module02/flow -d dist // 命令
通過babel的 方式 要配置.babelrc文件,配置如下:
{
"presets":["@babel/preset-flow"]
}
4、開發工具插件
Flow Language Support VScode插件
5、 flow類型
6、 flow運行環境API
內置對象
TS (語言)
1、JS的超集
- 可以對ES新特性編譯(類似babel)
- 功能強大、生態健全、完善
- 任意JS環境都支持
- TS屬於漸進式的
- 【缺點】語言本省多了很多概念,如接口、泛型
- 【缺點】項目初期,增加開發成本
2、基本使用 ts代碼–> js代碼yarn add typescript --dev tsc .\01-getting-start.ts
3、配置文件
tsc --init
tsconfig.json
4、 原始類型
原始類型
標準庫-- 就是內置對象所對應的說明
5、 TS中文錯誤消息
tsc --locale zh-Ch
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-45u2mvba-1593528494645)(./img/3.png)]
6、作用域問題
7、類型
隱式類型推斷
類型斷言
// as 關鍵字
const num1 = res as number; //(推薦)
//或
const num2 = <number>res; // 會和JSX標籤衝突
8、 接口
接口
9、類
類
類和接口 類和接口
用接口抽象類的共同屬性
抽象類:約束子類必須有某些成員,只能被繼承;
子類必須實現父類的抽象方法。
abstract class Animals {
eat(food:string):void{}
abstract run(distance:number):void
}
10、泛型 泛型
11、類型聲明
JS性能優化
1、內存管理
申請、使用、釋放空間。
2、垃圾回收 、常見GC算法
- JS中的垃圾
- JS中內存管理是自動的
- 對象不再被引用時是垃圾
- 對象不能從根上訪問到時是垃圾
- 可達對象 可達
- 引用、作用域鏈
- 全局執行上下文(根)
- GC算法
- GC-垃圾回收
- GC可以在內存中找到垃圾
- 程序中不再使用的對象
- 程序中不能訪問到的對象
- GC是一種機制(垃圾回收器完成的具體工作)
- 工作內容就是查找垃圾釋放空間、回收空間
- 算法就是工作時查找和回收所遵循的規則
- 常見GC算法
3、V8的垃圾回收
- V8
- JS 執行引擎
- 即時編譯
- 內存設限
- V8垃圾回收策略
- 分代回收思想
- 內存分新生代和老生代
- 針對不同的生代採用不用的算法
- V8中常用算法
- 分代回收
- 空間複製
- 標記清除
- 標記整理
- 標記增量
- 新生代垃圾回收
- V8內存分配
- V8內存空間一分爲二
- 小空間用於存儲新生代對象(32M | 16M)
- 新生代指的是存活時間短的對象
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-yOXCqj7p-1593528494647)(./img/4.png)]
- 回收實現
- 回收過程採用複製算法+標記整理
- 新生代內存區分爲2個等大小空間
- 使用空間爲From,空閒空間爲To
- 活動對象存儲於From空間
- 標記整理後將活動對象拷貝至To
- From和To交換空間完成釋放
- 拷貝過程中可能會出現晉升(將新生代對象移動至老生代)
- 一輪GC還存活的新生代對象需要晉升
- To空間使用率超過25% — 晉升
- V8內存分配
- 老生代垃圾回收
- 老生代對象存放在右側老生代區
- 64位操作系統1.4G 32位 700M
- 老生代對象就是存活時間較長的對象
- 垃圾回收實現
- 主要採用標記清除、標記整理、增量標記算法
- 首先使用標記清除完成垃圾空間的回收
- 採用標記整理進行空間優化(對象晉升時)
- 採用增量標記進行效率優化
- VS 新生代
- 新生代—空間換時間
- 老生代不適合複製算法(空間浪費、複製量大)
4、performance工具
- 爲啥使用performance
- GC的目的是爲了實現內存空間的良性循環
- 良性循環的基石是合理利用
- 時刻關注才能確定是否合理
- performance提供多種監控方式
- performance使用
- 打開瀏覽器輸入目標網址
- F12面板 — 性能
- 開啓錄製功能,訪問具體頁面
- 執行用戶行爲,一段時間後停止錄製
- 分析界面中記錄的內存信息
- 內存問題的體現
- 頁面出現延遲加載或經常性暫停
- 頁面持續性出現槽糕的性能
- 頁面性能隨時間延長越來越差
- 界定內存問題的標準
- 內存泄漏 內存使用持續升高
- 內存膨脹 在多數設備上都存在性能問題
- 頻繁垃圾回收 通過內存變化圖分析
- 監控內存的幾種方式
5、代碼優化
-
如何精準測試JS性能?
- 本質上就是採集大量的執行樣本進行數學統計和分析
- 使用基於Benchmark.js的https://jsperf.com完成
-
jsperf使用流程
- 使用GitHub賬號登錄
- 填寫個人信息(非必填)
- 填寫詳細的測試用例信息(title、slug)
- 填寫準備代碼(DOM操作時經常使用)
- 填寫必要有setup與teardown代碼
- 填寫測試代碼片段
-
慎用全局變量慎用全局變量
- 全局變量定義在全局執行上下文,是所有作用域鏈的頂端
- 全局執行上下文一直存在於上下文執行棧,直到程序退出
- 如果某個局部作用域出現了同名變量則會出現遮蔽或污染全局
-
緩存全局變量全局變量
- 將使用中無法避免的全局變量緩存到局部
-
通過原型對象添加附加方法原型對象添加
-
避開閉包陷阱閉包
- 閉包的特點
- 外部具有指向內部的引用
- 在‘外’部作用域訪問‘內’部作用域的數據
- 關於閉包
- 閉包是一種強大的語法
- 閉包使用不當很容易出現內存泄漏
- 不要爲了閉包而閉包
- 閉包的特點
-
避免屬性訪問方法使用屬性訪問方法
- JS不需屬性的訪問方法,所有屬性都是外部可見的
- 使用屬性訪問方法只會增加一層重定義,沒有訪問的控制力
-
for循環優化for
-
選擇最優的循環方法最優的循環方法
- for(中)
- for … in (低)
- foreach (高)
-
文檔碎片優化節點添加節點添加
-
克隆優化節點節點克隆
-
直接量替換new ObjectObject
本模塊思維導圖
Q:vue項目有很多分離DOM,如何定位到是哪裏生成的呢?