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方法,直到它指向数据结构的结束位置.