function makeIterator(array){ var nextIndex = 0; return { next: function(){ return nextIndex < array.length ? {value: array[nextIndex++],done:false} : {value: undefined, done: true}; } } } var it = makeIterator(['a','b']); it.next(); // {value: "a", done: false} it.next(); // {value: "b", done: true} it.next(); // {value: undefined, done: true}
// 建立getJSON方法 var getJSON = function (url) { var promise = new Promise(function(resolve,reject){ var client = new XMLHttpRequest() || new ActiveXObject('Microsoft.XMLHTTP'); client.open('GET',url); client.onreadystatechange = handler; client.responseType = 'json'; client.setRequestHeader('Accept','application/json'); client.send(); function handler() { if(this.readyState===4) { if(this.status ===200) { resolve(this.response); }else { reject(new Error(this.statusText)); } } } }) return promise; } // 調用方法 getJSON('https://www.qinghuo.ltd:8888').then(function(json){ console.log('後臺返回數據'+json); },function(err){ console.log('訪問出錯'+err); })
let x = 1; let y = 2; [x,y] = [y,x]; //上面的代碼交換變量x和y的值,這樣的寫法不只簡潔,並且易讀,語義很是清晰.
// 返回一個數組 function example() { return [1,2,3]; } let [a,b,c] = example(); // 返回一個對象 function example() { return { foo: 1, bar: 2 } } let {foo,bar} = example();
// 解構賦值能夠方便的將一組參數和變量名對應起來 // 參數是一組有次序的值 function f([x,y,z]) {...} f([1,2,3]); // 參數是一組無次序的值 function f({x,y,z}) {...} f({z:3,y:2,x:1});
// 解構賦值對提取JSON對象中的數據尤爲有用 let jsonData = { id: 42, status: "OK", data: [876, 534] }; let {id,status,data:number} = jsonData; console.log(id,status,number); // 42,"OK",[876, 534]
JQuery.ajax = function (url, { async = true, beforeSend = function () {}, catch = true, complete = function () {}, crossDomain = false, global = true, // ... more config }) { // ... do stuff }; // 指定參數的默認值,這樣就避免了在函數體內部再寫 var foo = config.foo || 'default foo';這樣的語句.
// 任何部署了iterator接口的對象均可以用for...of循環遍歷.Map結構原生支持Iterator接口,配合變量的解構賦值獲取鍵名和鍵值就很是方便. var map = new Map(); map.set('first','hello'); map.set('second','world'); for(let [key,value] of map) { console.log(key + 'is' + value); } // first is hello // second is world // 若是隻想獲取鍵名,或者只想獲取鍵值,能夠寫成下面這樣 // 獲取鍵名 for(let [key] of map) {...} // 獲取鍵值 for(let [,value] of map) {...}
// 加載模塊時,每每須要指定輸入的方法.解構賦值使輸入語句很是清晰 const {SourceMapConsumer, SourceNode} = require("source-map");
// 案例: var s = 'hello world!'; console.log(s.indexOf('e')) // 1 console.log(s.includes('e')) // true console.log(s.startsWith('h')) // true console.log(s.endsWith('!')) // true
遞歸很是消耗內存,由於須要同時保存成百上千的調用幀,很容易發生"棧溢出"錯誤(stack overflow).但對於尾遞歸來講,因爲只存在一個調用幀,因此永遠不會發生"棧溢出"錯誤
// 正常遞歸調用,求階乘 function factorial(n) { if(n===1) { return 1; }else { return n*factorial(n-1); } } factorial(5) // 120 // 尾遞歸調用 function factorial(n,total) { if(n===1) { return total; }else { return factorial(n-1,n*total); } } factorial(5,1) // 120 //上面的代碼是一個階乘函數,計算n的階乘,最多須要保存n個調用記錄,複雜度爲O(n).若是改爲成爲尾遞歸,值保留一個調用記錄,則複雜度爲O(1). //正常的斐波那契數列 function Fibonacci (n) { if(n<=2) { return 1; }else { return Fibonacci (n-1) + Fibonacci (n-2); } } Fibonacci (10) // 89 Fibonacci (100) // 堆棧溢出 Fibonacci (500) // 堆棧溢出 // 尾遞歸優化的斐波那契數列 function Fibonacci2 (n, ac1 = 0, ac2 = 1) { if(n<=1) { return ac2; }else { return Fibonacci2 (n-1, ac2, ac1+ ac2) } } Fibonacci2 (100) // 5731478440138430000 Fibonacci2 (1000) // 7.022033e+208 Fibonacci2 (10000) // Infinity
for...in循環遍歷對象自身和繼承的可枚舉屬性(不包含Symbol屬性)
Object.keys返回一個數組,包括對象自身的(不包含繼承的)全部的可枚舉屬性(不包括Symbol屬性)
Object.getOwnPropertyNames返回一個數組,包含對象自身的全部屬性(不包含Symbol屬性,但包含不可枚舉屬性)
Object.getOwnPropertySymbols返回一個數組,包含對象自身的全部Symbol屬性
Reflect.ownKeys返回一個數組,包含對象自身的全部屬性,無論屬性名是Symbol仍是字符串,也無論是否可枚舉.
以上5種方法遍歷對象屬性時都遵照一樣的屬性遍歷次序規則ajax
- 首先遍歷全部屬性名爲數值的屬性,按照數字排序.
- 其次遍歷全部屬性名爲字符串的屬性,按照生成時間排序.
- 最後遍歷全部屬性名爲Symbol值得屬性,按照生成時間排序.
舉例:Reflect.ownKeys({[Symbol()]:0,b:0,10:0,2:0,a:0}) // ['2','10','b','a',Symbol()]
Iterator的做用有3個:一是爲各類數據結構提供一個統一的,簡便的訪問接口; 二是使得數據結構的成員可以按照某種次序排列; 三是ES6創造了一種新的遍歷命令--for of循環,Iterator接口主要供for of消費
1.建立一個指針對象,指向當前數據結構的起始位置.也就是說,遍歷器對象本質上就是一個指針對象. 2.第一次調用指針對象的next方法,能夠將指針指向數據結構的第一個成員. 3.第二次調用指針對象的next方法,指針指向數據結構的第二個成員. 4.不斷調用指針對象的next方法,直到它指向數據結構的結束位置.