Class

Class基本语法

ES6中引入了Class这个概念作为对象的模板,通过Class关键字可以定义类。

function Person (name, age) {
    this.name = name;   //this指向对象的实例
    this.age = age;
}
Person.prototype.sayName = function () {
    return this.name;
}   //ES5 构造函数

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    sayName() {
        return this.name;
    }
}   //ES6定义类   这样的写法只是为了看起来更像传统的面向对象语言

所有类的方法都可以添加到prototype对戏上,prototype对象的constructor属性直接指向“类”本身。类的内部定义的所有方法都是不可枚举的

constructor方法

constructor方法是类的默认方法,通过new命令生成对象实例时自动调用constructor方法。

class Foo {
    constructor() {
        return Object.create(null);
    }
}
new Foo() instanceof Foo    //false
//constructor默认返回实例对象(this),也可以指定
实例对象

实例对象的属性除非显式地定义在其本身(this对象),否则都是定义在原型上的 :

var p = new Person('Jersey', 20);
p.sayName()  // 'Jersey'
p.hasOwnProperty('name');   //true
p.hasOwnProperty('sayName');    //false

name和age都是实例对象p自身的属性(因为定义在this变量上),而sayName方法是定义在原型上的。类的所有实例都共享一个原型对象

Class表达式
const MyClass = class Me {
    getClassName() {
        return Me.name;
    }
};
let inst = new MyClass();
inst.getClassName();    //Me
Me.name     //error: Me is not undefined
//相当于:
const MyClass = class {//do somenthing};

这是一个MyClass类而不是Me,Me只在Class的内部代码可用,指代当前类

立即执行的Class

var person = new class {
    constructor(name) {
        this.name = name;   
    }
    sayName() {
        return this.name;
    }
}('Jersey');
person.sayName()    //'Jersey'

Class的继承

Class之间可以通过关键字extends实现继承

class Per extends Person {}

上面的代码定义了一个Per类,该类继承了Person类的所有属性和方法,

class Per extends Person {
    constructor(name, age, home) {
        super(x, y);   //调用父类的constructor(name, age)
        this.home = home;
    }
}

上面的代码中,constructor方法中出现了super关键字,它指代父类的实例(即父类的this对象)。子类必须在constructor方法中调用super方法,否则新建实例会报错。因为子类没有自己的this对象,而是继承了父类的this对象,必须调用super方法之后才能得到this对象。

类的prototype属性和 _proto_ 属性

ES5的实现中,每个对象的_proto_属性指向对应的构造函数的prototype属性。Class同时存在两条继承链:

  • 子类的_proto_属性构造函数的继承,总指向父类
  • 子类prototype属性的_proto_属性表示方法的继承,总是指向父类的prototype属性

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

class A {}
class B extends A {}
B._proto_ === A     //true  作为一个对象
B.prototype._proto_ === A.prototype     //true   作为一个构造函数
extends的继承目标

extends关键字后面可以跟多种类型的值,上面的A只要是一个有prototype属性的函数,就能被B继承,所以A可以是任意函数。Object.getPrototypeOf()方法可以判断一个类是否继承了另一个类

原生构造函数的继承

ES5中,原生构造函数是无法继承的,比如我们不能定义一个Array, String的子类。这是因为子类无法获得原生构造函数的内部属性。ES6允许继承原生构造函数定义子类,ES6先新建父类的实例对象this,再用子类的构造函数修饰this,是父类的所有行为都可以被继承

class arr extends Array {
    constructor(...args) {
        super(...args);
    }
}       //这里定义了一个arr类,继承了原生构造函数Array

Class的 getter 和 setter

在Class内部可以使用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'      prop属性的赋值和取值行为都被定义了!

new.target属性

在构造函数中new.target属性返回new命令所作用的构造函数,如果构造函数不是通过new命令所调用的,就会返回undefined

class内部调用new.target返回当前class

class A {
    constructor(length, width) {
        console.log(new.target === A);
        this.length = length;
        this.width = width;
    }
}
let B = new A(3, 3)         //true

子类继承父类时new.target会返回子类

class C extends A {
    constructor(length) {
        super(length, length);
    }
}
var d = new C(3);       //false

转载于:https://www.cnblogs.com/lugefan/p/7345798.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值