ECMAScript 6 学习总结

1.什么是ES6?

      简单的说 ES6 的第一个版本,在2015年6月发布了,正式名称就是《ECMAScript 2015标准》(简称 ES2015)在2016年6月,小幅修订的《ECMAScript 2016标准》(简称 ES2016)如期发布,2017年6月发布的新版本就是ES7。ES6 既是一个历史名词,也是一个泛指,含义是5.1版以后的 JavaScript 的下一代标准,涵盖了ES2015、ES2016、ES2017等等。

2.箭头函数 =>

会解析为 function(){}

eg. input.map(item => item+1);  解析完:

      input.map(function(item){

          item = item + 1;

      });

箭头函数的特征:

  • 代码简写
  • 箭头函数会捕获上下文的this对象,本身没有this对象
  • 箭头函数是匿名函数
function MyFun(){

this.a = 1;

setInterval(function growUp(){

//此处的this,growUp函数定义的内部的this, 不同于构造函数MyFun函数中的this

this.a ++; 

},1000);

}

var fun = new MyFun();

//要修改的话,我们往往会将构造函数的this指定到一个新增的变量中

//如果使用箭头函数,就会很方便:

function MyFun(){

this.a = 1;

setInterval(() => {

//此处的this正确的指向了构造函数MyFun

  this.a++;

},1000);

}
var fun = new MyFun();

3.let 和const命令

let定义的变量只在let命令所在的代码块内有效.

let不允许在相同作用域内重复声明,允许在块级作用域内声明函数, 声明类似于var,即会提升到全局作用域或函数作用域的头部。同时,函数声明还会提升到所在的块级作用域的头部。

{
  let a = 10;
  var b = 1;
}
console.log(a);  // ReferenceError: a is not defined.
console.log(b); // 1

for循环,就很适合使用let命令
for(let i = 0; i < 10; i++){}
    console.log(i);// ReferenceError: i is not defined
//循环的语句定义和循环体可以作为两个不同的作用域
for(let i = 0; i < 10; i++){
    let i = “abc”;
    console.log(i);
}
//所以会打印3个”abc”

const用来定义不可变的常量,不可变的常量名一般全大写。一旦声明,常量的值就不能改变。

eg. const PI = 3.14;

对于const来说,只声明不赋值,就会报错。const的作用域与let命令相同:只在声明所在的块级作用域内有效。

4.ES6 的解构赋值

(1)数组的解构赋值——右边如果不是数组则报错,并且在严格模式中,变量不能重复定义,否则会报异常。

let [x, y, z] = [1, 2, 3];
let [a, …b] = [1, 2, 3, 4];  ==> a = 1; b = [2, 3, 4];
let [x1, [y1, [z1, r]]] = [1, [2, [3]]]; r = undefined;  //对应不上的变量值为undefined

//解构赋值可以添加默认值,如果右边赋值不严格(===)等于undefined, 则默认值将不会生效。
let [h=1] = [undefined]; //h = 1;
let [h1=1] = [null]; //h1 = null;

//如果默认值是一个表达式,会懒赋值,就是在需要的时候才会去执行结果
function myFun(){
console.log(“come in”);
}
let [f = myFun()] = [1];

(2)对象的解构赋值

对象赋值可数组赋值的区别是:数组是按位置取值,值由位置来决定

而对象不一定顺序一致,只要变量名和属性名相同,便可以取值。

var {bar, liz} = {bar: ‘barValue’, liz1: ‘liz1Value’}; 
console.log(bar);//barValue
console.log(liz);//undefined   属性名不一致

var obj = {first:'hello',last:'world'};
var {first:fi,last:la} = obj;
console.log(fi);//hello
console.log(la);//world

//默认赋值,必须严格等于(===)undefined,默认值才会生效.如果解构失败,变量的值就等于undefined
var {lib = 1} = {lib: undefined};
var {lib1 = 2} = {lib1: null};
console.log(lib); //1
console.log(lib1); //null

(3)字符串的解构赋值 —其赋值规则类似于数组

