日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

ES6-ES12

發布時間:2023/12/20 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 ES6-ES12 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

  • ES6
    • 一、class定義類
      • 1.類的聲明
      • 2.constructor
      • 3.實例方法
      • 4.類的訪問器方法
      • 5.類的靜態方法
      • 6.繼承
      • 7.super關鍵字
    • 二、字面量的增強
      • 1.屬性的簡寫
      • 2.方法的簡寫
      • 3.計算屬性名
    • 三、解構賦值
      • 1.數組的解構
      • 2.對象的解構
    • 四、var、const、let
      • 1.var
      • 2.const
      • 3.let
    • 五、模板字符串
      • 1.基本使用
      • 2.標簽模板字符串
    • 六、函數的參數
      • 1.函數的默認參數
      • 2.函數的剩余參數
      • 3.箭頭函數的補充
    • 七、展開運算符
    • 八、數值的表示
    • 九、Symbol
      • 1.Symbol的使用
    • 十、Set
      • 1.Set的基本使用
      • 2.Set的常見方法
      • 3.WeakSet
        • (1) Set與WeakSet的區別
        • (2) WeakSet常見方法
    • 十一、Map
      • 1.Map的常用方法
      • 2.WeakMap
        • (1)Map與WeakMap的區別
        • (2)WeakMap的常用方法
        • (3)WeakMap的應用
    • 十二、Porxy
      • 1.監聽對象的方式
      • 2.Proxy的基本使用
      • 3.Proxy的捕獲器
    • 十三、Reflect
      • 1.Reflect的基本使用
      • 2.Reflect的常見方法
      • 3.Reflect中的construct
      • 4.receiver的作用
  • ES7
      • 1.數組includes方法
      • 2.指數運算符
  • ES8
      • 1. Object values
      • 2. Object entries
      • 3.String Padding
      • 4.Trailing Commas
      • 5.Object Descriptors
  • ES9
    • 一、迭代器iterators
    • 二、promise的finally
  • ES10
      • 1.flat與flatMap
        • (1)flat
        • (2)flatMap
      • 2.entries轉對象
      • 3.trimStart與trimEnd
      • 4. Symbol description
        • 5. Optional catch binding
  • ES11
      • 1.BigInt
      • 2.空值合并運算符
      • 3.可選鏈
      • 4.globalThis
  • ES12
      • 1.FinalizationRegistry
      • 2.WeakRefs

ES6

一、class定義類

構造函數形式創建 ,不僅僅和編寫普通的函數過于相似,而且代碼并不容易理解。 在ES6新的標準中使用了class關鍵字來直接定義類; 但是類本質上構造函數、原型鏈的語法糖而已;

1.類的聲明

// 類聲明 class Person { } // 類表達式 var Student = class { }// 相似的如: // 函數聲明 function Parent() { } // 函數表達式 var son = function() { }

2.constructor

constructor方法(即構造方法)是類的默認方法,通過new生成對象時,自動調用該方法。

  • 每個類只能有一個構造函數,如果包含多個構造函數,那么會拋出異常;

  • 一個類必須有constructor方法,如果沒有顯示定義,一個空的constructor方法會被默認添加;

class People {constructor(name, age) {this.name = namethis.age = age}eatting() {console.log(this.name + "吃!");}running() {console.log(this.name + "跑!");} }var p1 = new People('顫三',19) p1.eatting() // 顫三吃! p1.running() // 顫三跑!

3.實例方法

class中定義的方法,實際上都是定義在這個"類"的prototype上的。

class People {constructor(name, age) {this.name = namethis.age = age}eatting() {console.log(this.name + "吃!");}running() {console.log(this.name + "跑!");} }console.log(Object.getOwnPropertyDescriptors(People)); // 輸出如下: // { // length: { value: 2, writable: false, enumerable: false, configurable: true }, // name: { // value: 'People', // writable: false, // enumerable: false, // configurable: true // }, // prototype: { // value: {}, // writable: false, // enumerable: false, // configurable: false // } // } console.log(Object.getOwnPropertyDescriptors(People.prototype)); // 輸出如下: // { // constructor: { // value: [class People], // writable: true, // enumerable: false, // configurable: true // }, // eatting: { // value: [Function: eatting], // writable: true, // enumerable: false, // configurable: true // }, // running: { // value: [Function: running], // writable: true, // enumerable: false, // configurable: true // } // }

4.類的訪問器方法

當調用獲取設置某個屬性時,觸發getset函數里的函數體代碼。

