zoukankan      html  css  js  c++  java
  • 对象的继承

    fucntion Person(name,sex){    //父类

      this.name=name;

      this.sex=sex;

    }

    Person.prototype.showName=function(){

      alert(this.name);

    }

    function Star(){}    //子类

    现在有一个新的对象 Star,去继承Person,并给Star添加自己的新属性job,和新方法 sing。

     

    对象的属性继承和方法继承。

    属性继承:通过父类的构造函数继承(使用call函数);

    //属性继承:调用父类的call

    fucntion Star(name,sex,job){

        // ❌   Person(name,sex)    //如果直接用Person(),因为函数Person()直接被调用,所以Person函数中的this指向的是window。

      Person.call(this,name,sex)    //继承Person的属性,使用call。使用call函数,将this指向为新创建的对象p2。 

      this.job=job;

    }

    但是方法继承的时候我们不能直接使用原型赋值

    //❌ Star.prototype=Person.prototype;  //为对象赋给对象,为对象的引用,所以这两个对象指向的是同一存储空间,任意一个对象的修改都会引起另一个的变化。因此,我们要将对象的赋值改变为基本类型的赋值。

    继承:拷贝继承、类式继承、原型继承

    1、拷贝继承(for in)  ( jquery的extend函数也是拷贝继承。$.extend(),当把第一个参数设置为true时,为深拷贝)

    封装extend函数:(将obj2拷贝给obj1)

    function extend(obj1,obj2){
      for(var attr in obj2){
        obj1[attr]=obj2[attr];
      }
    }

     

    使用方法:extend(Child.prototype,Parent.prototype);   

    这种拷贝写法适合所有属性都是基本类型的对象。当某个属性为一个数组或是一个对象时,这样的拷贝无法实现数组、对象的真正拷贝。也就是这种写法实际上是浅拷贝。

    若想实现深拷贝,只要递归调用浅拷贝方法即可:

    function extend(obj1,obj2){
      for(var attr in obj2){
           if (typeof obj2[i] === 'object') {  //当某个属性的值为一个对象时,需要递归调用extend
          obj1[i] = (obj2[i].constructor ===  Array) ? [] : {};  //创建空的数组或对象
          extend(obj1[i], obj2[i]);
        } else {
          obj1[attr]=obj2[attr];
        }  
      }
    }    

     

    在这个例子中:extend(Star.prototype,Person.prototype);

    Star.prototype.sing=function(){

      alert('sing a song');

    }

    2、类式继承(构造函数)

    JS中没有类,但是我们可以把JS中的构造函数看作类。

    Star.prototype=new Person();   //用父类的实例,赋值给子类的原型。它相当于完全删除了prototype 对象原先的值,然后赋予一个新值。

    //这时,Star.Prototype.constructor=Person,这显然会导致继承链的紊乱,因此我们必须手动纠正,将Star.prototype对象的constructor值改为Star。

    Star.Prototype.constructor=Star;  

    另外一个问题:当我们创建两个实例:

    s1=new Star();

    s2=new Star(); //测试会发现s1和s2之间的属性不是独立的,因为它们的继承都来自Person。当s1的属性变化时,s2也会受到影响。为了避免这个问题,我们需要属性和方法分开继承。

    我们需要一个空对象,作为中间桥梁:

    var F=funtion(){};

    F.prototype=Person.prototype;

    所以最终的类式继承,需要4句话:

    var F=funtion(){};
    F.prototype=Person.prototype;  //只会复制方法,属性并没有复制。
    Star.prototype=new F(); //所以这时候Star只是接收了父类的方法,而没有接收父类的属性。要想继承父类的属性,仍然使用Person.call(this)的方法。this的指向不同,因此s1和s2的属性不会相互干扰。
    Star.prototype.constructor=Star;

     

    3、原型继承(借助prototype)

    var A={

      name:'a';

    }

    var B=cloneObj(A);

    function cloneObj(obj){

      var F=function(){};

      F.prototype=obj;

      return new F();

    }

    B继承了A。且B和A的属性相互独立。

     

    总结:

    (1)拷贝继承:通用

    (2)类式继承:适合通过new构造函数

    (3)原型继承:适合无new的对象

     

  • 相关阅读:
    将 Web 项目从 Visual Studio .Net 2002/2003 转换到 Visual Studio 2005 的分步指南
    用 ASP.NET 2.0 改进的 ViewState 加快网站速度
    SQL行列转换实战
    分页存储过程
    分布式系统设计套件
    ASP.NET 2.0 本地化功能:本地化 Web 应用程序的新方法
    在 ASP.NET 页面中使用 TreeView 控件
    SQL Server中的几个方法和Transact SQL 常用语句以及函数[个人推荐]
    ASP.NET 常见问题 和 网页上加上百度搜索
    两台SQL Server数据同步解决方案
  • 原文地址:https://www.cnblogs.com/telnetzhang/p/5821114.html
Copyright © 2011-2022 走看看