const [a0, b0, c0, d0, e0] = “hello”;
console.log(a0);//h
console.log(b0);//e
console.log(c0);//l
console.log(d0);//l
console.log(e0);//o

//字符串有个属性length
const {length: len} = “hello”;
console.log(len); //5

(4)数值和布尔类型的解构赋值——等号右边不是对象,而是数值或者布尔值,则先转换为对象。

let {toString: x0} = 123;
console.log(x0);//[function:toString]
x0 === Number.prototype.toString;
let {toString:y0} = true;
console.log(y0);//[function:toString]
y0 === Boolean.prototype.toString;

//因为undefined和null不能转换为对象,所以会报异常
let {toString:z0} = undefined /null;
console.log(z0); //var z0 = undefined.toString;TypeError: Cannot read property 'toString' of undefined

(5)函数的参数解构赋值

function add([x, y]){
    return x+y;
}
console.log(add([1,2])); //3
console.log([[1,2],[3,4]].map(([a,b]) => a+b));//[3,7]

//函数参数默认值结构赋值,也是===undefined时,默认值有效
function myFun([x=1,y=2]){
  return x+y;
}
console.log(myFun([4,5]));//9
console.log(myFun({}));//error
console.log(myFun([5]));//7
console.log(myFun([null,null]));//0

变量解构赋值用处:

(1)交换值

eg. let [myx,myy] = [myy,myx];

(2)函数可以返回多个值(good)

eg. function mytest(){

        return [1,2,3];

      }

     let [m1,m2,m3] = mytest();

(3)函数可以返回多个对象

eg.  function mytest2(){

        return ({

           foo:1,

           foo1:2,

         })

      }

      let {foo, foo1} = mytest2();

      console.log(foo); //1

      console.log(foo1); //2

5.ES6的算术方法

ES6的二进制(0b/0B)和八进制(0o/0O)表示

Number(); //方法将其转换为10进制数值
console.log(Number(0b111));
console.log(Number(0o111));
NUmber.isFinite();//判断是否是非无穷
Number.isNaN();//检查是否是NaN
Number.parseInt();
Number.parseFloat();
Number.isInterger();

console.log(Number.isInterger(3));
console.log(Number.isInterger(3.0));

Number.EPSILON;//表示一个极小的变量 2.220446049250313e-16
//起作用来进行浮点数计算的误差判断,误差<Number.EPSILON 则计算结果正确
// js表示整数的范围是 -2^53 ~ 2^53
//ES6引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示这个范围的上下限。
Number.MAX_SAFE_INTEGER;
Number.MIN_SAFE_INTEGER;
isSafeInterger()//方法就是判断某个整数值是否落在上面的安全范围之间
Number.isSafeInterger();

//获取整数部分,对于空值和无法截取整数的值,返回NaN。
Math.trunc(4.1);//4
Math.trunc(4.9);//4
Math.trunc(-4.1);//-4
Math.trunc('NaN');//NaN
//来返回一个函数是正数(1),负数(-1),还是0(0),-0(-0),其他返回NaN
Math.sign(5);//1
Math.sign(-5);//-1
Math.sign(0);//0
Math.sign(-0);//-0
Math.sign("NaN");//NaN
//用来计算一个数的立方根
Math.cbrt();
//将一个整数用32位二进制来表示
Math.clz32();
//Math.imul方法返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位的带符号整数。
Math.imul(a,b);
//返回一个数的单精度浮点数形式
Math.fround();
//Math.hypot方法返回所有参数的平方和的平方根。
Math.hypot();

ES6新增了6个三角函数方法。
Math.sinh(x) //返回x的双曲正弦(hyperbolic sine)
Math.cosh(x) //返回x的双曲余弦(hyperbolic cosine)
Math.tanh(x) //返回x的双曲正切(hyperbolic tangent)
Math.asinh(x) //返回x的反双曲正弦(inverse hyperbolic sine)
Math.acosh(x) //返回x的反双曲余弦(inverse hyperbolic cosine)
Math.atanh(x) //返回x的反双曲正切(inverse hyperbolic tangent)