class Abc {constructor(name) {this.name = name}set name(newName) {console.log("設置了這個屬性name");}get name() {console.log("調用或獲取了這個屬性name");// return this.namereturn "獲取" // get必須有返回值} } console.log(Abc.name); // Abc

5.類的靜態方法

靜態方法通常用于定義直接使用類來執行的方法,不需要有類的實例,使用static關鍵字來定義.

class Asd {constructor(asd) {this.asd = asd}haox() {console.log("不是靜態方法不可以直接調用");}static create() {console.log("你調用了靜態方法");} } Asd.create() // 你調用了靜態方法 // Asd.haoX() // 報錯,不是靜態方法不能直接調用,需要new一個實例才能調用 var a1 = new Asd() a1.haox() // 不是靜態方法不可以直接調用

6.繼承

通過extends關鍵字繼承。

class A {} class B extends A {}
  • 子類中新添加的方法是添加到了子類的原型對象上,并不是父類的遠程對象上;
class A {constructor(name,age) {this.name = namethis.age = age}eatting() {console.log(this.name + "吃!");}running() {console.log(this.name + "跑!");} } class B extends A {constructor(name,age,height) {// this.name = name// this.age = agesuper(name,age) // 這里必須調用父類的構造器否則報錯(派生類的構造函數必須包含 "super" 調用。),同時可以避免代碼冗余this.height = height}study() {console.log("study");} }// 子類中新添加的方法是添加到了子類的原型對象上,并不是父類的遠程對象上 console.log(Object.getOwnPropertyDescriptors(B.prototype)); // 輸出如下: // { // constructor: { // value: [class B extends A], // writable: true, // enumerable: false, // configurable: true // }, // study: { // value: [Function: study], // writable: true, // enumerable: false, // configurable: true // } // } console.log(Object.getOwnPropertyDescriptors(A.prototype)); // 輸出如下: // { // constructor: { // value: [class A], // writable: true, // enumerable: false, // configurable: true // }, // eatting: { // value: [Function: eatting], // writable: true, // enumerable: false, // configurable: true // }, // running: { // value: [Function: running], // writable: true, // enumerable: false, // configurable: true // } // }

7.super關鍵字

