1.模拟next方法返回值的例子
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}
2.用Promise对象实现AJAX操作
// 创建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);
})
3.变量的解构赋值的用途
交换变量的值
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数据
// 解构赋值对提取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';这样的语句.
遍历Map结构
// 任何部署了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");
4.确定一个字符串是否包含在另一个字符串中的四种方法
indexOf() : 返回Number,表示该值在字符串中的索引,未找到,则返回-1
includes() : 返回布尔值,表示是否找到参数字符串
startsWith() : 返回布尔值,表示参数字符串是否在源字符串的头部
endsWith() : 返回布尔值,表示参数字符串是否在源字符串的尾部
// 案例:
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
5.尾递归
递归非常消耗内存,因为需要同时保存成百上千的调用帧,很容易发生"栈溢出"错误(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
6.属性的遍历
for in
for...in循环遍历对象自身和继承的可枚举属性(不包含Symbol属性)
Object.keys(obj)
Object.keys返回一个数组,包括对象自身的(不包含继承的)所有的可枚举属性(不包括Symbol属性)
Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不包含Symbol属性,但包含不可枚举属性)
Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有Symbol属性
Reflect.ownKeys(obj)
Reflect.ownKeys返回一个数组,包含对象自身的所有属性,不管属性名是Symbol还是字符串,也不管是否可枚举.
以上5种方法遍历对象属性时都遵守同样的属性遍历次序规则
- 首先遍历所有属性名为数值的属性,按照数字排序.
- 其次遍历所有属性名为字符串的属性,按照生成时间排序.
- 最后遍历所有属性名为Symbol值得属性,按照生成时间排序.
举例:Reflect.ownKeys({[Symbol()]:0,b:0,10:0,2:0,a:0}) // ['2','10','b','a',Symbol()]
7.Iterator的作用
Iterator的作用有3个:一是为各种数据结构提供一个统一的,简便的访问接口;
二是使得数据结构的成员能够按照某种次序排列;
三是ES6创造了一种新的遍历命令--for of循环,Iterator接口主要供for of消费
8.Iterator的遍历过程
1.创建一个指针对象,指向当前数据结构的起始位置.也就是说,遍历器对象本质上就是一个指针对象.
2.第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员.
3.第二次调用指针对象的next方法,指针指向数据结构的第二个成员.
4.不断调用指针对象的next方法,直到它指向数据结构的结束位置.
9.异步编程的5种方法
- 回调函数
- 事件监听
- 发布/订阅
- Promise对象
- Generator函数