ES6标准入门(二)

avatarplhDigital nomad

第18章 class Class基本语法

JavaScript语言的传统方法是通过构造函数定义并生成新对象。下面举个例子。

  this.x = x;
  this.y = y;
Point.prototype.toString = function(){
  return `(${this.x} , ${this.y})`
}

上面这种写法和Java,c++区别很大,这让程序员很困惑。 es6提供了新的语法糖ckass

class Point{
  constructor(x,y){
    this.x = x;
    this.y = y;
  }
  toString(){
    return `(${this.x} , ${this.y})`
  }
}

constructor是构造器的方法。而this则代表了该对象。class就是es5的构造函数的另一种写法。更加语义化。

class Point{}
Point === Point.prototype.constructor.Point   //true

下面写法也是对等的

class Point {
  constructor() {
    // ...
  }
  toString() {
    // ...
  }
  toValue() {
    // ...
  }
}
Point.prototype = {
	constructor(){}
	toString(){}
	toValue(){}
}

而在类的实例上面调用方法,其实就算调用原型上面的方法。

class B{}
let b = new B();

这些方法都是不可枚举的.通过class内部命名的方法,和通过prototype命名的方法最大的不同是一个是可枚举的,另一个是不可枚举的。而添加static关键字的方法会被添加到Point的原型,因此仅仅只可以内部使用。

class Point {
  constructor() {
    // ...
  }
  static toString() {
    // ...
  }
  toValue() {
    // ...
  }
}
class Point1 {}
Point1.prototype = {
  constructor() {},
  toString() {},
  toValue() {},
};
const p = new Point();
const p1 = new Point1();
console.log(Object.keys(Point.prototype));
console.log(Object.keys(Point1.prototype));
console.log(p);
console.log(p1);
console.log(Point.prototype.constructor === Point);      // true
console.log(Point1.prototype.constructor === Point1);      // true
console.log(Point1.prototype.constructor == Point1);      // true  

image 其中虚的是不可枚举的。

constructor 方法

这个方法是默认存在的方法,,通过new命令生成对象实例时候自动调用的方法,默认返回它本身这个实例化对象this,当然可以指定返回其他对象。

实例对象

生成实例对象和es5一样,如果没有new命令,则会报错,除非你在他前面添加static 作为静态方法,就可以。下面可以看到,constructor里面的x,y, 静态aa方法,普通bb方法

class Point {
  constructor() {
    // ...
    this.x = 1;
    this.y = 1;
  }
  static aa() {}
  bb() {}
}
const p = new Point();
console.log(p);
console.log(Object.keys(Point.prototype));

image

但是当aa,bb都是普通方法的时候,又是另一个样子,奇了个葩

image

不存在的变量提升hoist,他这个和es5的函数提升完全不一样

new Foo(); // referenceError: Me is not defined class Foo{};

class 的继承

class Foo exntend foo {} 下面介绍super()

class Point {
  constructor() {
    this.x = 1;
    this.y = 1;
  }
  getname() {
    return this.name;
  }
}
class ColorPoint extends Point {
  constructor() {
    super();
    this.name = 'ColorPoint';
  }
  aaa() {
    return 'ColorPoint';
  }
}
const p = new ColorPoint();
console.log(p);

image 这里ColorPoint存在两条原型链,一条是继承方法,另一条是继承constructor里面定义的变量。 下面由3钟继承的特殊情况

  • 第一种,子类继承Object class A extends Object {} 其实就算对Object的复制
  • 第二种不继承 class A{} 其实就是默认继承Function。
  • 第三种继承null class A extends null{} 真正的不继承任何东西

super 关键字

他代表了父类的实例。

class类中的getter和setter

class Point {
  constructor() {
    this.x = 1;
    this.y = 1;
    this.name = 'pengliheng';
  }
  getname() {
    return this.name;
  }
  get prop() {
    return this.name;
  }
  set prop(value) {
    console.log(`setter: ${value}`);
  }
}
const p = new Point();
p.prop;                             // setter: pengliheng
p.prop = 'hhhah';            
p.prop;                            //  setter: hhhah

定义一个属于自己的Array,不要再原生Array上面扩展方法,如果需要,请看下面代码

class VersionArray extends Array {
  constructor() {
    super();
    this.history=[[]];
  }
  commit() {
    this.history.push(this.slice());
  }
  revert(){
    this.splice
  }
}

18.5 class 的 静态方法

const a = 'test';
const b = 'test';
a===b // true

const a = {};
const b = {};
a===b // false

const a = [];
const b = [];
a===b // false
[] === []  //false

const a = [];
const b = a;
a===b // true    ,为什么呢? 因为point   ,a point b

下面看一下他们为什么不相等

class Point {
  constructor() {
    this.x = 1;
    this.y = 1;
    this.name = 'pengliheng';
  }
  static getname() {
    return this.name;
  }
  getTName() {
    console.log(new Point() === this);
  }
}
console.log(Point.getname());     // 静态方法,不需要实例化就能获取
const p = new Point();
p.getTName();                             // false,{} !== {},即便是同样的对象,他们也互不相等。     普通方法需要实例化。

静态属性

19章装饰器

装饰器是一种表达式,他能对类的行为发生改变,,这种改变发生在编译阶段, 有点超前,自己去了解吧,如果你不是用的react或者经常用class面向对象编程,并且需要继承属性的时候,你都用不到装饰器。

20章module,这个以后再说,书里面没有提到module模块化的原理,如何引入的。没有讲的深入。

21章编程风格(关于es5过度到es6的使用建议)

####使用 let / constant 替代 var 由于模块化默认使用'use strit'严格模式 所以以后应该是严格模式默认的。 使用优先级 const>let>var const 的使用是因为他是常量,能够给人直观的,如果你要改变常量,建议去定义一个新的常量。这也是函数式编程风格所要求的。 坚持遵循 先声明,再使用的编程规范。

####使用模板字符串添加变量 使用单引号

// bad
const a = '<div>'+value+'</div>'
// good   更具语义化
const a = `<div>${value}</div>`

解构变量

// bad
var a = 1,b=2,c=3;
//good
const a = 1;
const b = 2;
const c = 3;
// best,,,,,更具语义化。
const [a,b,c] = [1,2,3];

image

对象

熟悉typescript的你可能知道,它推崇的是尽量使用常量,以及变量+类型 声明了一个对象,尽量不要去改变它,如果真的要改变它,建议使用以下

// bad
const a = {};
a.x = 3;
// 

使用...扩展符号来复制数组

var a = [...arr]; var b = Array.from(arr);

箭头函数 => 推荐使用,

他消灭了 绑定 bind

推荐使用class来命名对象

使用Eslint代码检查工具。。。

统一规范编程风格,

结束语,不写了。烂书越写越烦。