摘自(阮一峰著)经典案例---持续更新中

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.确定一个字符串是否包含在另一个字符串中的四种方法

  1. indexOf() : 返回Number,表示该值在字符串中的索引,未找到,则返回-1

  2. includes() : 返回布尔值,表示是否找到参数字符串

  3. startsWith() : 返回布尔值,表示参数字符串是否在源字符串的头部

  4. 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函数

你可能感兴趣的:(es6,markdown)