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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

ES6学习笔记

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

ES6學習筆記

在學習ES6的過程中做的一些記錄,用于未來的快速回憶。

let&const

作用域的概念

  • ES6新增塊級作用域的概念(一個大括號括起來的部分就是一個塊作用域)
  • let與const用于在塊級作用域中聲明變量,該變量僅在當前塊級作用域有效
  • ES6強制啟用嚴格模式,變量未聲明不允許使用

如何使用let與const

  • let關鍵詞用于聲明變量
  • const關鍵詞用于聲明常量,聲明時必須賦值
  • let&const關鍵詞不能在同一個塊級作用域內重復聲明一個變量
  • const定義的基本類型常量不能被修改,但是引用類型常量內部的值能被修改,只要不改變常量的引用即可

解構賦值

ES6允許按照一定模式,從數組和對象中提取值,對變量進行賦值。

數組解構賦值

// 完全解構 //本質上這種寫法屬于‘模式匹配‘,只要等號兩邊的模式相同,左邊的變量就會被賦予對應的值 let [a,b,c] = [1,2,3]; // a=1,b=2,c=3 let [a,[b]] = [1, [2]]; // a=1,b=[2] let [,,a] = [1,2,3]; // a=3 let [d,...rest] = [1,2,3,4,5,6]; // d=1,rest=[2,3,4,5,6] // 解構不成功 // 如果解構不成功,變量的值就等于undefined let [x,y] = ['xy'] //x='xy',y=undefined // 不完全解構 let [i,j] = [1,2,3]; // i=1,j=2 //如果等號的右邊不是數組,或者說不是可遍歷的結構,那么將會報錯 let [a] = 1; // 這里會報錯:Uncaught TypeError: 1 is not iterable

默認值

解構賦值允許有默認值。

let [x,y='b'] = ['a']; console.log(y); //blet [x,y = 'b'] = ['a',undefined]; console.log(y); //b // 數組成員為undefined時,默認值仍會生效 // 因為在ES6內部使用嚴格相等運算符‘===‘,判斷一個位置是否有值, // 所以當一個數組成員嚴格等于undefined,默認值才會生效。let [x,y = 'b'] = ['a',null]; console.log(y); //null // 如果一個數組成員是null,默認值就不會生效,因為null不嚴格等于undefined

對象解構賦值

對象的解構與數組有一個重要的不同,數組的元素是按次序排列的,變量的取值由它的位置決定;而對象的屬性沒有次序,變量必須與屬性同名,才能取到正確的值

// 變量名與屬性名一致的情況下 let {foo,bar} = {foo : "aaa",bar : "bbb"} console.log(foo); //aaa console.log(bar); //bbb // 實際上 對象的解構賦值是以這樣的形式簡寫的 let {foo : foo ,bar : bar} = {foo : "aaa",bar : "bbb"} // 變量名與屬性名不一致的情況下,必須這樣寫 let {a : name, b : age} = {a : 'zhangsan', b : 33}; console.log(name); //zhangsan console.log(age); //33

對象的解構賦值的內部機制,是先找到同名屬性,然后再賦值給對應的變量,真正被賦值的是后者,而不是前者,第一個foo/bar 是匹配的模式,對應的foo/bar屬性值才是變量,真正被賦值的是屬性值(也就是第二個foo/bar)。

字符串解構賦值

const [a,b,c,d,e] = 'hello'; console.log(a); //h console.log(b); //e console.log(c); //l console.log(d); //l console.log(e); //olet { length : len} = 'yahooa'; console.log(len); //類似數組的對象都有一個length屬性,還可以對這個屬性解構賦值

布爾值/數值解構賦值

解構賦值時,如果等號右邊是數值和布爾值,則會先轉為對象,但是等號右邊為undefined 和 null時無法轉為對象,所以對他們進行解構賦值時,都會報錯。

let {prop : x } = undefined; console.log(x); //報錯:Uncaught TypeError: Cannot destructure property `prop` of 'undefined' or 'null'

