JavaScript面向对象编程-阮一峰-已读

本文介绍JavaScript中的封装与继承实现方式,包括构造函数、原型继承、构造函数绑定等方法,并探讨了不同继承方式的特点与适用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

封装
  • 最简单的封装就是将属性封装在对象中,这是生成对象的原始模式;
    • 缺点在于写起来麻烦,而且原型与实例之间没有联系;
          //原型
        var Cat={
            name:"",
            color:""
        }
        //实例
        var cat1={};
            cat1.name="Tom";
            cat1.color="yellow";
        var cat2={};
            cat1.name="Peter";
            cat1.color="black";
  • 用函数生成实例:原型与实例之间仍然没有关联
            //用函数生成实例
        function Cat(name,color){
            return{
                name:name,
                color:color
            }
        }
       var cat1=Cat("Tom", "yellow");
       var cat2=Cat("Peter", "black"); 
  • 构造函数模式:构造函数其实是个普通函数,但内部使用this变量;
    • 实例的constructor属性指向构造函数
    • 构造函数模式的问题在于浪费内存:当为构造函数添加固定值的属性和方法时,在所有实例中这些属性和方法时一样的,但 
        //构造函数
        function Cat(name,color){
            this.name=name;
            this.color=color;
        }
        //生成实例
        var cat1=new Cat("Tom","yellow");
        var cat2=new Cat("Peter","black");
继承
    //animal对象的构造函数,使cat对象继承animal
    function(){
        this.species="动物";
    }
  • 构造函数绑定:使用call()或apply()方法将要继承的对象的构造函数绑定到子对象的构造函数中;
    function Cat(name,color){
    //将Animal构造函数作为cat对象的方法调用,使cat对象继承animal的属性和方法
        Animal.apply(this,arguments); 
        this.name=name;
        this.color=color;
    }
  • prototype模式
    • Cat.prototype.constructor默认是指向Cat的,但是重写了Cat.prototype之后,该属性就指向Animal()了,而且实例将继承该属性,cat1的构造函数也变成了Animal(), 所以必须手动纠正,将Cat.prototype.constructor重新指向Cat, 这在重写prototype是必须的;
Cat.prototype=new Animal();  //将cat的原型指向Animal的实例
Cat.prototype.constructor=Cat; //将cat原型原型的constructor设置为Cat
  • 直接继承原型
    • Animal的属性可以直接写到Animal.prototype中,所以可以直接让Cat.prototype继承Animal.prototype;
    • 优点是效率高,不需要创建Animal的实例;
    • 缺点是Cat.prototype和Animal.prototype指向同一个对象,对Cat.prototype的修改同样会反映到Animal.prototype;
      • 所以现在Animal.prototype.constructor也指向Cat();
        function Animal(){}
        Animal.prototype.species="动物";
        Cat.prototype=Animal.prototype;
        Cat.prototype.constructor=Cat;
  • 利用空对象作为中介,然后继承原型;
    • F是空对象,几乎不占内存;
    • 通过F()作为中介,修改cat的原型就不会影响animal的原型了;
var F=function(){};
F.prototype=Animal.prototype;
Cat.prototype=new F(); 
Cat.prototype.constructor=Cat;
    • 将以上方法封装为函数:child对象将继承parent对象
function extend(Child, Parent){  //Child是子类,Parent是父类
    var F=function(0{};
    F.prototype=Parent.prototype;
    Child.prototype=new F();
    Child.prototype.constructor.=Child;
    Child.uber=Parent.prototype;
}
      • uber属性直接指向Parent.prototype, 是为了使对象可以直接调用父对象的方法,纯属备用性质;
  • 复制继承:将父类的属性和方法都复制到子类中
        //复制继承
        function extend2(Child,Parent){
            var p=Parent.prototype;
            var c=Child.prototype;
            for(var prop in p){
                c[prop]=p[prop]; //将父类的属性复制给子类
            }
            c.uber=p;
        }
不使用构造函数的继承
    • 不经过构造函数,直接实现实例对象之间的继承;
  • object()方法:该函数返回的对象继承了传入的对象;
        //object()函数:实现实例对象之间的继承
        function object(parent){
            function F(){};
            F.prototype=parent;
            return new F();  //返回的对象不包含自有属性
        }
  • 浅复制:将父对象的属性复制给子对象
    • 当对象的属性值是引用类型时,子对象获得是该属性值一个引用,当修改子对象的属性只时,父对象的属性也会被修改
    • 所以浅复制只适用于复制基本类型属性值;
        //浅复制
        function extendCopy(parent){
            var child={};
            for(prop in parent){
                child[prop]=parent[prop];    
            }
            c.uber=p;
            return c;
        }
  • 深复制:真正实现对对象的复制,而不是引用
        //深复制
        function deepCopy(parent,child){
            var c=c || {};
            for(prop in parent){
                if(parent[prop]==="object"){
                    child[prop]=(p[prop].constructor===Array) ? []:{};
                    deepCopy(parent[prop],child[prop]); //递归,将prop对象的属性值复制给child[prop]对象
                }
                else{
                    child[prop]=parent[prop];
                }
            }
            return child;
        }

转载于:https://www.cnblogs.com/qinghe/p/5391529.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值