ES6!!!

变量的解构赋值

数组的解构赋值:

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
本质上,这种写法属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。如果解构不成功,变量的值就等于undefined。事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值。
结构赋值可以指定默认值,但如果默认值是一个表达式,那么这个表达式是惰性求值的,即只有在用到的时候,才会求值。例如:

function f(){
	console.log('aaa');
}
let [x=f()] = [1]; //x=1 且 不会输出aaa

对象的解构赋值:

对象的解构赋值与数组有一个重要的不同:数组的是按照次序(我理解为index)对应才能赋上值。对象的解构赋值没有次序但需要变量名与对象的属性名相同。
如果变量名与属性名不一致,必须写成下面这样。下面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。(相当于给对象属性名起个别名,作为变量名用,赋值也是赋给变量名)

var{foo模式(对象属性名): baz变量名} = {foo:'aaa',bar:'bbb'}
baz // "aaa"

这样写时,baz的声明和赋值是一起的,对于let和const来说,变量不能重新声明,所以一旦赋值的变量以前声明过,就会报错。

let foo;
let {foo} = {foo: 1}; // SyntaxError: Duplicate declaration "foo"

函数参数的解构赋值

下面代码看似传入一个数组,但是传入参数的那一刻,数组就被结构成变量x,y了

function add([x,y]){
	return x+y;
}
add([1,2]);

字符串

JavaScript内部,字符以UTF-16的格式储存,每个字符固定为2个字节。

字符串的遍历器接口

ES6为字符串添加了遍历器接口,使得字符串可以被for…of循环遍历。

for (let x of "text"){console.log(x)}  // "f"  "o"  "o"
for(let x of text){console.log(x)}   //Uncaught TypeError: text is not iterable

字符串API

indexOf(): 可以用来确定一个字符串是否包含在另一个字符串中。
includes():返回布尔值,表示是否找到了参数字符串。
startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。
这三个方法都支持第二个参数,表示开始搜索的位置。使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。
repeat(次数):返回一个新字符串,表示将原字符串重复n次。参数如果是小数,会被取整。如果repeat的参数是负数或者Infinity,会报错。但是,如果参数是0到-1之间的小数,则等同于0,参数是字符串,则会先转换成数字。
padStart(),padEnd():如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。padStart和padEnd一共接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。

Iterator和for…of循环

在ES6中,有三类数据结构原生具备Iterator接口:数组、某些类似数组的对象、Set和Map结构。
为对象添加Iterator接口:

let obj = {
  data: [ 'hello', 'world' ],
  [Symbol.iterator]() {
    const self = this;
    let index = 0;
    //调用obj[Symbol.iterator]后返回对象,此对象有next()方法
    return {
      next() {
        if (index < self.data.length) {
        //next()方法的返回值对象,对象.value得到值,value.done得到是否是最后一个属性,当true时是最后一个,for...of 看到true就不执行了,这行也不打印。
          return {
            value: self.data[index++],
            done: false
          };
        } else {
          return { value: undefined, done: true };
        }
      }
    };
  }
};

Promise

1.API:
Promise.resolve():将promise对象的状态由peding转换为fulfilled成功,返回值为一个promise实例对象,是属于Promise函数对象的方法,不是实例对象的方法;
Promise.reject():返回一个失败的promise实例对象
Promise.all():参数为数组,数组中存promise实例对象,当数组中实例对象状态全是成功时,返回一个成功的promise实例对象,结果值为数组中promise实例对象的结果值组成的数组;当数组中有失败状态的promise实例对象时,返回那个失败的promise实例对象。
Promise.race():参数为数组,数组中存promise实例对象,返回值为最先发生状态改变的promise实例对象。
改变promise实例对象的状态方式:
1.resolve() 2.reject() 3.抛出错误:throw “出错了”

