• js中比較好的继承方式


    前面说到了原型和原型链,今天就来说说在面向对象中比較好的继承方式吧。先来看看两种基础的继承方式:

    一、构造函数型

    function People(name)
    {
    	this.name=name;
    }
    People.prototype.sayName=function()
    {
    	console.log(this.name);
    }
    function Student(id,name)
    {
    	People.call(this,name);
    	this.id=id;
    }
    Student.prototype.sayId=function()
    {
    	console.log(this.id);
    }

    在Student类里用了Person的call方法,就会在对象上自己主动绑定了name属性。可是这种方法的缺点就是无法继承原型方法。也就是无法继承sayName这种方法。

    二、原型覆盖型

    function People(name)
    {
    <span style="white-space:pre">	</span>this.name=name;
    <span style="white-space:pre">	</span>this.friends=[];
    }
    People.prototype.sayName=function()
    {
    <span style="white-space:pre">	</span>console.log(this.name);
    }
    function Student(id)
    {
    <span style="white-space:pre">	</span>this.id=id;
    }
    Student.prototype=new People();
    Student.prototype.sayId=function()
    {
    <span style="white-space:pre">	</span>console.log(this.id);
    }
    var stu1=new Student(1);
    stu1.name="stu1";
    console.log(stu1);
    
    在这里,Student类的原型指向了People的一个实例,尽管这样既继承了属性。又继承了原型方法,可是缺点就是无法像构造函数那样传递name进去,仅仅能实例化以后再为name属性赋值。大家都知道,尽管在查找时遵循原型链的规则。可是在赋值时,这个规则却是不有用的,实例化过后的对象是无法改动原型对象里面的属性的。

    比方上式里面,为stu1的name属性赋值了,可是结果例如以下:


    正如大家所见,并没有改动其原型对象的name属性。而是在stu1上加了一条name属性

    再来看看改动对象指针:

    function People(name)
    {
    	this.name=name;
    	this.friends=[];
    }
    People.prototype.sayName=function()
    {
    	console.log(this.name);
    }
    function Student(id)
    {
    	this.id=id;
    }
    Student.prototype=new People();
    Student.prototype.sayId=function()
    {
    	console.log(this.id);
    }
    var stu1=new Student(1);
    stu1.friends=["ro"];
    console.log(stu1);

    结果与一般类型的几乎相同,可是我们用以下这样的方式:

    function People(name)
    {
    	this.name=name;
    	this.friends=[];
    }
    People.prototype.sayName=function()
    {
    	console.log(this.name);
    }
    function Student(id)
    {
    	this.id=id;
    }
    Student.prototype=new People();
    Student.prototype.sayId=function()
    {
    	console.log(this.id);
    }
    var stu1=new Student(1);
    stu1.friends.push("Bob");
    console.log(stu1);


    大家看到了,在原型对象里的friends数组加了一个Bob。那是由于friends是引用类型,找到指针后再为其push一个值,这样就改动了原型对象的属性,可是为其赋值的话就会在对象上添加一个,而不是改动原型对象,问题来了。这样的push的方式能改动原型对象的friends。可是每个Student对象都要拥有自己私有的friends属性怎么办呢,能够为其赋值,可是这跟我们要的效果不一样,要的就是friends以及name属性都能成为私有属性,可是方法是原型方法。那么就能借鉴以上两种方式。

    function People(name,arr)
    {
    <span style="white-space:pre">	</span>this.name=name;
    <span style="white-space:pre">	</span>this.friends=arr;
    }
    People.prototype.sayName=function()
    {
    <span style="white-space:pre">	</span>console.log(this.name);
    }
    function Student(id,name,arr)
    {
    <span style="white-space:pre">	</span>People.call(this,name,arr);
    <span style="white-space:pre">	</span>this.id=id;
    }
    Student.prototype=new People();
    Student.prototype.sayId=function()
    {
    <span style="white-space:pre">	</span>console.log(this.id);
    }
    var stu1=new Student(1,"I",["bob"]);
    console.log(stu1);

    大家看到了,name和friends属性确实成为了私有属性,可是原型对象里面也有这两个属性,这样也不好。占用了空间,那应该怎么办呢?怎么样才干去掉这个原型对象里面的属性,事实上非常easy,我们想要的仅仅是People原型对象里面的方法,那么我们仅仅须要继承原型对象即可了呀

    function People(name,arr)
    {
    	this.name=name;
    	this.friends=arr;
    }
    People.prototype.sayName=function()
    {
    	console.log(this.name);
    }
    function Student(id,name,arr)
    {
    	People.call(this,name,arr);
    	this.id=id;
    }
    Student.prototype=People.prototype;
    Student.prototype.sayId=function()
    {
    	console.log(this.id);
    }
    var stu1=new Student(1,"I",["bob"]);
    console.log(stu1);


    这里大概就变成我们想要的样子了。可是另一点问题。constructor指向问题,本来这个constructor应该指向Student,改动一下就可以:

    function inheritPrototype(subType, superType){ 
    	var prototype = superType.prototype;
    	prototype.constructor = subType; 
    	subType.prototype = prototype; 
    }
    function People(name,arr)
    {
    	this.name=name;
    	this.friends=arr;
    }
    People.prototype.sayName=function()
    {
    	console.log(this.name);
    }
    function Student(id,name,arr)
    {
    	People.call(this,name,arr);
    	this.id=id;
    }
    inheritPrototype(Student,People);
    Student.prototype.sayId=function()
    {
    	console.log(this.id);
    }
    var stu1=new Student(1,"I",["bob"]);
    console.log(stu1);



    搞定了,这里我在前面写了一个继承原型的函数,首先将子类的原型指向父类的原型,然后改动其constructor指向,貌似这样就已经非常完美了,可是在不知道不觉中我又发现了一个问题,我也是此时此刻发现的,所以写博客还是有非常大的帮助的。能够帮自己理清思路,大家看到了我改动了constructor指向,可是我同一时候改动了父类的constructor指向,由于两者的原型对象是一个对象。所以这是有问题的。那么如何才干修正这个问题呢?事实上动动脑筋就知道,我们须要复制一个People的原型的副本,然后将Student的原型指向这个副本。那么问题来了,究竟是深拷贝还是浅拷贝呢,至于深拷贝和浅拷贝的概念不知道的能够上网查一查,深拷贝是全然能够满足这个要求的,那假设是浅拷贝呢,并且这个浅拷贝还不是普通的浅拷贝。要用到上面我们分析的知识。刚刚我们是为其赋值,赋值的话我们是不能改动一个对象的原型对象的。那么问题就迎刃而解了。我们能够这样:

    function inheritPrototype(subType, superType){ 
    	function Obj()
    	{
    
    	}
    	Obj.prototype=superType.prototype;
    	var newObject=new Obj();
    	newObject.constructor = subType; 
    	subType.prototype = newObject; 
    }
    function People(name,arr)
    {
    	this.name=name;
    	this.friends=arr;
    }
    People.prototype.sayName=function()
    {
    	console.log(this.name);
    }
    function Student(id,name,arr)
    {
    	People.call(this,name,arr);
    	this.id=id;
    }
    inheritPrototype(Student,People);
    Student.prototype.sayId=function()
    {
    	console.log(this.id);
    }
    var stu1=new Student(1,"I",["bob"]);
    console.log(stu1);

    在inheritPrototype函数里,我先新建了一个类,然后将这个类的原型指向了父类的原型,然后再实例化一个对象。这时我为这个对象的constructor赋值,那么这个constructor属性就会存在于这个对象上,而不会去改动原型对象的constructor。唯一的缺点就是多了一重继承。可是这是最好的继承方式,我们来看看结果:


    看上去就完美了。这就是比較好的继承方式。写到末尾,我想说写博客确实不错。不仅帮助了大家。也帮助了自己,大家一起成长,一起进步!

  • 相关阅读:
    Windows平台下Android应用抓包挖掘漏洞方法
    长城宽带核心系统存严重漏洞,数十万用户、账单信息存泄露风险
    互联网公司站点通病之弱口令
    【Python】python-一个class继承的小case
    【Python】Python-skier游戏[摘自.与孩子一起学编程]
    【Python】一个python实例:给重要的文件创建备份.摘自crossin-python简明教程
    【JMeter】JMeter完成一个java请求的压测
    【Tcpcopy】离线回放功能
    【JMeter】Jmeter-完成一个http压力测试
    Apache-AB压力测试实例
  • 原文地址:https://www.cnblogs.com/wzjhoutai/p/6800410.html
Copyright © 2020-2023  润新知