ES7新增了一个指数运算符(**)
b **= 3;//等同于 b = b * b * b;

 6.ES6数组方法

    Array.from();   ——将类似于数组的对象和可遍历的对象(明显特征就是有length属性)转为数组

let obj = {
  "0":"dtl",
  "1":18,
  "2":1234,
  length:5
}
var arr = Array.from(obj);
console.log(arr);  //["dtl",18,1234,undefined,undefined]

   Array.of();  ——将一组数转为数组,如果没有参数,返回一个空数组

  console.log(Array.of(3));//[1]

  

  copyWith(); ——方法用于将目标元素拷贝到指定位置,将代替指定位置target的元素

     Array.prototype.copyWithin(target,[start],[end]);  //target 必需元素,从start位置开始拷贝 :默认为0

 

//复制几个就从指定位置替换几个元素
console.log([1,2,3,4,5].copyWithin(0,3));//[4,5,3,4,5]
console.log([1,2,3,4,5].copyWithin(0,2));//[3,4,5,4,5]
console.log([1,2,3,4,5].copyWithin(0));//[1,2,3,4,5]

  find(); ——用于找回第一个符合条件的数组成员,回调函数的三个参数:1表示当前的值,2表示当前的位置,3表示当前的数组

  findIndex(); ——返回第一个符合条件的数组成员的位置

let b = [1,2,5,8,9].find(function(value,index,arr){
  return value > 7;
});
console.log(b);//8


let c = [1,2,5,8,9].findIndex(function(value,index,arr){
  return value > 7;
});
console.log(c);//3

  fill(value,start,end); ——使用给定值来填充一个数组 ,常用于数组的初始化。value表示填充的值,start填充的起始位置,end填充的结束位置(但不包括结束位置)

let myArr = new Array(3).fill(7, 0, 2);
console.log(myArr); //[7, 7, ]

  entries(),keys(),values(); ——来遍历数组

for (let index of ['a', 'b'].keys()) {
  console.log(index);
}
0
1

for (let elem of ['a', 'b'].values()) {
  console.log(elem);
}
'a'
'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  console.log(index, elem);
}
0 "a"
1 "b"

  includes(); ——返回数组是否包含某个值,true/false。没有includes之前我们通过indexOf()来判断,它有两个弊端:使用===判断,对NaN判断不准确,还有表达语义不够直观

 Es6明确将空位转为undefined。

copyWith()//会连空位一起拷贝

fill()//会将空位当正常数组对待

for...of //循环会遍历空位

entires(),keys(),values(),find(),findIndex()//都会将空处理成undefined

7.ES6 函数

函数参数赋默认值

//原来的方式给函数赋默认值
function add(x,y){
  y=y||'world';
console.log(x+' '+y);
}
add('hello',);
add('hello','china');
add('hello','');//hello world 将“”变成了默认值,所以给y赋值时先要判断又是否有值,因此原来的方式很麻烦

//新的方式给函数参数赋默认值
function newAdd(x,y = 'world'){
  console.log(x+' '+y);
}
newAdd('hello',);
newAdd('hello','');//hello

 

后续ES6 学习总结:

1.块级作用域和let ,const

let和const不会提升变量的声明

同名的变量或者常量在同一个作用域不能重复定义

在作用域内,在声明前操作let或const定义的变量或者常量,会抛出异常。 (临时死区 TDZ)

在循环中使用let和const每次迭代会创建新绑定(产生一个副本),所以可以获取到每次迭代的值

块级作用域绑定的最佳实践: 默认使用const 定义,除非需要修改变量值时,使用let, 这样在很大程度上就实现了代码的不可变,防止错误的产生。

 

