ES6学习之Class
一、定义类(ES6的类,完全可以看做是构造函数的另一种写法)
class Greet { constructor(x, y) { this.x = x; this.y = y; } sayHello() { console.log(this.x + " " + this.y) } } let a = new Greet("hello", "everybody"); a.sayHello() //hello everybody
《注》:
- 以上定义的类如果用ES5的构造函数实现如下:
function Greet(x, y) { this.x = x; this.y = y; this.sayHello = function () { console.log(this.x + " " + this.y) } } let a = new Greet("hello", "everybody"); a.sayHello() //hello everybody
- 类的数据类型就是函数,类本身就指向构造函数
typeof Greet; //function Greet === Greet.prototype.constructor //true
- 类的所有方法都定义在类的prototype属性上面
class Greet { constructor() {...} sayHello() {...} sayHi(){...} } 等同于 Greet Greet.prototype = { constructor() {}, sayHello() {}, sayHi() {}, };
constructor方法:
- 是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
class Greet { } // 等同于 class Greet { constructor() {} }
- constructor方法默认返回实例对象(即- this),完全可以指定返回另外一个对象。
class Foo { constructor() { return Object.create(null); } } new Foo() instanceof Foo // false
类的实例对象:
- 实例的属性除非显式定义在其本身(即定义在this对象上),否则都是定义在原型上(即定义在class上)。
class Greet { constructor(x, y) { this.x = x; this.y = y; } sayHello() { console.log(this.x + " " + this.y) } } let a = new Greet("hello", "everybody"); // x,y都是实例对象a自身的属性,因为定义在this上 a.hasOwnProperty('x') // true a.hasOwnProperty('y') // true //sayHello是原型对象的属性,因为定义在Greet上 a.hasOwnProperty('sayHello') // false a.__proto__.hasOwnProperty('sayHello') // true
- 类的所有实例共享一个原型对象
let a = new Greet("hello", "everybody"); let b = new Greet("hello", "everybody"); a.__proto__ === b.__proto__ //true
Class表达式:
const MyClass = class Me { getClassName() { return Me.name; } }; //类的名字是MyClass而不是Me,Me只在 Class 的内部代码可用,指代当前类。 //如果类的内部没用到的话,可以省略Me const MyClass = class { ... };
不存在变量提升:必须先定义类,再使用
私有方法:
- 利用Symbol值的唯一性
const bar = Symbol('bar');
const snaf = Symbol('snaf');
export default class myClass{
  // 公有方法
  foo(baz) {
    this[bar](baz);
  }
  // 私有方法
  [bar](baz) {
    return this[snaf] = baz;
  }
  // ...
};
- 利用#标识:
class Greet { constructor(x, y) { this.x = x; this.y = y; } #sayHello() { console.log(this.x + " " + this.y) } }
Class 的取值函数(getter)和存值函数(setter):在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
class MyClass { constructor() { // ... } get prop() { return 'getter'; } set prop(value) { console.log('setter: '+value); } } let inst = new MyClass(); inst.prop = 123; // setter: 123 inst.prop // 'getter'
Class 的静态方法:加上static关键字,表示该方法不会被实例继承,而是直接通过类来调用
class Foo { static classMethod() { return 'hello'; } } Foo.classMethod() // 'hello' var foo = new Foo(); foo.classMethod() // TypeError: foo.classMethod is not a function
- 如果静态方法包含this关键字,这个this指的是类,而不是实例
- 父类的静态方法,可以被子类继承
- 静态方法也是可以从super对象上调用的
Class 的静态属性和实例属性
- 静态属性指的是 Class 本身的属性,即Class.propName,而不是定义在实例对象(this)上的属性,定义方法如下:
class MyClass { static myStaticProp = 42; constructor() { console.log(MyClass.myStaticProp); // 42 } }
- 类的实例属性可以用等式,写入类的定义之中
class MyClass { myProp = 42; constructor() { console.log(this.myProp); // 42 } }
new.target 属性:如果构造函数不是通过new命令调用的,new.target会返回undefined
用来确定构造函数是怎么调用的。
function Person(name) { if (new.target !== undefined) { this.name = name; } else { throw new Error('必须使用 new 命令生成实例'); } }
二、Class继承:通过extends关键字实现继承
class Point {
}
class ColorPoint extends Point {
}
supper:
- 子类必须在constructor方法中调用super方法(子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工)
class Point { /* ... */ }
class ColorPoint extends Point {
  constructor() {
  }
}
let cp = new ColorPoint(); // ReferenceError
- 如果子类没有定义constructor方法,这个方法会被默认添加
class ColorPoint extends Point { } // 等同于 class ColorPoint extends Point { constructor(...args) { super(...args); } }
- 在子类的构造函数中,只有调用super之后,才可以使用this关键字(子类实例的构建,是基于对父类实例加工,只有super方法才能返回父类实例)
class Point { constructor(x, y) { this.x = x; this.y = y; } } class ColorPoint extends Point { constructor(x, y, color) { this.color = color; // ReferenceError super(x, y); this.color = color; // 正确 } }
- super作为函数调用时,代表父类的构造函数。ES6 要求,子类的构造函数必须执行一次- super函数。且只能用在子类的构造函数之中,用在其他地方就会报错
class A {}
class B extends A {
  constructor() {
    super();
  }
}  //super虽然代表了父类A的构造函数,但是返回的是子类B的实例
- super作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
a)普通方法中:
class A { p() { return 2; } } class B extends A { constructor() { super(); console.log(super.p()); // 2 } } //指向父类的原型对象 let b = new B();
b) 静态方法中:
class Parent { static myMethod(msg) { console.log('static', msg); } myMethod(msg) { console.log('instance', msg); } } class Child extends Parent { static myMethod(msg) { super.myMethod(msg); } myMethod(msg) { super.myMethod(msg); } } Child.myMethod(1); // static 1 var child = new Child(); child.myMethod(2); // instance 2
 
                    
                
 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号