函數參數解構賦值

function move({x = 0,y = 0} = { }){return [x,y];} console.log(move({x : 3,y : 4})); //[3,4] console.log(move({x : 3})); //[3,0] console.log(move({})); //[0,0] console.log(move()); //[0,0] // move()的參數是一個對象,通過對這個對象進行解構,得到變量x、y的值,如果解構失敗,x和y 等于默認值 function move2({x,y} = {x : 1, y : 2 }){return [x,y]; } console.log(move2({x : 6,y : 8})); //[6,8] console.log(move2({})); //[undefined,undefined] console.log(move2()); //[1,2] // move2() 是為函數move的參數指定默認值,而不是為變量x和y指定默認值, // 所以與前一種寫法的結果不太一樣,undefined 就會觸發函數的默認值

解構作用

  • 改變變量的值

    let x = 1; let y = 2; [x,y] = [y,x]; // x=2, y=1
  • 從方法返回多個值

    function example(){return {foo : 'a',bar : 'b'} } let {foo,bar} = example(); // foo='a',bar='b' function example222(){return [1,2,3,4,5]; } let [a,,...b] = example222(); // a=1, b=[3,4,5]
  • 函數參數的定義

    //參數是一組有次序的值 function example([x,y,z]){return x + y + z; } example([1,2,3]) console.log(example([1,2,3])); //6 //參數是一組無次序的值 function f({x,y,z}){return x + y + z; } f({x : 'a', z : 'b', y : 'c' }); console.log(f({x : 'a', z : 'b', y : 'c' })); //acb
  • 提取JSON數據
  • 函數參數的默認值
  • 輸入模塊的指定用法

正則擴展

構造函數的變化

// ES5 的方式 let reg = new RegExp('xyz', 'i'); let reg2 = new RegExp(/xyz/i); reg.test('xyz123'); // true reg.test('xyz123'); // true // ES6 方式的變化,可以有第二個參數用作修飾符 // 這種方式,第二個參數的修飾符會覆蓋第一個正則表達式的修飾符 let reg3 = new RegExp(/xyz/ig, 'i') reg3.flags // i

u修飾符

// u -> unicode,用于處理unicode編碼的正則匹配 // unicode中4個字節 = 一個字母 /^\uD83D/.test('\uD83D\uDC2A'); // true \uD83D\uDC2A 被當做兩個字母來處理 /^\uD83D/u.test('\uD83D\uDC2A'); // false,\uD83D\uDC2A 被當作一個字母來處理 // 正則中,大括號里面若是unicode編碼,需添加u修飾符才能被識別 /\u{61}/.test('a'); // false /\u{61}/u.test('a'); // true // 用'.'操作符識別大于兩個字節的字符需要加上u修飾符 // '.'操作符不能處理換行符/回車符/行分隔符/段分隔符 /^.$/.test('吉'); // false /^.$/u.test('吉'); // true /吉{2}/.test('吉吉'); // false /吉{2}/u.test('吉吉'); // true // 凡是超過兩個字節的匹配都需要添加 u 修飾符

y修飾符

let s = 'bbb_bb_b'; let a1 = /b+/g; let a2 = /b+/y; a1.exec(s); // g修飾符全局匹配,不強調從下一個字符開始匹配,只要接下來的字符能匹配成功就ok a2.exec(s); // y修飾符全局匹配,必須緊跟著下一個字符開始匹配 // sticky屬性用于判斷是否開啟了y修飾符 a1.sticky; // false a2.sticky; // true

s修飾符

未實現,僅作為提案

// '.'操作符不能處理換行符/回車符/行分隔符/段分隔符 // 但添加 s 修飾符就可以

字符串擴展

Unicode表示法

