zoukankan      html  css  js  c++  java
  • 聊一聊Javasript继承

      前前后后已经快写了2年左右javaScript,刚开始只是简单用于一些表单验证和操作dom节点,并没有深入的使用,随着渐渐的深入,开始不想去写重复的代码(懒的开始),从而写简单的继承,封装,抽象等等,最终效果写重复代码少、可用性高(主要:迭代快、代码可以持续使用,加班也少)

    Demo构造函数声明类

    function Person(name){
        this.name = name;
    }
    
    new生成实例

    new生成实例的缺点:无法共享属性和方法,每次new新的实例会开辟新的内存空间,造成极大的资源浪费。

    var personA = new Person('小明');
    console.log(personA.name);
    

    构造函数的this指向新的实例
    如:

    function Person(name){
    	this.name = name;
    	this.sex = '女'
    }
    
    var personA = new Person('小明');
    var personB = new Person('小妞');
    personA.sex = '男';
    console.log(personB.sex);  //女
    

    在这里我们该采用声明解决方案呢?设计者很好的解决了这个问题,那么就是prototype属性(包含对象)的引入

    prototype属性

    它的好处是,实例一旦创建,将自动共同持有共享属性和方法,如:

    function Person(name){
    	this.name = name;
    }
    Person.prototype.sex = '女';
    var personA = new Person('小明');
    var personB = new Person('小妞');
    console.log(personA.sex);  //女
    console.log(personB.sex);  //女
    
    //证明它们是共享的
    Person.prototype.sex = '男';
    console.log(personA.sex);  //男
    console.log(personB.sex);  //男
    

    也许在这里你看不出prototype的好处,但是当你有很多方法和属性时,你的运行效率还高嘛?那么:

    function Person(name, sex){
    	this.name = name;
    	this.sex = sex,
    	this.country = '中国',
    	this.show = function(){
    		console.log(this.name + '的国籍是:'+this.country+',性别:'+this.sex);
    	}
    }
    var personA = new Person('小明'.'男');
    personA.show();   //小明的国籍是是中国,性别:男
    var personB = new Person('小妞','女');
    personB.show();  //小妞的国籍是是中国,性别:女
    

    感觉似乎没有什么问题,但是personA和personB都包含有country、show属性方法一模一样的内容,这样就造成了空间的浪费,效率也降低了,那么我们可以它们共享属性和方法

    function Person(name, sex){
    	this.name = name;
    	this.sex = sex,
    }
    
    Person.prototype.country = '中国';
    Person.prototype.show = function(){
    	console.log(this.name + '的国籍是:'+this.country+',性别:'+this.sex);
    }
    
    var personA = new Person('小明'.'男');
    var personB = new Person('小妞','女');
    personA.show();   //小明的国籍是是中国,性别:男
    personB.show();  //小妞的国籍是是中国,性别:女
    

    配合protorype使用的属性--isPrototypeOf(),hasOwnPrototype(),in

    function Person(name, sex){
    	this.name = name;
    	this.sex = sex,
    }
    
    Person.prototype.country = '中国';
    Person.prototype.show = function(){
    	console.log(this.name + '的国籍是:'+this.country+',性别:'+this.sex);
    }
    
    //isPrototypeOf() 判断实例和对象之间的关系
    console.log(Person.prototype.isPrototype(personA))  //true
    console.log(Person.prototype.isPrototype(personB))  //true
    
    //hasOwnPrototype() 判断属性是本地属性,还是继承自prototype属性
    console.log(personA.hasOwnPrototy('name'))  //true
    console.log(personA.hasOwnPrototy('country'))  //false
    
    //in 判断是否含有属性,不管本地还是继承prototype
    console.log('name' in personA)  //true
    console.log('country' in personA)  //true
    

    constructor属性

    继续使用前面Person原型对象

    function Person(name){
    	this.name = name;
    }
    Person.prototype.sex = '女';
    var personA = new Person('小明');
    var personB = new Person('小妞');
    //新增的实例自动包含有constructor属性
    console.log(personA.constructor == Person);  //true
    console.log(personB.constructor == Person);  //true
    

    这里也可以使用instanceof判断实例和原型对象之间的关系

    console.log(personA instanceof Person);  //true
    console.log(personB instanceof Person);  //true
    

    常用Object之间“继承”(构造函数继承)(5种)

    假设现在有Person和Teacher两个Object,想让Teacher继承Person

    //Person对象
    function Person(name){
        this.name = name;
    }
    
    //Teacher对象
    function Teacher(age,sex){
        this.age = age;
        this.sex = sex;
    }
    
    1、利用构造函数绑定(call或者apply)
    function Teacher(age,sex,name){
        Person.apply(this,name);//Person.call(this,name);
        this.age = age;
        this.sex =sex;
    }
    
    2、使用prototype,也就是我们前面说prototype属性,修改constructor指向
    Teacher.prototype = new Person('xiaoming'); //修改prototy对象原先的值
    Teacher.prototype.constructor = Teacher;
    var teacher1 = new Teacher(19,'女');
    
    3、直接继承prototype
    function Person(){}
    person.prototype.name = "xiaoming";
    
    function Teacher(age,sex){
        this.age = age;
        this.sex = sex;
    }
    
    //Teacher的prototype对象直接指向Person的prototype对象
    Teacher.prototype = Person.prototype;
    Teacher.prototype.constructor = Teacher
    var teacher1 = new Teacher(19,"女");
    
    4、中介new function(){}空对象
    var Fn = new function(){};
    Fn.prototype = Person.prototype;
    Teacher.prototype = new Fn();
    Teacher.prototype.constructor = Teacher;
    
    //扩展封装
    function Extend(ChildObj,ParentObj){
        var Fn = new function(){};
        Fn.prototype = ParentObj.prototype;
        ChildObj.prototype = new Fn();
        ChildObj.prototype.constructor = ChildObj;
        ChildObj.uber = ParentObj.prototype;  //直接指向父对象prototype属性
    }
    
    //Teacher继承Person
    Extend(Teacher,Person);
    var teacher1 = new Teacher(19,'女');
    
    5、拷贝继承(完全)
    function Extend(ChildObj, ParentObj) {
        var p = ParentObj.prototype;
        var c = ChildObj.prototype;
        for (var i in p) { 
            c[i] = p[i];
      }
      c.uber = p;
    } 
    //Teacher继承Person
    Extend(Teacher,Person);
    var teacher1 = new Teacher(19,'女');
    

    非构造函数“继承”(3种)

    //原始
    var Person = {
        name: '小明'
    }
    var Teacher ={
        age:19,
        sex:'女'
    }
    

    这里我们如何可以让Teacher继承Person

    1、object方法
    function object(obj){
        function Fn(){}
        Fn.prototype = obj;
        return new Fn();
    }
    var teacher1 = object(Person);
    teacher1.age = 19;
    teacher1.sex = '女';
    
    2、浅拷贝方法
    function extendCopy(ParentObj){
        var c = {};
        for(var i in ParentObj){
            c[i] = p[i];
        }
        c.uber = p;
        return c;
    }
    //使用extendCopy
    var teacher1 =  extendCopy(Person);
    teacher1.age = 19;
    teacher1.sex = '女';
    
    3、深拷贝方法
    function extendDeepCopy(ParentObj,ChildObj){
        var ChildObj = ChildObj || {};
        for(var i in ParentObj){
            if(typeof  ParentObj[i] === 'object'){
                c[i] = (ParentObj[i].constructor === Array) ? [] : {};
                extendDeepCopy(ChildObj[i],ParentObj[i]);
            }else{
                ChildObj[i] = ParentObj[i];
            }
        }
        return ChildObj;
    }
    
    //使用
    var teacher1 = extendDeepCopy(Person1);
    teacher1.age = 19;
    teacher1.sex = '女';
    

    本文版权归作者共有,欢迎转载,须保留此段声明,并给出原文链接,谢谢!

  • 相关阅读:
    wpf passwordbox控件 光标移到最后
    C#程序 给IE网页IFRAME控件中所嵌入网页的元素赋值
    C#客户端填充外部IE浏览器中网页文本(input)且不提交
    C# 获取当前网页HTML
    WPF 带有提示文本的透明文本框
    C# 导出Excel文件 所导出文件打开时提示“Excel文件格式与扩展名指定格式不一致”
    php生成验证码
    Python命名规范
    UE4碰撞规则详解
    四大编程思想简述
  • 原文地址:https://www.cnblogs.com/moyhui/p/8308994.html
Copyright © 2011-2022 走看看