JS的类与继承

继承

继承的作用是:子类可以具有父类的属性和方法

JS没有继承,只有原型链引用

一个对象的proto指向构造他的函数的protype

obj._proto_ = Object.prototype

如:

var a = new Array();
a.push() //实例属性
a.valueOf() //继承Object

push是Array.protoype的属性;
valueOf是继承子Ojbect.prototype的;
因为

Array.protoype.__proto__ = Object.protoype

隔了两层的才是继承,对于a;push是自身有的,valueOf才是继承的.

能产生对象的东西即为类

自己写一个继承类

function Human(name){
    this.name = name;
}
Human.prototype.run = function(){
    console.log('跑跑跑');
    return undefined;
}

function Man(name){
    Human.call(this,name); //使子类有父类的属性,假如不写this,那么this就是window
    this.gender = '男';
}

Man.prototype.__proto__ = Human.prototype //插入父类原型链,但是IE不支持

Man.prototype.fight = function(){
    console.log('打击');
    return undefined;
} 

var f = new Man('某个男人'); //假如不写new,那么this就是window,因为new的时候this会绑定到这个对象名为Man的对象上

输出:
f.name  //'某个男人'
f.gender //'男'
f.fight()  //'打击'
f.run() //'跑'

f.__proto__ === Man.prototype;//true
f.__proto__.proto__ === Human.prototype;//true
Man.prototype.__proto__ === Human.prototype;//true
prototype

prototype,存放共有属性对象的地址

ES5和ES6的写法

ES5:

var f = function(){}
f.protype = Human.protype
Man.protype = new f()

为什么?

当var obj = new Fn()时,会做以下几件事

  1. 产生一个空对象
  2. this = 该空对象
  3. this.proto = Fn.protype
  4. 执行Fn.call(this,x,y..)
  5. return this

Man.prtotype = New Human();会执行this.name,使得有多余属性
因为第4步不想要,所以构造一个空函数,只要他的protype

空函数.protype = Human.prototype;
Man.protype = new f() // 1,2,3,5步
f.protype === Human.prototype //true
Man.protype.proto === f.prototype //true

ES6:
constructor构造自有属性,共有属性写在constructor外面
super,执行超类(父类)的constructor

class Human{
    constructor(name){
        this.name = name
    }
    run(){
        console.log('run')
    }
}

class Man extends Human{//等价于Man.protype.__protype = Human.protype
    constructor(name){
        super(name) //等价于Human.call(this,name),super意为超类,即父类
        this.gender = 'Man'
    }
    fight(){
        console.log('fight')
    }
}

var author = new Man('roxas')
atuhor//{
    name:'roxas',
    gender:'Man'
    __proto__:{
        fight(){},
        ...
        __proto__:{
            run(){}
            ...
        }
    }
}
get set

//属性封装
用get来控制只读属性.属性可通过set来条件控制

class Animal{
    constructor(name){
        this.name = name
        this._race = 'moving'
    }
    get race(){
        return this._race
    }
    set race(value){
        this._race = value
    }
}

//let dog = new Animal('dog')
dog.race //moving
dog.race = 'donig'
dog.race //doing
static静态方法

不需要实例化就可以调用的方法

class Animal{
    constructor(name){
        this.name = name
        this._race = 'moving'
    }
    static die(){
        console.log('Animal Die')
    }
}

Animal.die //Animal Die