2.String.codePointAt() 获取字符占用的编码单元数量

   String.fromCodePoint() 根据指定的码位生成一个字符串

   normalize() 字符串比较之前,现将其按照同一规则进行转换

   includes(), startWith(), endsWith()  返回结果为true/false, 都可以传入两个参数,第一个表示要搜索的字符,第二个参数可选表示开始检索的其实位置

   endsWith() 从字符串的末尾开始向前匹配

   repeat() 传入number类型的参数,表示字符串重复的次数

   正则表达式的flags属性会返回所有应用于但钱正则表达式的修饰字符串,source属性获取正则表达式的文本部分

   ES5中一直缺乏许多特性,如多行字符串、字符串格式化、HTML转义等。ES6通过模板字面量的方式进行了填补。模板字面量:用反撇号(``)替代单双引号,如果要在字符串中使用反撇号,用反斜杠(\)将其转义即可。字符串占位符${} 符号组合,中间可以包含任意的JavaScript表达式,可以是变量,运算式,函数等,也可以在模板字       面量里面嵌套另外一个。创建标签模板,标签函数接受模板字面量每个部分组成的参数数组,通过这些数据来组装出一个适合的字符串值。String.raw`Multiline\nstring` 获取原生字串-> Multiline\\nstring

 

3.ECMAScript 6 的函数

默认参数值arguments,在ECMAScript 5里非严格模式和严格模式不同:

function(first, second){

console.log(first === arguments[0]);

console.log(second === arguments[1]);

first = ‘c’;

second = ‘d’;

console.log(first === arguments[0]);

console.log(second === arguments[1]);

}

返回的结果为:

true

true

true

true

非严格模式下,参数的改变会同步到arguments对象中

 

下面再看下严格模式:

function(first, second){

“use strict”;

console.log(first === arguments[0]);

console.log(second === arguments[1]);

first = ‘c’;

second = ‘d’;

console.log(first === arguments[0]);

console.log(second === arguments[1]);

}

返回的结果为:

true 

true

false

false

严格模式下,无论参数如何变化,arguments 对象不再随之改变

ECMAScript 6 的函数,如果使用了默认值,则无论是否显式的定义了严格模式,arguments都保持和ECMAScript 5严格模式下保持一致

function(first, second=‘5’){

console.log(arguments.length);

console.log(first === arguments[0]);

console.log(second === arguments[1]);

first = ‘c’;

second = ‘d’;

console.log(first === arguments[0]);

console.log(second === arguments[1]);

}

返回结果为:

1

true

false

false

false

arguments.length的值为1,arguments[1]的值为undefined

 

函数的不定参数:在函数的命名参数前添加三个点(…)就表明这是一个不定参数,该参数为一个数组,包含自它传入后的所有参数。arguments 是返回了所有的参数,不定参数可以放心直接遍历。如果函数声明了不定参数,arguements对象包含了所有传入函数的参数。

函数的length 属性统计的是函数命名参数的数量,不算不定参数,所以不定参数的引入不会影响函数的length值。还有不定参数必须放在函数参数的末尾,否则会语法错误。    

 

展开运算符: 简化使用数组传参的过程。

let values = [10, 9, 0,5,6,20];

console.log(Math.max.apply(Math, values)); //ES5 通过apply实现

console.log(Math.max(…values));  //ES6中展开运算符很大程度可以代替apply 

 

Es6引入了new.target原属性,如果通过new 函数调用则new.target !== undefined,比如通过call,或者apply调用。

ES6引入了块级函数,来解决在ES6之前版本函数声明在不同浏览器下的不兼容性。

“use strict”;

if(s){

 console.log(typeof doSomething); // function

console.log(typeof doSomething1); // undefined

  function doSomething(){

 } //Es6的严格模式下,块级函数的声明会被提升到块级顶部

  let doSomething1 = function(){} // let定义的函数声明不会被提升

}

console.log(typeof doSomething); // undefined   在非严格模式下会提升至全局作用域

增加了name 属性,来返回函数的名称。

箭头函数

1.没有this,super, arguments, new.target的绑定,这些值由外围最近一层的非箭头函数决定。

2.不能通过new关键字调用

3.没有原型

4.不可改变this的绑定

5.不支持arguments对象

6.不支持重复的命名参数

 

let reflect = value => value;

let sum = (sum1, sum2) => sum1 + sum2;

let sum2 = (num1, num2) => {

return num1 + num2;

}

let getName = () => 'dtl';

let myFun = () => {} ; // 创建一个空函数

let getObj = id => ({id: id, name:'dd'}); //在函数外返回一个对象字面量,用小括号将字面量包裹起来

 