console.log(`\u0061`); // a console.log(`\u20887`); // []7,會將20087拆成2008 / 7 console.log(`\u{20887}`); // ?, 大括號括起來后,將作為一個字符處理// 每兩個字節為一個單位長度 // ES5 不能很好的處理長度超過兩個字節的字符 let s = '?'; s.length; // 2 'a'.length; // 1 s.codePointAt(0); // 可以很好的處理長度超過兩個字節的字符的碼值,將字符轉為碼值 String.fromCodePoint("0x20087"); // 將碼值轉為字符

遍歷接口

let str "\u{20bb7}abc"; // ES5的遍歷方式,不能很好的處理長度超過兩個字節的字符 for(let i=0; i<str.length; i++) {console.log(str[i]); } // 新的遍歷接口,可以自動處理任何字符 for (let code of str) {console.log(code); }

模板字符串

let name = 'list'; let info = 'hello world'; let meg = `This is ${name}, ${info}`; console.log(meg);

數值擴展

新增方法

Number.isFinite(); // 判斷是否為有窮數 Number.isNaN(); // 判斷是否不是數字 Number.isInteger(); // 判斷是否為整數 , 25/25.0均為true,25.1為false,參數必須為數值 Number.MAX_SAFE_INTEGER // 數的上限,ES5 Number.MAX_SAFE_INTEGER // 數的下限,ES5 Number.isSafeInteger(); // 判斷一個數是否在有效范圍內 Math.trunc(); // 取整數部分 Math.sign(); // 正數返回1,負數返回-1,0返回0 Math.cbrt(); // 求立方根 // 還補充了三角函數方法、對數方法

方法調整

將ES5中某些全局方法移到對象下面,如parseInt()由全局移動到Number對象。

數組擴展(新增特性)

Array.from

// 從類數組中創建數組 // 如頁面中有一堆 p 標簽 let p = document.querySelectorAll('p'); let pArr = Array.from(p); // 此時,將集合p轉為了數組pArr// 將數組中的元素按照function的規則處理后并返回一個數組 Array.from([1,3,5], function(item){return item*2}); // [1,6,10]

Array.of

let arr = Array.of(1,2,3,4,5); // arr=[1,2,3,4,5] let emptyArr = Array.of(); // emptyArr=[]\

copyWithin

let arr = [1,2,3,4,5].copyWithin(0, 3, 5); // arr = [4, 5, 3, 4, 5] // 將起始位置3到終止位置5的元素覆蓋掉從0開始的元素(不包括下標為5的元素) let arr2 = [1,2,3,4,5].copyWithin(0, 1, 5); // arr2 = [2, 3, 4, 5, 5];

find/findIndex

let val = [1,2,3,4,5,6].find(function(item){return item>3}); // val = 4 // find找到一個符合條件的元素就結束,并返回該元素的值 let index = [1,2,3,4,5,6].findIndex(function(item){return item>3}); // index = 3 // findIndex找到一個符合條件的元素就結束,并返回該元素的下標

fill

let arr = [1,'a',undefined]; arr.fill(6); // arr=[6,6,6] // 將起始位置1到終止位置3的元素替換成5(不包括下標為3的位置) arr.fill(5,1,3); // arr=[6,5,5]

entries/keys/values