  • 可調用父類的構造函數;
  • 可調用父類上的方法

二、字面量的增強

ES6中對 對象字面量 進行了增強;

1.屬性的簡寫

2.方法的簡寫

3.計算屬性名

var age = 18 var obj1 = {// age : ageage, // 1.屬性的簡寫// 2.方法名簡寫// foo: function() {// }foo() { // 簡寫},// 3.計算屬性[age + 123]: 'hhhhh',[age + '123']: 'hhhhh' }console.log(obj1); // { '141': 'hhhhh', '18123': 'hhhhh', age: 18, foo: [Function: foo] }

三、解構賦值

1.數組的解構

// 1.數組的解構 var names = ['agc', 'cag', 'asd'] var [item1, item2, item3] = names console.log(item1,item2,item3); // agc cag asd// 2.解構后面元素 var [, itema, itemb] = names console.log(itema,itemb); // cag asd// 3.解構出一個元素,后面的元素放到一個新數組中 var [itemx, ...newNames] = names console.log(newNames); // [ 'cag', 'asd' ]// 4.解構的默認值 (當解構的元素可能沒有值時,可以設置一個默認值) var [itema, itemb, itemc, itemd = 'aaa'] = names console.log(itemd); // aaa

2.對象的解構

var obj = {name: 'tjx',age: 39,height: 12,a: 12 }// 1.對象的解構 var { namea, age, height } = obj console.log(namea, age, height); // tjx 39 12var { a } = obj console.log(a); // 12// 2.解構重命名 var {name: newName} = obj console.log(newName); // tjx// 3.解構重命名并給默認值 var { address: newAddress = "廣州" } = obj console.log(newAddress); // 廣州

四、var、const、let

  • let和const,是目前開發中推薦使用的;

  • 優先推薦使用const,這樣可以保證數據的安全性不會被隨意的篡改;

  • 只有當明確知道一個變量后續會需要被重新賦值時,這個時候再使用let;

1.var

  • 作用域提升;
  • 函數有塊級作用域,在函數中var變量屬于該函數的局部變量;

2.const

const關鍵字是constant的單詞的縮寫,表示常量、衡量的意思;

它表示保存的數據一旦被賦值,就不能被修改;

但是如果賦值的是引用類型,那么可以通過引用找到對應的對象,修改對象的內容;

3.let

聲明的變量具有塊級作用域的特征;

五、模板字符串

1.基本使用

let agea = 9 const info = `age: ${agea *2}` console.log(info); // age: 18function doubleAge() {return agea * 2 } const infoa = `age: ${doubleAge()}` console.log(infoa); // age: 18

2.標簽模板字符串

// 第一個參數依然是模板字符串中整個字符串,只是被切割成多塊,放到了一個數組中 // 第二個參數是模塊字符串中,第一個${},一次類推 function foo(m, n, x) {console.log(m,n, x, '..........'); } const named = 'tjx' const aged = 13// 通過模板標簽調用函數 foo`Hello${named}, world${aged},!` // [ 'Hello', ', world', ',!' ] tjx 13 ..........

六、函數的參數

1.函數的默認參數

// 1.函數默認參數 function foo(m = 'aaa', n = 'bb') {console.log(m,n); } foo() // aaa bb foo('dfs','fds') // dfs fds// 對象參數和默認參數以及解構 // 寫法一: function printInfo({name, age} = {name: 'tjc', age: 19}) {console.log(name,age); } printInfo() // tjc 19 printInfo({name: 'lobe', age: 90}) // lobe 90// 寫法二: function printInfo({name = 'tjx', age = 19} = {}) {console.log(name,age); }

2.函數的剩余參數

function foo(m,n,...args) {console.log(m,n); // 1 2console.log(args); // [ 3, 4, 5, 6, 7 ]console.log(arguments); // [Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5, '5': 6, '6': 7 } } foo(1,2,3,4,5,6,7)

3.箭頭函數的補充

  • 箭頭函數沒有prototype,不能通過new關鍵字創建箭頭函數;
  • 箭頭函數沒有this以及arguments

七、展開運算符

const nameg = ['asd', 'dfg', 'sdfg'] const nameh = 'tjx' const infog = {name: 'tjx', age: 19}// 1.函數調用時 function foo(x, y, z) {console.log(x,y,z); }foo(...nameg) // asd dfg sdfg foo(...nameh) // t j x// 2.構造數組時 const newNameg = [...nameg, ...nameh] console.log(newNameg); // [ 'asd', 'dfg', 'sdfg', 't', 'j', 'x' ]// 3.構造對象字面量時 const objh = {...infog, address: 'guand'} console.log(objh); // { name: 'tjx', age: 19, address: 'guand' }

八、數值的表示

const num1 = 100 // 十進制 const num2 = 0b100 // 二進制 const num3 = 0o100 // 八進制 const num4 = 0x100 // 十六進制console.log(num1, num2, num3, num4); // 100 4 64 256// 大的數值的連接符 const num = 10_000_000_000_000 console.log(num); // 10000000000000

九、Symbol

在ES6之前,對象的屬性名都是字符串形式,那么很容易造成屬性名的沖突; 比如原來有一個對象,我們希望在其中添加一個新的屬性和值,但是我們在不確定它原來內部有什么內容的情況下, 很容易造成沖突,從而覆蓋掉它內部的某個屬性;Symbol就是為了解決上面的問題,用來生成一個獨一無二的值。

1.Symbol的使用

  • Symbol值是通過Symbol函數來生成的,生成后可以作為屬性名; 在ES6中,對象的屬性名可以使用字符串,也可以使用Symbol值
  • Symbol即使多次創建值,它們也是不同的:Symbol函數執行后每次創建出來的值都是獨一無二的;
  • 也可以在創建Symbol值的時候傳入一個描述description:這個是(ES10)新增的特性;
// 1.Symbol的基本使用 const symbol1 = Symbol() const symbol2 = Symbol() console.log(symbol1 === symbol2); // false// 2.description描述符 const symbol3 = Symbol('aaa') console.log(symbol3.description); // aaa// 3.Symbol值最為key // 3.1 在定義對象字面量時使用 const obj = {[symbol1]: 'abc',[symbol2]: 'dfa' } // 3.2 新增屬性 obj[symbol3] = 'nab' // 3.3 Object.defineProperty方式const symbol4 = Symbol() Object.defineProperty(obj, symbol4, {enumerable: true,configurable: true,writable: true,value: 'mag' }) console.log(obj[symbol1], obj[symbol2], obj[symbol3], obj[symbol4]); // abc dfa nab mag // 注意:不能通過 . 的方式獲取 結果:undefined console.log(obj.symbol1); // undefined// 4.使用Symbol作為key的屬性名,在遍歷/Object.keys等中是獲取不到這些symbol值,需要Object.getOwnPropertySymbols來獲取所有Symbol的key console.log(Object.keys(obj)); // [] console.log(Object.getOwnPropertyNames(obj)); // [] console.log(Object.getOwnPropertySymbols(obj)); // [ Symbol(), Symbol(), Symbol(aaa), Symbol() ] const keys = Object.getOwnPropertySymbols(obj) for (const sKey of keys) {console.log(obj[sKey]); // 輸出如下:// abc// dfa// nab// mag }// 5.創建相同的Symbol Symbol.for(key)/Symbol.keyFor(symbol) const a = Symbol.for('aaa') const b = Symbol.for('aaa') console.log(a); // Symbol(aaa) console.log(a === b); // trueconst keya = Symbol.keyFor(a) // 獲取aaa用于通過for()創建相同的symbol console.log(keya); // aaa const c = Symbol.for(keya) console.log(a === c); // true

十、Set

1.Set的基本使用

在ES6中新增了另外兩種數據結構:Set、Map,以及它們的另外形式WeakSet、WeakMap。

  • Set是一個新增的數據結構,可以用來保存數據,類似于數組,但是和數組的區別是元素不能重復。
  • 創建Set我們需要通過Set構造函數(暫時沒有字面量創建的方式)
// 1.創建Set const set = new Set(); set.add(10) set.add(20) set.add(30) set.add({}) console.log(set); // Set(4) { 10, 20, 30, {} } set中內容不能重復 set.add({}) console.log(set); // Set(6) { 10, 20, 30, {}, {} } 這里set存放的是地址,所以兩個對象 var obj = {} set.add(obj) set.add(obj) set.add(obj) console.log(set); // Set(6) { 10, 20, 30, {}, {}, {} }// 2.數組去重 const arr = [33, 10, 26, 30, 33, 26] const arrSet = new Set(arr) const newArr1 = Array.from(arrSet) const newArr2 = [...arrSet] // set也支持展開運算符 console.log(newArr1); // [ 33, 10, 26, 30 ] console.log(newArr2); // [ 33, 10, 26, 30 ]

2.Set的常見方法

Set常見屬性:

  • size:返回Set中的元素的個數;

Set常見方法:

  • add(value):添加某個元素,返回Set對象本身;
  • delete(value):從set中刪除和這個值相等的元素,返回boolean類型;
  • has(value):判斷set中是否存在某個元素,返回boolean類型;
  • clear():清空set中所有的元素,沒有返回值;
  • forEach(callback, [, thisArg]):通過forEach遍歷set;

**另外:**Set是支持for of的遍歷的。

const arr1 = [33, 10, 26, 30, 33, 26] const arrSet1 = new Set(arr1)// 1.set的屬性 size console.log(arrSet1.size); // 4// 2.set的方法 arrSet1.add(1000) console.log(arrSet1); // Set(5) { 33, 10, 26, 30, 1000 }arrSet1.delete(1000) // 刪除這里只能傳入值,不是下標 console.log(arrSet1); // Set(4) { 33, 10, 26, 30 }console.log(arrSet1.has(33)); // true 判斷是否有這個值,返回布爾值arrSet1.clear() console.log(arrSet1); // Set(0) {}// 遍歷Set const arr2 = [33, 10, 26, 30, 33, 26] const arrSet2 = new Set(arr2)arrSet2.forEach(item => {console.log(item); })for (const item of arrSet2) {console.log(item); }

3.WeakSet

一般比較少用。

(1) Set與WeakSet的區別

  • 區別一:WeakSet中只能存放對象類型,不能存放基本數據類型;
  • 區別二:WeakSet對元素的引用是弱引用,如果沒有其他引用對某個對象進行引用,那么GC可以對該對象進行回收;
// 區別一:只能存放對象類型 let weakSet = new WeakSet() // weakSet.add(10) // 報錯// 區別二:對對象是一個弱引用 let obj3 = {name: 'tjx' } weakSet.add(obj3) // 弱引用 console.log(weakSet); // WeakSet { <items unknown> }const set3 = new Set() set.add(obj3) // 強引用

(2) WeakSet常見方法

  • add(value):添加某個元素,返回WeakSet對象本身;
  • delete(value):從WeakSet中刪除和這個值相等的元素,返回boolean類型;
  • has(value):判斷WeakSet中是否存在某個元素,返回boolean類型;

注意:WeakSet只是對對象的弱引用,如果我們遍歷獲取到其中的元素,那么有可能造成對象不能正常的銷毀。 所以存儲到WeakSet中的對象是沒辦法獲取的;

十一、Map

數據結構是Map,用于存儲映射關系

對象存儲映射關系只能用字符串(ES6新增了Symbol)作為屬性名(key);

某些情況下我們可能希望通過其他類型作為key,比如對象,這是我們可以使用Map。

1.Map的常用方法

  • size:返回Map中元素的個數;
  • set(key, value):在Map中添加key、value,并且返回整個Map對象;
  • get(key):根據key獲取Map中的value; phas(key):判斷是否包括某一個key,返回Boolean類型;
  • delete(key):根據key刪除一個鍵值對,返回Boolean類型;
  • clear():清空所有的元素;
  • forEach(callback, [, thisArg]):通過forEach遍歷Map;

另外:

  • Map也可以通過for of進行遍歷。
let obj4 = {name: 'tjx' }, obj5 = {age: 12 } // 1.map的創建 const map = new Map() map.set(obj4, 'aaa') map.set(obj5, 'bbb') map.set(1, 'ccc') console.log(map); // Map(3) { { name: 'tjx' } => 'aaa', { age: 12 } => 'bbb', 1 => 'ccc' }// 2.map的常見屬性和方法 console.log(map.size); // 3 map.set('tjx', 'ddd') console.log(map); // 輸出如下:// Map(4) {// { name: 'tjx' } => 'aaa',// { age: 12 } => 'bbb',// 1 => 'ccc',// 'tjx' => 'ddd'// } console.log(map.get('tjx')); // dddconsole.log(map.has(1)); // truemap.delete('tjx') console.log(map); // Map(3) { { name: 'tjx' } => 'aaa', { age: 12 } => 'bbb', 1 => 'ccc' }// map.clear() // console.log(map); // Map(0) {}// 3.map的遍歷 map.forEach((item, key) => {console.log(item, key); // 輸出如下:// aaa { name: 'tjx' }// bbb { age: 12 }// ccc 1 })for(const item of map) {console.log(item); // 輸出如下:// [ { name: 'tjx' }, 'aaa' ]// [ { age: 12 }, 'bbb' ]// [ 1, 'ccc' ] }for (const [key, value] of map) {console.log(key, value); // 輸出如下:// { name: 'tjx' } aaa// { age: 12 } bbb// 1 ccc }

2.WeakMap

(1)Map與WeakMap的區別

  • 區別一:WeakMap的key只能使用對象,不接受其他的類型作為key;
  • 區別二:WeakMap的key對對象想的引用是弱引用,如果沒有其他引用引用這個對象,那么GC可以回收該對象;

(2)WeakMap的常用方法

  • set(key, value):在Map中添加key、value,并且返回整個Map對象;
  • get(key):根據key獲取Map中的value;
  • has(key):判斷是否包括某一個key,返回Boolean類型;
  • delete(key):根據key刪除一個鍵值對,返回Boolean類型;

(3)WeakMap的應用

vue3響應式原理。

// 引用場景(vue3響應式原理) const obj1 = {name: 'tjx',age: 19 } function obj1NameFn1() {console.log("obj1NameFn1被執行"); } function obj1NameFn2() {console.log("obj1NameFn2被執行"); } function obj1AgeFn1() {console.log("obj1AgeFn1被執行"); } function obj1AgeFn2() {console.log("obj1AgeFn2被執行"); }const obj3 = {name: 'aaa',age: 09 } function obj3NameFn1() {console.log("obj3NameFn1被執行"); } function obj3NameFn2() {console.log("obj3NameFn2被執行"); }// 1.創建WealMap const weakMap = new WeakMap()// 2.收集依賴結構 // 2.1 對obj1收集的數據結構 const obj1Map = new Map() obj1Map.set('name', [obj1NameFn1, obj1NameFn2]) obj1Map.set('age', [obj1AgeFn1, obj1AgeFn2]) weakMap.set(obj1, obj1Map)// 3.如果obj1.name發生了變化 // Proxy/Object.definePoroperty obj1.name = 'java' const targetWeakMap = weakMap.get(obj1) const fns = targetWeakMap.get('name') fns.forEach(item => item())

十二、Porxy

1.監聽對象的方式

通過Object.defineProperty的get和set監聽對象屬性的變化。

const obj = {name: 'tjx',age: 19 }Object.keys(obj).forEach(key => {let value = obj[key]Object.defineProperty(obj, key, {get: function() {console.log(`監聽到obj對象的${key}屬性被訪問`);return value},set: function(newValue) {console.log(`監聽到obj對象的${key}屬性被修改`);value = newValue}}) }) obj.name = 'kis' obj.age = 30console.log(obj.name); console.log(obj.age); // 傳統監聽方法的弊端,不能監聽新的屬性的添加 obj.height = 1.88

缺點:如果監聽更加豐富的操作,比如新增屬性、刪除屬性,那么 Object.defineProperty是無能為力的。所以可以通過Proxy類。

2.Proxy的基本使用

在ES6中,新增了一個Proxy類,這個類用于幫助我們創建一個代理。先創建一個代理對象(Proxy對象);之后對該對象的所有操作,都通過代理對象來完成,代理對象可以監聽我們想要對原對象進行哪些操作;

  • 首先new Proxy對象,傳入需要偵聽的對象以及一個處理對象
  • 在處理對象中進行監聽,之后的操作都是直接對Proxy的操作,而不是原有的對象;
const obj = {name: 'tjx',age: 19 }const objProxy = new Proxy(obj, {// 獲取值時的捕獲器// target為obj對象,key為變化的屬性名get: function(target, key) {console.log(`監聽到對象的${key}屬性被訪問了`, target);return target[key]},// 設置值時的捕獲器set: function(target, key, newValue) {console.log(`監聽到對象的${key}屬性被設置值`, target);target[key] = newValue} })console.log(objProxy.name); console.log(objProxy.age);objProxy.name = 'xja' objProxy.age = 39console.log(obj.name); // xja console.log(obj.age); // 39

3.Proxy的捕獲器

13個常用捕獲器。

  • handler.getPrototypeOf()
    • Object.getPrototypeOf 方法的捕捉器。
  • handler.setPrototypeOf()
    • Object.setPrototypeOf 方法的捕捉器。
  • handler.isExtensible()
    • Object.isExtensible 方法的捕捉器。
  • handler.preventExtensions()
    • Object.preventExtensions 方法的捕捉器。
  • handler.getOwnPropertyDescriptor()
    • Object.getOwnPropertyDescriptor 方法的捕捉器。
  • handler.defineProperty()
    • Object.defineProperty 方法的捕捉器。
  • handler.ownKeys()
    • Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。
  • handler.has()
    • in 操作符的捕捉器。
  • handler.get()
    • 屬性讀取操作的捕捉器。
  • handler.set()
    • 屬性設置操作的捕捉器。
  • handler.deleteProperty()
    • delete 操作符的捕捉器。
  • handler.apply()
    • 函數調用操作的捕捉器。
  • handler.construct()
    • new 操作符的捕捉器。
const obj = {name: "why", // 數據屬性描述符age: 18 }// 變成一個訪問屬性描述符 // Object.defineProperty(obj, "name", {// })const objProxy = new Proxy(obj, {// 獲取值時的捕獲器get: function(target, key) {console.log(`監聽到對象的${key}屬性被訪問了`, target)return target[key]},// 設置值時的捕獲器set: function(target, key, newValue) {console.log(`監聽到對象的${key}屬性被設置值`, target)target[key] = newValue},// 監聽in的捕獲器has: function(target, key) {console.log(`監聽到對象的${key}屬性in操作`, target)return key in target},// 監聽delete的捕獲器deleteProperty: function(target, key) {console.log(`監聽到對象的${key}屬性in操作`, target)delete target[key]} })// in操作符 // console.log("name" in objProxy)// delete操作 delete objProxy.name

對函數對象的監聽:

function foo() {} const fooProxy = new Proxy(foo, {apply: function(target, thisArg, argArray) {console.log("對foo函數進行了apply調用");return target.apply(thisArg, argArray)},construct: function(target, argArray, newTarget) {console.log("對foo函數進行了new調用");return new target(...argArray)} }) fooProxy.apply({}, ['a','b']) new fooProxy('a','b')

十三、Reflect

  • Reflect也是ES6新增的一個API,它是一個對象,字面的意思是反射。
  • 那么這個Reflect有什么用呢?
    • 它主要提供了很多操作JavaScript對象的方法,有點像Object中操作對象的方法;
    • 比如Reflect.getPrototypeOf(target)類似于Object.getPrototypeOf();
    • 比如Reflect.defineProperty(target, propertyKey, attributes)類似于Object.defineProperty() ;
  • 如果我們有Object可以做這些操作,那么為什么還需要有Reflect這樣的新增對象呢?
    • 這是因為在早期的ECMA規范中沒有考慮到這種對 對象本身 的操作如何設計會更加規范,所以將這些API放到了Object上面;
    • 但是Object作為一個構造函數,這些操作實際上放到它身上并不合適;
    • 另外還包含一些類似于 in、delete操作符,讓JS看起來是會有一些奇怪的;
    • 所以在ES6中新增了Reflect,讓我們這些操作都集中到了Reflect對象上;
  • 那么Object和Reflect對象之間的API關系,可以參考MDN文檔: 比較 Reflect 和 Object 方法 - JavaScript | MDN (mozilla.org)

1.Reflect的基本使用

const obj = {name: 'tjx',age: 19 }const objProxy = new Proxy(obj, {get: function(target, key, reciver) {console.log("get");return Reflect.get(target, key)},set: function(target, key, newValue, receiver) {console.log("set");target[key] = newValue// target[key] = newValue 與通過Reflect.set的區別是:后者有返回布爾值,代表是設置成功const result = Reflect.set(target, key, newValue)if(result) {0} else {}} }) objProxy.name = 'dfs' console.log(objProxy.name);

2.Reflect的常見方法

  • Reflect.getPrototypeOf(target)
    • 類似于 Object.getPrototypeOf()。
  • Reflect.setPrototypeOf(target, prototype)
    • 設置對象原型的函數. 返回一個 Boolean, 如果更新成功,則返 回true。
  • Reflect.isExtensible(target)
    • 類似于 Object.isExtensible()
  • Reflect.preventExtensions(target)
    • 類似于 Object.preventExtensions()。返回一個Boolean。
  • Reflect.getOwnPropertyDescriptor(target, propertyKey)
    • 類似于 Object.getOwnPropertyDescriptor()。如果對象中存在 該屬性,則返回對應的屬性描述符, 否則返回 undefined.
  • Reflect.defineProperty(target, propertyKey, attributes)
    • 和 Object.defineProperty() 類似。如果設置成功就會返回 true
  • Reflect.ownKeys(target)
    • 返回一個包含所有自身屬性(不包含繼承屬性)的數組。(類似于 Object.keys(), 但不會受enumerable影響).
  • Reflect.has(target, propertyKey)
    • 判斷一個對象是否存在某個屬性,和 in 運算符 的功能完全相同。
  • Reflect.get(target, propertyKey[, receiver])
    • 獲取對象身上某個屬性的值,類似于 target[name]。
  • Reflect.set(target, propertyKey, value[, receiver])
    • 將值分配給屬性的函數。返回一個Boolean,如果更新成功,則返回true。
  • Reflect.deleteProperty(target, propertyKey)
    • 作為函數的delete操作符,相當于執行 delete target[name]。
  • Reflect.apply(target, thisArgument, argumentsList)
    • 對一個函數進行調用操作,同時可以傳入一個數組作為調用參數。和 Function.prototype.apply() 功能類似。
  • Reflect.construct(target, argumentsList[, newTarget])
    • 對構造函數進行 new 操作,相當于執行 new target(…args)。

3.Reflect中的construct

// 作用:創建的一個對象,但是這個對象的方式是另一個對象的方法 function Students(name, age) {this.name = namethis.age = age } function Teachers() {} // 執行Students函數中的內容,但是創建出的對象是Teacher對象 const teachers = Reflect.construct(Students, ['saf', 'sf'], Teachers) console.log(teachers); // Teachers { name: 'saf', age: 'sf' } console.log(teachers.__proto__ === Teachers.prototype); // true

4.receiver的作用

如果我們的源對象(obj)有setter、getter的訪問器屬性,那么可以通過receiver來改變里面的this;

const obj = {_name: 'ujx',get name() {return this._name // 傳遞了reveiver后這里的this指向objProxy},set name(newValue) {this._name = newValue} }const objProxy = new Proxy(obj, {get: function(target, key, receiver) {// reveiver 是創建出來的代理對象console.log("get方法別訪問---", key, receiver); return Reflect.get(target, key, receiver)},set: function(target, key, newValue, receiver) {console.log("set方法被訪問------",key);Reflect.set(target, key, newValue, receiver)} }) objProxy.name = 'ksafa' // 返回了兩次 set方法被調用---- 但是兩次key值不同,第一次為name,第二次為_name

ES7

1.數組includes方法

在ES7之前,如果我們想判斷一個數組中是否包含某個元素,需要通過 indexOf 獲取結果,并且判斷是否為 -1。

在ES7中,我們可以通過includes來判斷一個數組中是否包含一個指定的元素,根據情況,如果包含則返回 true, 否則返回false。

const arrays = ['aba', 'cag', 'aba', 'dca', NaN] if (arrays.indexOf('aba') !== -1) {console.log("包含aba"); // 包含aba }// ES7 console.log(arrays.includes('aba')); // true console.log(arrays.includes('aba', 3)); // false 第二個參數表示從第幾個開始查找是否包含該元素// includes與indexof的區別: indexOf不能查找NaN console.log(arrays.indexOf(NaN)); // -1 console.log(arrays.includes(NaN)); // true

2.指數運算符

const result = Math.pow(3,3) const result2 = 3 ** 3 console.log(result, result2); // 27 27

ES8

1. Object values

之前我們可以通過 Object.keys 獲取一個對象所有的key,在ES8中提供了 Object.values 來獲取所有的value值。

const obj = {name: 'tjx',age: 18 }console.log(Object.keys(obj)); // [ 'name', 'age' ] console.log(Object.values(obj)); // [ 'tjx', 18 ] // 用到非常少 console.log(Object.values(['abc', 'dxa', 'dsx'])); // [ 'abc', 'dxa', 'dsx' ] console.log(Object.values("abx")); // [ 'a', 'b', 'x' ]

2. Object entries

通過Object.entries 可以獲取到一個數組,數組中會存放可枚舉屬性的鍵值對數組。

const obj = {name: 'tjx',age: 18 }console.log(Object.entries(obj)); // [ [ 'name', 'tjx' ], [ 'age', 18 ] ] const objEntries = Object.entries(obj) objEntries.forEach(item => {console.log(item[0], item[1]); })console.log(Object.entries(['abc', 'sgc', 'aej'])); // [ [ '0', 'abc' ], [ '1', 'sgc' ], [ '2', 'aej' ] ] console.log(Object.entries('adc')); // [ [ '0', 'a' ], [ '1', 'd' ], [ '2', 'c' ] ]

3.String Padding

ES8中增加了 padStart 和 padEnd 方法,分 別是對字符串的首尾進行填充的。

const message = "hello world"const newMessage = message.padStart(15, '*').padEnd(20, '-') console.log(newMessage); // ****hello world-----// 案例:銀行卡位數的隱藏 const cardNumber = "52208420390323232" const lastFourCard = cardNumber.slice(-4) const finalCard = lastFourCard.padStart(cardNumber.length, '*') console.log(finalCard); // *************3232

4.Trailing Commas

在ES8中,我們允許在函數定義和調用時多加一個逗號。

function foo(a,b,) {console.log(a,b); } foo(10,20,)

5.Object Descriptors

n ES8中增加了另一個對對象的操作是 Object.getOwnPropertyDescriptors

ES9

一、迭代器iterators

二、promise的finally

ES10

1.flat與flatMap

(1)flat

flat() 方法會按照一個可指定的深度遞歸遍歷數組,并將所有元素與遍歷到的子數組中的元素合并為一個新數組返 回。

(2)flatMap

flatMap() 方法首先使用映射函數映射每個元素,然后將結果壓縮成一個新數組。

即:先進行map操作,再進行flat操作。

// 1.flat的使用 const nums = [10, 20, [2, 3], 90, [1, 4, [2, 4]], 90] const newNums = nums.flat() console.log(newNums); // 默認進行一次降維 [ 10, 20, 2, 3, 90, 1, 4, [ 2, 4 ], 90 ] const newNums2 = nums.flat(2) // 進行兩次降維 console.log(newNums2); // [ 10, 20, 2, 3, 90, 1, 4, 2, 4, 90 ]// 2.flatMap的使用 const nums2 = [10, 38, 40] const newNums3 = nums2.flatMap(item => {return item * 2 }) const newNums4 = nums2.map(item => {return item * 2 }) console.log(newNums3); // [ 20, 76, 80 ] console.log(newNums4); // [ 20, 76, 80 ]// 3.flatMap的應用 const messaes = ['hello world', 'hello lyh', 'my name is loc'] const words = messaes.flatMap(item => {return item.split(' ') }) console.log(words); // 輸出如下:// [// 'hello', 'world',// 'hello', 'lyh',// 'my', 'name',// 'is', 'loc'// ] const words2 = messaes.map(item => {return item.split(' ') }) console.log(words2); // 輸出如下:// [// [ 'hello', 'world' ],// [ 'hello', 'lyh' ],// [ 'my', 'name', 'is', 'loc' ]// ] // 區別:flatMap是先進行map操作,再進行flat操作

2.entries轉對象

const obj = {name: 'tjx',age: 19,height: 1.88 } const entries = Object.entries(obj) console.log(entries); // [ [ 'name', 'tjx' ], [ 'age', 19 ], [ 'height', 1.88 ] ] // 傳統方法 const newObj1 = {} for (const entry of entries) {newObj1[entry[0]] = entry[1] } console.log(newObj1); // { name: 'tjx', age: 19, height: 1.88 } // 使用ES10新增方法 const newObj2 = Object.fromEntries(entries) console.log(newObj2); // { name: 'tjx', age: 19, height: 1.88 } console.log("((((((((("); // 應用 const queryString = 'name=tjx&age=19&height=1.88' const queryParams = new URLSearchParams(queryString) console.log(queryParams); // URLSearchParams { 'name' => 'tjx', 'age' => '19', 'height' => '1.88' } for (const param of queryParams) {console.log(param); // 輸出如下:// [ 'name', 'tjx' ]// [ 'age', '19' ]// [ 'height', '1.88' ] } const paramObj = Object.fromEntries(queryParams) console.log(paramObj); // { name: 'tjx', age: '19', height: '1.88' }

3.trimStart與trimEnd

trimStart 去除字符串前面的空格,trimEnd去除字符串后面的空格。

4. Symbol description

5. Optional catch binding

ES11

1.BigInt

數據類型BigInt,用于表示大的整數

const maxInt = Number.MAX_SAFE_INTEGER console.log(maxInt); // 9007199254740991const bigInt = 9007199254740991100n; // 使用n表示BigInt // console.log(bigInt + 10); // 報錯,只能同類型運算 console.log(bigInt + 10n); // 9007199254740991110nconst num = 100 console.log(bigInt + BigInt(num)); // 9007199254740991000const smallNum = Number(bigInt) console.log(smallNum); // 9007199254740991000

2.空值合并運算符

const fooa = '' const result1 = fooa || '默認值' const result2 = fooa ?? '默認值' console.log(result1); // 默認值 console.log(result2); // '' // 作用:有時為了那個值就是空字符串,使用 || 會出現不想要的錯誤,所以使用 ??

3.可選鏈

可選鏈也是ES11中新增一個特性,主要作用是讓我們的代碼在進行nullundefined判斷時更加清晰和簡潔

const obj = {friend: {girlFriend: {name: 'luck'}} } // 傳統方式需要一個一個判斷 if (obj.friend && obj.friend.girlFriend) {console.log(obj.friend.girlFriend.name); } // 可選鏈 console.log(obj.friend?.girlFriend?.name);

4.globalThis

瀏覽器中globalThis指向window,在node中globalThis指向node的全局變量。

ES12

1.FinalizationRegistry

FinalizationRegistry 對象可以讓你在對象被垃圾回收時請求一個回調。

FinalizationRegistry 提供了這樣的一種方法:當一個在注冊表中注冊的對象被回收時,請求在某個時間點上調 用一個清理回調。(清理回調有時被稱為 finalizer ); 你可以通過調用register方法,注冊任何你想要清理回調的對象,傳入該對象和所含的值;

let objp = {name: 'tjx' } const registry = new FinalizationRegistry(value => {console.log("對象被銷毀了", value); }) registry.register(objp, 'obj')objp = null

2.WeakRefs

如果我們默認將一個對象賦值給另外一個引用,那么這個引用是一個強引用: 如果我們希望是一個弱引用的話,可以使用WeakRef

let obj = { name: 'tjx'} let inof = new WeakRef(obj)

總結

以上是生活随笔為你收集整理的ES6-ES12的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。