let person = ((name) => {

return {

    getName: function(){

        return name;

        }

    };

})('dtl'); //创建立即执行函数,小括号将箭头函数包裹,不包裹传参部分。

 

尾调用优化可以帮助函数保持一个更小的调用栈,从而减少内存的使用,避免栈溢出错误。在函数尾部,直接return 函数调用结果。引擎进行的自动优化。

function factorial(n, p = 1){

if(n <= 1){

return 1*p;

}else{

let result = n*p;

return factorial(n -1, result);  // 优于 return n*factorial(n -1);

}

}

 

4.扩展对象的功能性

对象字面量:

function createPerson(id, name){

return {  //当属性名与值名字相同,可以不用写冒号

    id,

        name,

    }

}

var person = {

id: '123',

  sayName(){   //消除了冒号和function关键字

    console.log(this.name);

    }

}

let lastName = "last name";

let person = {

"first name" : 'taoli',

    [lastName]: 'du', // 在对象字面量中使用[],表示该属性名是可以计算的,它的内容被求值并转换为一个字符串。

}

 

ES6 在全局Object上引入了新方法:

Object.is() 弥补全等运算符的不准确计算 +0 === -0 //true Object.is(+0, -0)//false   NaN === NaN //false Object.is(NaN, NaN) // true  除了这两个特例,剩下的基本和 === 返回结果一致

Object.assign() 接受一个接收对象和任意淑玲的源对象,最终返回接收对象。可以代替ES5中的maxin() 方法

ES6 清晰的定义了枚举类型的枚举顺序,先数字升序,再字母,按照插入的先后顺序排列。

Object.getPrototypeOf()

Object.setPrototypeOf(a, b) //改变a 的原型为 b 对象创建后,用此方法修改它的原型

 

super 便捷地访问原型对象原型  super 就是 Object.getPrototypeof(this)的值,使用super时,此时的this会被自动设置为当前作用域的this值。

 

5.解构:使数据访问更便捷

对象解构:根据对象字面量,读取相应的属性名称。注意,使用 var,let或const 解构声明变量时,必须提供初始化值。如果不适用解构赋值,只有const定义必须初始化。

数组解构:按顺序对应赋值,eg, let a =1;b=2; [a, b] = [b, a];实现两个数的交换。嵌套数组解构,不定元素解构,不定元素必须是数组的最后一个条目。

解构的混合应用: 对象解构和数组解构嵌套混合使用赋值。

在对象和解构赋值中,都可以为值为null/undefined的对象数组或数组元素指定默认值。

let node = {

type : 'identifier',

  name: 'foo',

  loc: {

    start: {

        line: 1,

          column: 1

        },

      end:{

      line: 1,

          column: 4

      }

    },

  range: [0, 3]

}

 

let {

loc: { start },

    range: [ startIndex ]

} = node;

 

console.log(start.line); //1

console.log(start.column); //1

console.log(startIndex);//0

 

6.Symbol和Symbol属性

ES6 为 JavaScript 引入了一种新的基本类型:Symbol,它由全局 Symbol() 函数创建,每次调用 Symbol()函数,都会返回一个唯一的 Symbol

所有可以计算属性名的地方都可以用Symbol。

Symbol 是 JavaScript 中的新原始类型。console.log(typeof symbol) //Symbol

let uid = Symbol.for(‘uid’);//Symbol.for() 创建之前会去全局Symbol注册表中搜索,如果有,就是用已建的,没有就创建新的Symbol

Symbol.keyFor(‘uid’) //‘uid’ /undefined Symbol.keyFor() 在Symbol全局注册表中检索与Symbol有关的键

Symbol不能和其他类型进行转换/强制转换,会报错

Object.getOwnProperty-Symbol() 来检索Symbol属性

Object.getOwnPropertySymbol() 返回Symbol自有属性数组

well-known Symbol定义了一些语言内部可用的功能,eg. Symbol.hasInstance 属性,需要再去查阅。

 

7.Set集合和Map集合

一般来说,Set集合常被用于检查对象中是否存在某个键名,而Map集合常被用于获取已存信息。