for (let index of [1,2,3].keys()){console.log(index); // 0,1,2 } for (let value of [1,2,3].values()){console.log(value); // 1,2,3 } for (let [index,value] of [1,2,3].entries()){console.log(index, value); // 0,1;1,2; 2,3 }

includes

let a = [1,2,NaN].includes(1); // a = true let b = [1,2,NaN].includes(NaN); // b = true

函數擴展

參數默認值

// 有默認值的參數右邊的參數都需要有默認值 function test(x, y='hello world') {console.log("默認值:", x, y); } test('hhh'); // 觸發默認值 test('hhh', 'aaa'); // 不觸發默認值 // 默認參數的作用域 let x = "test"; function test(x, y=x) {console.log(x, y); } function test2(c, y=x) {console.log(x, y); } test("hhh"); // hhh hhh test2("hhh"); // hhh test // 采用這種方式傳遞默認值時,要注意等號右邊變量的作用域 // 等號右邊的變量的值與最近定義的同名變量的值相同

rest參數

// rest參數后不能有其他參數 function test3(...arg) {for(let v of arg) {console.log('rest:', v)} }

擴展運算符

// 擴展運算符會將解構數據 console.log(...[1,2,3]); // 1;2;3 console.log("a", ...[1,2,3]); // a;1;2;3

箭頭函數

// 單個參數時可以不使用括號,多個參數時需要使用括號將其括起來 // 函數體有多個語句時,使用大括號括起來 let arrow = v => v*2; arrow(3); // 6let arrow2 = () => 5; arrow2(); // 5

尾調用

// 函數內部的最后一句是另一個函數 // 尾調用可以提升JS的性能 // 下面例子中,fx()就實現了尾調用 function tail(x) {console.log(x); } function fx(x) {return tail(x); } fx(123); // 123

對象擴展(新增特性)

簡潔表示法

// 當對象中的屬性名與變量名相同時,可以只寫一個 // 對象里面有方法,在ES6中可以省略function關鍵字 let o = 1; let k = 2; let obj = {o,k,hello () {console.log('hhh');} }

屬性表達式

// ES5中,對象中的key是固定的 // ES6中,key是可以用表達式或者變量的 let a = 'b'; let es5_obj = { // {a:c}a: 'c' } let es6_obj = { // {b:c}[a]: 'c' }

擴展運算符(ES7提案)

// 不建議使用,支持不好 let {a,b,...c} = {a:'1', b:'2', c:'3', d:'5'}; // a = 1 // b = 2 // c = {c:'3', d: '5'}

Object新增方法

Object.is('abc', 'abc'); // 與===的功能相同 Object.assign({a:'1'}, {b:'2'}); // 將第二個對象的內容追加到第一個對象里,淺拷貝 // 只拷貝自身的數據,不拷貝繼承的屬性以及不可枚舉的屬性// 遍歷對象 let obj = {a:'1', b:'2'}; for(let [key, value] of Object.entries(test)) {console.log([key, value]); }

Symbol

Symbol概念

這種數據類型提供一個獨一無二的值。

Symbol的作用

  • 聲明

    // 方法1 let a1 = Symbol(); let a2 = Symbol(); console.log(a1 === a2); // false // 方法2 // 在生成a3前,會檢查‘a3’在全局是否存在 // 若存在,則為取值 // 若不存在,則為生成一個新的Symbol let a3 = Symbol.for('a3')
  • 作用

    // 可用于處理對象里面的重名,防止沖突 let a1 = Symbol.for('abc');
[a1]: '123','abc': '5','c': '6'

}
// 常規循環只能處理非Symbol值
for(let [key, value] of Object.entries(obj)) {

console.log(key, value); // {abc:'5', c:'6'}

}
// 這種方式只能處理Symbol值
Object.getOwnPropertySymbol(obj).foreach(function(item) {

console.log(obj[item]); // 123

})
// 這種方式能夠處理以上兩種情況
Reflect.ownKeys(obj).foreach(function(item) {

console.log(obj[item]); // 123,5,6

})`

Map & Set 數據結構

Set

  • Set中的元素是不能重復的
  • Set可用于數組去重
  • Set里面不會自動數據類型轉換
let list = new Set(); list.add(5); // 5 list.add(6); // 5,6 list.size; // 2let arr = [1,2,3,4,5]; let list2 = new Set(arr); list2.size; // 5let list3 = new Set([2, '2']); // 2, '2'// 幾個Set常用方法 let set = new Set([1,2,3]); set.add(5); // 添加元素 set.has(2); // 判斷是否有某個元素 set.delete(3); // 刪除元素 set.clear(); // 清空Set// 遍歷Set let set2 = new Set([2, '2']); // 使用keys()與values()的效果一樣,因為Set中鍵值一致 // 不使用keys()、values(),直接遍歷Set也可以 // 也可以使用entries() for(let key of set2.keys()) {console.log(key); // 2, '2' } for(let value of set2.values()) {console.log(value); // 2, '2' } for(let val of set2) {console.log(val); // 2, '2' } for(let [key,value] of set2.values()) {console.log([key, value]); // 2, '2' }

WeakSet

  • WeakSet的元素只能是對象
  • WeakSet存儲的是弱引用,且不會檢測是否被垃圾回收機制回收
let weakList = new WeakSet(); let arg = {}; weakList.add(arg); // arg // WeakSet沒有clear方法、沒有size屬性、不能遍歷

Map

  • 任意數據類型都可以作為Map的數據類型
let map = new Map(); let arr = ['123']; map.set(arr, 123); // ['123']=>123 map.get(arr); // 123// Map可以接收一個二維數組作為參數 let map2 = new Map([['a',123],['b',456]]); console.log(map2); // 'a'=>123, 'b'=>456 map2.size; // 2 map2.delete('a'); // 'b'=>456 map2.clear(); // 清空Map

WeakMap

  • WeakMap的key只能是對象
  • WeakMap沒有clear方法、沒有size屬性、不能遍歷
  • WeakMap存儲的是弱引用,且不會檢測是否被垃圾回收機制回收
let weakMap = new WeakMap(); let arg = {}; weakMap.set(arg, 123); weakMap.get(arg); // 123

Map和Array的對比

let map = new Map(); let array = []; // add map.set('t', 1); // 't'=>1 array.push({t:1}); // {t:1} // query let map_exist = map.has('t'); // true let array_exist = array.find(item=>item.t); // {t:1} // modify map.set('t', 2); // 't' => 2 array.forEach(item => item.t?item.t=2:''); // {t:2} // delete map.delete('t'); let index = array.findIndex(item => item.t); array.splice(index, 1);

Set和Array的對比

let set = new Set(); let arr = []; // add set.add({t:1}); arr.push({t:1}); // query let set_exist = set.has({t:1}); // false,因為是不同的引用 let arr_exist = array.find(item=>item.t); // {t:1} // modify set.forEach(item => item.t?item.t=2:''); // 若直接add,則不能修改成功,因為引用不同 arr.forEach(item => item.t?item.t=2:''); // 這里遍歷是確保{t:1}存在 // delete set.forEach(item => item.t?delete(item):''); let index = array.findIndex(item => item.t); array.splice(index, 1);

Map、Set、Object的對比

let item = {t:1}; let map = new Map(); let set = new Set(); let obj = {}; // add map.set('t', 1); set.add(item); obj['t'] = 1; // query let map_exist = map.has('t'); let set_exist = set.has(item); let obj_exist = 't' in obj; // modify map.set('t', 2); item.t = 2; // 這里,set存儲的是引用,因此對對象的修改也會修改set里面對應的值 obj['t'] = 2; // delete map.delete('t'); set.selete(item); delete obj['t'];

Proxy與Reflect

Proxy的使用

// Proxy為代理,在用戶和對象之間設置代理,防止用戶直接操作對象 // 同時,可以在代理上做一些操作來修改查詢到的內容 // 或者限制用戶對某些屬性的修改行為 let obj = {time: '2018-11-21',name: 'net',_r: 123 }; let monitor = new Proxy(obj, {// 攔截對象屬性的讀取// 這里,當查詢的value中有2018字符串時將其替換成2019get (target, key) {return target[key].replace('2018', '2019'); // 將2018替換成2019},// 攔截對象屬性的修改// 這里只允許對name的修改set (target, key, value) {if(key === 'name') {return target[key] = value;} else {return target[key];}},// 攔截key in obj操作,限制暴露哪些屬性// 此處只允許判斷是否存在name這個key,對于其它key一律返回falsehas (target, key) {if (key === 'name') {return target[key];} else {return false;}},// 攔截delete// 這里只允許刪除以下劃線開頭的屬性deleteProperty (target, key) {if (key.indexOf('_') > -1) {delete target[key];return true;} else {return target[key];}},// 攔截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames// 這里將time屬性屬性過濾掉ownKeys (target) {return Object.keys(target).filter(item => item!='time')} }); monitor.time; // 2019-11-21 monitor.time = '2015-11-21'; // 2018-11-21 monitor.name = 'Chung'; // Chung 'name' in monitor; // true 'time' in monitor; // false

Reflect的使用

// 使用Reflect有以下好處 // 1.更加有用的返回值 // 2.函數操作,如判斷一個屬性是否在該obj里面, Reflect.has(obj, key) // 3.更加可靠的函數式執行方式 // 4.可變參數形式的構造函數 // 5.控制訪問器或者讀取器的this // Reflect用于代替直接操作對象 // 建議使用Reflect來操作對象 let obj = {time: '2018-11-21',name: 'net',_r: 123 }; Reflect.get(obj, 'time'); // 2018-11-21 Reflect.set(obj, 'name', 'Chung'); // name: 'Chung' Reflect.has(obj, 'name'); // true

使用場景

// 使用Proxy和Reflect實現解耦的數據校驗 function validator (target, validator) {return new Proxy(target, {_validator: validator,set (target, key, value, proxy) {if (target.hasOwnProperty(key)) {let val = this._validator[key];if(!!val(value)) {return Reflect.set(target, key, value, proxy);} else {throw Error(`Can not set ${key} to ${value}!`);}} else {throw Error(`${key} not exist!`)}}}) }const personValidator = {name (val) {return typeof val === 'string';},age (val) {return typeof val === 'number' && val > 18;} }class Person {constructor (name, age) {this.name = name;this.age = age;return validator(this, personValidator)} }const person = new Person('hh', 18); console.info(person); // {name: 'hh', age: '18'} person.name = 20; // 不能設置為20,因為 personValidator 限制name的值只能是string

類和對象

基本定義和生成實例

// 定義類 class Person {constructor (name='Jarry') {this.name = name;} } // 生成實例 let person = new Person('Chung'); console.log(person); // Person {name: ‘Chung’}

繼承

// 定義類 class Person {constructor (name='Jarry') {this.name = name;} } // 使用extends繼承 class Student extends Person {constructor (name='Sunny') {super(name); // 將子類的參數傳遞給父類// 若子類有自己的屬性,則需要將自有屬性放在super()下面} } // 生成實例 let stu = new Student(); console.log(stu); // Student {name: 'Sunny'}

Getter 和 Setter

// 定義類 class Person {constructor (name='Jarry') {this.name = name;}// longName是屬性而不是方法get longName () {return 'Good ' + this.name;}set longName (value) {this.name = value;} } // 生成實例 let person = new Person(); person.longName; // 'Good Jarry' person.longName = 'Chung'; // 'Good Chung'

靜態屬性和靜態方法

// 定義類 class Person {constructor (name='Jarry') {this.name = name;}// 使用static關鍵字定義靜態方法static tell () {console.log('hello');} } // 定義完類后再定義靜態屬性 Person.age = '18';// 調用靜態方法,使用類名調用而非實例調用 Person.tell(); // 'hello' Person.age; // 18

Promise

  • Promise是異步編程的一種解決方案

Promise基本使用

// 以回調函數處理異步 let ajax = function(callback) {console.log('執行1');setTimeout(function() {callback && callback.call();}, 1000) } ajax(function() {console.log('Timeout One'); })// 以Promise處理異步 let ajax = function() {console.log("執行2");return new Promise(function(resolve, reject) {setTimeout(function() {resolve();}, 1000)}) } ajax().then(function() {console.log('Timeout Two'); }) // 上面的結果為: // 執行1 // 執行2 // Timeout One // Timeout Two

Promise使用場景

// 所有圖片加載完再添加到頁面 function loadImg(src) {return new Promise((resolve, reject) => {let img = document.createElement('img');img.src = src;img.onload = function () {resolve(img)}img.onerror = function () {reject(err)}}) }function showImgs(imgs) {imgs.forEach(function(img) {document.body.append(img)}) } // all 將多個promise當作一個,全部加載完后才執行resolve Promise.all([loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),loadImg('http://i4.buimg.com/567571/df1ef0720bea6833.png') ]).then(showImgs) // race, 數組中某一個執行完就馬上執行resolve Promise.race([loadImg('http://i4.buimg.com/567571/df1ef0720bea6832.png'),loadImg('http://i4.buimg.com/567571/df1ef0720bea6833.png') ]).then(showImgs)

Iterator

  • for...of本質上是使用Iterator接口
let arr = [1,2]; let map = arr[Symbol.iterator](); map.next(); // {value:1, done:false} map.next(); // {value:2, done:false} map.next(); // {value:undefined, done:true}// 為對象實現iterator接口并指定遍歷方式 let obj = {start: [1,2,3],end: [7,8,9],[Symbol.iterator] () {let seft = this;let index = 0;let arr = seft.start.concat(self.end);let len = arr.length;return {next () {if (index < len) {return {value: arr[index++],done: false}} else {return {value: arr[index++],done: true}}}}} }for(let key of obj) {console.log(key); // 1,2,3,7,8,9 }

Generator

Generator基本定義與使用

let tell = function* () {yield 'a';yield 'b';return 'c'; } let k = tell(); k.next(); // {value:'a', done:false} k.next(); // {value:'b', done:false} k.next(); // {value:'c', done:true} k.next(); // {value:'undefined', done:true}let obj = {}; obj[Symbol.iterator] = function* () {yield 1;yield 2;yield 3; } for(let value of obj) {console.log(value); // 1,2,3 }

實例

// 應用1:狀態機 // 假設某一事物只有三種狀態,該事物僅在這三種狀態中轉換 // 以下生成器使得state僅在A、B、C間轉換 let state = function* () {while(1) {yield 'A';yield 'B';yield 'C';} }// 應用2:限制抽獎次數 let draw = function(count) {// 此處為具體的抽獎邏輯console.log(`Remain ${count}`); }let residue = function* (count) {while (count>0) {count --;yield draw(count);} }// 應用3:長輪詢 let ajax = function* () {yield new Promise(function(resolve, reject) {setTimeout(() => {resolve({code:0});}, 200);}) }let pull = function() {let generator = ajax();let step = generator.next();step.value.then(function(val) {if(val.code !== 0) {setTimeout(() => {console.log('wait');pull();}, 1000);} else {console.log(val);}}) }pull();

Decorator

  • 修飾器是一個函數,用來修改類的類型
  • 第三方庫core-decorators提供了現成的修飾器
  • 解決了兩個問題

    • 不同類間共享方法
    • 編譯期對類和方法的行為進行改變
  • 參數

    • target - 目標類
    • name - 屬性
    • descriptor - 屬性描述符
// *修飾器特性在將來的ES版本可能會被移除 let readonly = function (target, name, descriptor) {descriptor.writable = false;return descriptor; }class Test{@readonlytime () {return '2018-11-21';} } let t = new Test(); t.time = function(){}; // 會報錯,因為修飾器不允許對該方法進行修改// 也可修飾整個類 let typename = function (target, name, descriptor) {target.myname = 'hello'; } @typename class Name{} console.log(Name.myname);// 實例:日志系統的埋點 let log = (type) => {return function (target, name, descriptor) {let src_method = descriptor.value;descriptor.value = (...arg) => {src_method.apply(target, arg);console.log(`log ${type}`);}} }class AD{@log('show')show () {console.info('ad is shown');}@@log('click')click () {console.log('ad is clicked')} }

總結

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

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