问题:
1.改变promise对象的状态和执行回调谁先谁后?(resolve先执行还是then被指定)
都有可能,当promise对象中封装的是同步的,如resolve(“ok”),按顺序执行,当是异步的,会先按顺序执行完初始化代码,在执行异步队列中的任务
,then 的回调执行总是在改变状态之后才能拿到数据,注意是回调执行,不是then方法指定
2.异常穿透:
在promise调用链中,只需在最后指定一个catch,或then,写出错误的回调,这个错误的回调会穿透调用链,找到第一个出现状态为错误的地方并将此promise实例对象返回。
3.如何中断promise链:返回一个pading状态的promise对象,因为所有的then回调都是在promise对象状态改变后才执行的,中间返回pading状态的promise对象,后面的状态也都是peding,then的回调不会执行

Class

let methodName = "getArea";
class Point {
	//定义构造器
	constructor(x,y){
	this.x = x;
	this.y = y
	}
	//定义方法,在Point.prototype上
	toString(){
	return "(" + this.x + "+" this.y + ")";
	}
	[methodName](){}
	
}
  • 类的内部所有方法都是不可枚举的,es5的写法可以
  • class不存在变量提升,要先声明类在new,先有父类再有子类,否则会报错
  • 由于本质上,ES6的类只是ES5的构造函数的一层包装,所以函数的许多特性都被Class继承,包括name属性。

类的继承

class ColorPoint extends Point {
	constructor(x, y, color) {
    	super(x, y); // 调用父类的constructor(x, y)且super必须写第一行
    	this.color = color;
  	}

  	toString() {
    	return this.color + ' ' + super.toString(); // 调用父类的toString()
  	}
}
  • ES5的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。ES6的继承机制完全不同,实质是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this。

  • 在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例。

  • Class作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链。B extend A 时,①B的隐式原型属性,表示构造函数的继承,总是指向父类(函数对象,因为es6是先构造父类在对父类进行拓展),②B的prototype属性的–proto–属性总是指向父类的prototype,表示方法的继承(因为父类的方法在父类的原型上(实例对象))。

  • 这两条继承链,可以这样理解:作为一个对象,子类(B)的原型(__proto__属性)是父类(A);作为一个构造函数,子类(B)的原型(prototype属性)是父类的实例。

super

  1. 做函数时,用于构造方法第一行super(参数.)
  2. 做对象时,在普通方法中,指向父类的原型对象(注意,由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。) ;在静态方法中,指向父类

Class的取值函数(getter)和存值函数(setter)

Class的静态属性和实例属性

静态属性指的是Class本身的属性,不是其实例对象上的属性,

class Foo {
}

Foo.prop = 1;
Foo.prop // 1

目前,只有这种写法可行,因为ES6明确规定,Class内部只有静态方法,没有静态属性。
1).类的实例属性

class MyClass {
  myProp = 42;

  constructor() {
    console.log(this.myProp); // 42
  }
}

2)类的静态属性
类的静态属性只要在上面的实例属性写法前面,加上static关键字就可以了。

// 老写法
class Foo {
}
Foo.prop = 1;

// 新写法
class Foo {
  static prop = 1;
}

new.target属性:返回new命令作用于的那个构造函数。否则返回undefined,可以确保构造函数只能用于new

function Person(name) {
  if (new.target !== undefined) {
    this.name = name;
  } else {
    throw new Error('必须使用new生成实例');
  }
}

Mixin模式指的是,将多个类的接口“混入”(mix in)另一个类。

function mix(...mixins) {
  class Mix {}

  for (let mixin of mixins) {
    copyProperties(Mix, mixin);
    copyProperties(Mix.prototype, mixin.prototype);
  }

  return Mix;
}

function copyProperties(target, source) {
  for (let key of Reflect.ownKeys(source)) {
    if ( key !== "constructor"
      && key !== "prototype"
      && key !== "name"
    ) {
      let desc = Object.getOwnPropertyDescriptor(source, key);
      Object.defineProperty(target, key, desc);
    }
  }
}

使用:上面代码的mix函数,可以将多个对象合成为一个类。使用的时候,只要继承这个类即可。

class DistributedEdit extends mix(Loggable, Serializable) {
  // ...
}

ES6模块化

ES6 的模块自动采用严格模式,不管你有没有在模块头部加上"use strict"。
ES6 模块之中,顶层的this指向undefined,即不应该在顶层代码使用this。
一个模块就是一个独立的文件。该文件内部的所有变量,外部无法获取。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值