ES6中的Set集合: 是一种有序列表,其中含有一些相互独立的非重复值

let set = new Set();

set.add(5);

set.add(‘5’);

console.log(set.size); //2

set.add(5); //重复add的值,实际调用会被忽略

let set = new Set([1,2,3,4,5,5,5,5]); console.log(set.size);// 5  重复add的值,实际调用会被忽略

不会对所存值进行强制类型转换

let set = new Set(),

key1 = {},

key2 = {};

set.add(key1);

set.add(key2);

cosole.log(set.size); //2  ES6 中不会key1,key2强转为字符串,因此在set集合中是两个独立的元素,而在ES5中会被转换,则两者的值“[object object]”,实际是同一个属性值

set.has(5); // true  has()方法检测set集合中是否存在某个值

set.delete(5); //delete()方法移除Set集合中的某个元素

set.clear(); //clear()方法清除Set集合中的元素

Set集合和数组之间的转换:

let set = new Set([1,2,3,3,4,4,5]), //去掉了重复了值

array = […set]; //用展开运算符,很容易将set转换为array

console.log(array); //[1,2,3,4,5]

Weak set: 解决清除了对初始对象的引用,但Set集合缺保留着引用,而引起的一些内存泄漏问题。

创建Weak Set 集合:

let set = new WeakSet(),

key = {};

set.add(key);

key = null;

//console.log(set.has(key));// false

WeakSet 和Set的一些区别:

. 在weakSet的实例中,如果向 add(), has()和delete()这三个方法传入非对象参数都会导致程序出错。

.Weak Set 集合不可迭代,所以不能被用于for-of循环

.没有keys(),values()等任何迭代器,所以无法通过程序本身来检测其中的内容。

.不支持forEach()方法

.不支持size()属性

Map集合的初始化方法

let map = new Map([[‘name’, ‘dtl’], [‘age’, 18]]);

同样:map.set(key,value);

  map.delete(key);

map.clear(); //清除所有键值对

也可以用对象作为Map的key, 在对象中,是不能用对象作为对象的属性名。

let set = new Set([1, 2]);

forEach 方法都支持传入三个参数:

set.forEach(function(value, key, ownerset){  //set中的 value === key

  console.log(key + ' ' + value);

  console.log(ownerSet === set);

});

 

let map = new Map([['name', 'dtl'], ['age', 18]]);

map.forEach(function(value, key, ownerMap){

  console.log(key + ' ' + value);

  console.log(ownerMap === map);

});

WeakMap集合  支持 has(key), 和delete(key)方法判断和移除key,value.

如果只用对象作为key, WeakMap集合将是最好的选择,当数组再也不可访问后集合中存储的相关引用和数据会被自动回收。但是WeakMap不支持forEach(),size,clear()来管理元素,对用户的能见度较低。

如果使用费对象的kay,那就选择Map集合。   

Set 集合的值和Map集合的key 的等价性都是通过Object.is()来判断。如果相同,会高滤掉重复的值。

 

8.  ES6中的迭代器(Iterator)和生成器(Generator)

迭代器(Iterator): 迭代器是一种特殊对象,它具有一些专门为迭代过程设计的专有接口,所有的迭代器对象都有一个next()方法,每次调用都返回一个结果对象。结果对象有两个属性:一个是value,表示下一个将要返回的值;另一个是done,它是一个布尔类型的值,当没有更多可返回数据时返回true,如果没有相关数据则返回undefined 。迭代器还会保存一个内部指针,用来指向当前集合中值的位置,每调用一次next()方法,都会返回下一个可用的值。

生成器(Generator): 是来返回迭代器的函数。

function关键字后的星号(*)来表示,函数中会用到新的关键字yield。星号可以紧挨着function关键字,也可以在中间添加一个空格。

function *createGenerator(){

    yield 1;

    yield 2;

    yield 3;

}

// 生成器能像正规函数那样被调用,但会返回一个迭代器

let iterator = createIterator();

console.log(iterator.next().value); // 1

console.log(iterator.next().value); // 2

console.log(iterator.next().value); // 3

