• 继承


    批量创建对象的方法:

    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();
  • 相关阅读:
    高通Android分区表详解
    LC 871. Minimum Number of Refueling Stops 【lock, hard】
    LC 265. Paint House II
    Horovod 通信策略
    LC 351. Android Unlock Patterns
    LC 957. Prison Cells After N Days
    解析java泛型(二)
    解析java泛型(一)
    全面理解java异常机制
    java基础之继承(二)
  • 原文地址:https://www.cnblogs.com/wenzizaigaoge/p/10512832.html
Copyright © 2020-2023  润新知