继承

批量创建对象的方法:

1、工厂模式

  需要显示创建对象,并要返回对象,缺点在于无法判断对象类型。

//工厂模式
    function createperson(name,age,friends){
        var o=new Object();
        o.name=name;
        o.age=age;
        o.friends=friends;
        return o;
    }
    var person1=createperson('张三',19,['小花','等等']);
    var person2=createperson('李四',39,['二狗','小明']);
    console.log(person1);
    console.log(person2);

2、构造函数模式

  没有显示创建对象,直接将属性和方法赋给了this对象,没有return;

  要创建对象新实例,会有以下四个步骤:1.创建一个新对象;2.将构造函数作用域赋给新对象;3.执行构造函数代码;4.返回新对象

  创建对象新实例要用new操作符,可用instanceof操作符检测对象类型;

  缺点在于每次创建新对象时,每个方法都会在每个实例上被重新创建一次;

//构造函数模式
    function Person(name,age){
        this.name=name;
        this.age=age;
        this.run=function(){
            console.log('run');
        }
    }
    var person1=new Person('张三',19);
    var person2=new Person('李四',39);
    console.log(person1);
    person1.run();
    console.log(person2);

    //instanceof检测对象类型
    console.log(person1 instanceof Person);//true
    console.log(person1 instanceof Object);//true

3、原型模式

  好处在于可以让所有实例对象共享属性方法

  缺点在于无法传参

//原型模式
    function Person(){
    }
    Person.prototype.name='zhangsan';
    Person.prototype.age=19;
    Person.prototype.run=function(){
        console.log('run');
    }
    var person1=new Person();
    var person2=new Person();
    console.log(person1);
    person1.run();
    console.log(person1.name===person2.name);//true表明共享

    //对象实例不能重写原型中的值
    person1.name='wangwu';//实例属性会覆盖原型属性
    console.log(person1.name);//wangwu
    console.log(person2.name);//zhangsan

    //hasOwnProperty()方法可以检测方法或属性在实例中还是原型中
    console.log(person1.hasOwnProperty('name'));//true
    console.log(person2.hasOwnProperty('name'));//false

    //in操作符可以检测方法或属性是否存在,无论是在实例中还是原型中
    console.log('name' in person1);//true
    console.log('name' in person2);//true

    //结合hasOwnProperty()方法与in操作符可以判断属性到底存在于实例中还是原型中
    function hasprototypeproperty(object,name){
        return !(object.hasOwnProperty(name))&&(name in object);
    }
    console.log(hasprototypeproperty(person1,'name'));//false
    console.log(hasprototypeproperty(person2,'name'));//true

    //Object.keys()方法可枚举对象上所有实例属性
    console.log(Object.keys(Person.prototype));//["name","age","run"]
    console.log(Object.keys(person1));//["name"]
    
    //delete可以删除实例属性
    delete person1.name;
    console.log(person1.name);//zhangsan
    console.log(person2.name);//zhangsan
    
    //更简单的原型语法
    Person.prototype.name='zhangsan';
    Person.prototype.age=19;
    Person.prototype.run=function(){
        console.log('run');
    }
    //可写成对象字面量形式,但是这种对象形式相当于重写整个原型库,constructor属性改变,慎用!
    Person.prototype={
        constructor:Person,//constructor属性要跟回来!
        name:'zhangsan',
        age:19,
        run:function(){
            console.log('run');
        }
    }
    //原型的动态性,即对原型对象的任何修改都能实时从实例上反映出来,即使先实例对象,后修改原型

4、组合使用构造函数模式和原型模式

  构造函数模式用于定义实例属性

  原型模式用于定义方法和共享属性

//组合使用构造函数模式和原型模式
    function Person(name,age){
        this.name=name;
        this.age=age;
    }
    Person.prototype.run=function(){
        console.log('run');
    };
    var person1=new Person('zhangsan',16);
    console.log(person1);

继承实现的方式

1、原型链继承

    //原型链继承
    function Animal() {
        this.type = 'Animal'
    }
    Animal.prototype.run = function () {
        console.log('跑');
    };
    function Dog(name) {
        this.name = name;
    }
    Dog.prototype.speak = function () {
        console.log(this.name+'汪汪');
    };
    Dog.prototype=new Animal();//修改Dog的原型对象为Animal的实例
    var dog=new Dog('小花');
    console.log(dog.__proto__.constructor);//Animal
    console.log(dog.type);//Animal
    console.log(dog instanceof Dog);//true
    console.log(dog instanceof Animal);//true

原型链继承存在的问题:1.引用类型值会被共享;2.创建子类型的实例时,不能向超类型的构造函数传递参数

   //原型链继承存在的问题
    //引用类型值会被所有实例共享
    function Animal() {
        this.friends = ['小花','二毛'];
    }
    Animal.prototype.run = function () {
        console.log('跑');
    };
    function Dog(name) {
        this.name = name;
    }
    Dog.prototype.speak = function () {
        console.log(this.name+'汪汪');
    };
    Dog.prototype=new Animal();//修改Dog的原型对象为Animal的原型
    var dog1=new Dog();
    dog1.friends.push('狗蛋');
    var dog2=new Dog();
    console.log(dog1.friends);//小花,二毛,狗蛋
    console.log(dog2.friends);//小花,二毛,狗蛋

2、使用构造函数继承

  子类型借调超类型,用call或apply方法,可传参,但是构造函数继承存在问题在于:1.超类型原型对象上的方法无法为子类型所用;2.因此方法只能写在超类型构造函数中,无代码复用性可言;

  //利用构造函数继承,call或apply借调
    function Animal() {
        this.friends = ['小花','二毛'];
    }
    Animal.prototype.run = function () {
        console.log('跑');
    };
    function Dog(name) {
        Animal.apply(this);
        this.name = name;
    }
    Dog.prototype.speak = function () {
        console.log(this.name + '汪汪');
    };
    var dog1 = new Dog();
    dog1.friends.push('狗蛋');
    var dog2 = new Dog();
    console.log(dog1.friends);//小花,二毛,狗蛋
    console.log(dog2.friends);//小花,二毛
    dog1.run();

3、组合式继承(伪经典继承)

  综合使用原型链继承和构造函数继承,一般可满足开发所用,小问题在于父类属性重复。

//组合式继承
    function Animal(friends) {
        this.friends = friends;
    }
    Animal.prototype.run = function () {
        console.log('跑');
    };
    function Dog(name, friends) {
        Animal.call(this, friends);
        this.name = name;
    }
    Dog.prototype.speak = function () {
        console.log(this.name + '汪汪');
    };
    Dog.prototype = new Animal();
    Dog.prototype.constructor = Dog;
    var dog1 = new Dog('狗蛋', ['lala','cindy']);
    console.log(dog1.friends);//Dog

4、寄生式继承

  借助一个空的构造函数,实例化出一个对象,作为子类型的原型对象,它的原型对象指向超类型的原型对象,修复constructor,即可。

//寄生式继承
    function Animal(friends) {
        this.friends = friends;
    }
    Animal.prototype.run = function () {
        console.log('跑');
    };
    function Dog(name, friends) {
        Animal.call(this,friends);
        this.name = name;
    }
    Dog.prototype.speak = function () {
        console.log(this.name + '汪汪');
    };
    function Temp(){}
    Temp.prototype=Animal.prototype;
    var o=new Temp();
    Dog.prototype=o;
    Dog.constructor=Dog;
    var dog1 = new Dog('狗蛋', ['lala','cindy']);
    console.log(dog1.friends);//Dog
    dog1.run();
原文地址:https://www.cnblogs.com/wenzizaigaoge/p/10512832.html