只会在调用迭代器的next()方法时,返回yield的值。并且yield只能在迭代器的主函数中有效,不能嵌套在语句里,会报错。(yield关键字只可在生成器内部使用,在其他地方使用会导致程序抛出错误)

生成器函数表达式,function与次奥括号之间添加一个* 号。

let createIterator = function *(items) {

    for (let i = 0; i < items.length; i++) {

        yield items[i];

    }

};

生成器对象方法:

var o = {

    *createIterator(items) {

            for (let i = 0; i < items.length; i++) {

                yield items[i];

            }

        }

};

let iterator = o.createIterator([1, 2, 3]);

 

可迭代对象具有Symbol.iterator属性,是一种与迭代器密切相关的对象。在ES6中,所有的集合对象(数组、Set集合及Map集合)和字符串都是可迭代对象,这些对象中都有默认的迭代器。

let values = [1, 2, 3];

let iterator = values[Symbol.iterator]();

console.log(iterator.next()); // "{ value: 1, done: false }"

console.log(iterator.next()); // "{ value: 2, done: false }"

console.log(iterator.next()); // "{ value: 3, done: false }"

console.log(iterator.next()); // "{ value: undefined, done: true }"

创建可迭代对象:

默认情况下,开发者定义的对象都是不可迭代对象,但如果给Symbol.iterator属性添加一个生成器,则可以将其变为可迭代对象。

let collection = {

    items: [],

    *[Symbol.iterator]() {

        for (let item of this.items) {

            yield item;

        }

    }

};

collection.items.push(1);

collection.items.push(2);

collection.items.push(3);

for (let x of collection) {

    //1

    //2

    //3

    console.log(x);

}

在数组字面量对此使用展开运算符,将可迭代对象的多个元素依次插入新数组中,替换原先展开运算符所在的位置。

let smallNumbers = [1, 2, 3],

bigNumbers = [100, 101, 102],

allNumbers = [0, ...smallNumbers, ...bigNumbers];

console.log(allNumbers.length); // 7

console.log(allNumbers); // [0, 1, 2, 3, 100, 101, 102]

 内建迭代器:

1.集合对象迭代器: 数组,Map集合,Set集合

内建了三种迭代器:

entries() 返回一个迭代器,其值为对个键值对

values() 返回一个迭代器,其值为集合的值

keys() 返回一个迭代器,其值为集合中的所有键名

let colors = [ "red", "green", "blue" ];

let tracking = new Set([1234, 5678, 9012]);

let data = new Map();

data.set("title", "Understanding ES6");

data.set("format", "ebook");

for (let entry of colors.entries()) {  

    console.log(entry);  //[0, red][1, green],[2,blue]

}

for (let entry of tracking.entries()) {

    console.log(entry); //[1234,1234] [5678, 5678] [9012, 9012]

}

for (let entry of data.entries()) {

    console.log(entry); //[“title”, “Understanding ES6”] [“format”,”ebook”]

}

for (let entry of colors.values()) {  

    console.log(entry);  //“red” “green” “blue”

}

for (let entry of tracking.values()) {

    console.log(entry); //“1234” “5678” “9012”

}

for (let entry of data.values()) {

    console.log(entry); //“Understanding ES6” ”ebook”

}

for (let entry of colors.keys()) {  

    console.log(entry);  //0 1 2

}

for (let entry of tracking.keys()) {

    console.log(entry); //1234 5678 9012

}

for (let entry of data.keys()) {

    console.log(entry); //“title” “format”

}

2.字符串迭代器 for of 循环输出正确的内容

3.NodeList迭代器 for of 循环输出正确的内容

 

9.类的访问器属性

let propertyName = “html”;

class CustomHtmlElement {

constructor(element) {

this.element = element;

}

get [propertyName] () { //用[] 包裹起来,就是可计算名称

return this.element.innerHTML;

}

set [propertyName] () {

return this.element.innerHTML = value;

}

}

 

类中的所有方法和访问器属性都可以添加static,除了构造函数之外。

不可在实例中访问静态成员,必须要在类中访问静态成员。

继承和派生类:

class Rectangle

class Square extends  Rectangle 

使用super()可访问基类的构造函数,需注意以下几点:

1.只可在派生类(extends 声明的类)的构造函数中使用super()

2.在构造函数访问this之前一定要调用super()

3.如果不想调用super(),则唯一的方法就是让类的构造函数返回一个对象

 

10.改进的数组功能

ES6 增加了Array.of() 和Array.from() 方法

查找数组中匹配的元素:

find() 返回查到的值

findIndex() 返回查到值的索引

查找与某个值匹配的元素:

indexOf()和lastIndexOf()

fill()用指定的值填充数组中一到多个元素

eg.  let number = [1,2,3,4];

number.fill(1);

Console.log(numbers.toString()); //1,1,1,1

let number = [1,2,3,4];

number.fill(1,2);

Console.log(number.toString());//1,2,1,1  从索引2开始填充元素,到number.length结束

number.fill(0,1,3);

console.log(numbers.toString()); //1,0,0,1  索引1和2的元素填充0

copyWithin(a, b, [c]) 方法 a:开始填充值的索引位置 b:开始复制值的索引位置 [c]:到该索引停止赋值

eg. Let numbers = [1, 2, 3, 4]; numbers.copyWithin(2, 0); console.log(numbers.toString());// 1,2,1,2

numbers.copyWithin(2, 0, 1); //1,2,1,4 

了解定型数组

 

11.Promise 与异步编程

promise的生命周期: pending(进行中), fulfilled(已完成),rejected(已拒绝)

Promise.resolve() 

Promise.reject()

Promise 链操作,并且传递返回值给下一个promise, 看下面的例子:

let p1 = new Promise(function(resolve, reject){

resolve(42);

});

p1.then(function(value){

console.log(value);// 42

return value+1;

}).then(function(value){

console.log(value); //43

})

 

也可以返回promise对象,在一个promise执行成功后,创建另一个promise,然后调用

let p1 = new Promise(function(resolve,reject){

resolve(42);

});

 

P1.then(function(value){

console.log(value); //42

 

let p2 = new Promise(function(resolve, reject){

resolve(43);

})

return p2;

}).then(function(value){

console.log(value);//43

})

 

直到p2处理完成后,才处理第二个处理程序

 

响应多个Promise

Promise.all() 方法 只接受一个参数,并且返回一个Promise,该参数是一个含有多个受监视的promise可迭代对象,只有可迭代对象中的promise全部处理完成,最后的promise才会执行

let p1 = new promise(function(resolve,reject){

resolve(42);

});

 

Let p2 = new Promise(function(resolve,reject){

resolve(43);

});

 

Let p3 = new Promise(function(resolve.reject){

resolve(44);

});

 

Let p4 = Promise.all([p1,p2,p3]);

P4.then(function(value){

console.log(Array.isArray(value)); //true

console.log(value[0]);//42

console.log(value[1]);//43

console.log(value[2]);//44

});

 

Promise迭代对象中只要有一个被拒绝,不等其他执行完成,都全部拒绝。

 

let p1 = new promise(function(resolve,reject){

resolve(42);

});

 

Let p2 = new Promise(function(resolve,reject){

reject(43);

});

 

Let p3 = new Promise(function(resolve.reject){

resolve(44);

});

 

Let p4 = Promise.all([p1,p2,p3]);

P4.then(function(value){

console.log(Array.isArray(value)); //false

console.log(value);//42

});

 

 

Promise.race() 方法和promise.all()的区别就是,只要promise迭代对象中有一个解决,那么无需等待其他promise解决,就返回,会竞选,如果p2先完成,则返回拒绝的promise,如果跑先完成,返回已完成的promise.

 

let p1 = new promise(function(resolve,reject){

resolve(42);

});

 

Let p2 = new Promise(function(resolve,reject){

reject(43);

});

 

Let p3 = new Promise(function(resolve.reject){

resolve(44);

});

 

Let p4 = Promise.race([p1,p2,p3]);

P4.then(function(value){

console.log(value);//42

});

 

 

 

 

posted on 2017-05-23 15:41  清水伊梦  阅读(241)  评论(0编辑  收藏  举报