摘要:构造函数通过原型继承了构造函数和原型,这就形成了一个链条,通俗的讲就是原型链继承。而且方法只能冒充构造函数里面的属性和方法而无法冒充原型对象里面的属性和方法还有最大的问题就是重复使用。
前言: 写到这里,差不多就把OOP完结了,写了几篇OOP的文章,但是只是略懂皮毛,可能深入的OOP还有很多,但是我感觉写到这里也算是差不多完结了。
继承
继承是面向对象比较核心的概念,其他语言可能实现继承有两种方式:接口,继承。而ECMAscript只有继承。
原型链继承
通俗的讲,就是通过构造函数的原型对象去继承父类。上一篇文章我们说过。继承最大的优点也是缺点就是共享,看代码:
function First() { //创建一个构造函数(作为父类) this.a = "abc"; //添加属性 } function Second() { //另一个构造函数(作为派生类也称为子类) this.b = "10"; //同上 } Second.prototype = new First(); //子类的原型对象添加父类的实例。 var box = new Second(); //实例化并赋值给一个变量 alert(box.a); //返回abc
大家看的出,第二个构造函数内并没有a这个属性,但是我们从原型去添加一个父类的实例化,就能继承父类的构造体内的和原型对象。
Second构造函数通过原型继承了First构造函数和原型,这就形成了一个链条,通俗的讲就是:原型链继承。
也可以这么说,用对象实例化赋值给子类的原型属性,会将父类的构造函数里面的信息和原型里面的信息都交给子类。
重谈原型:还是那句话,字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。
对象冒充
不知道大家发现没有,父类是无法传参的,而且引用共享的问题,我们可以使用对象冒充的方法去实现继承。
function First (b) { //创建一个构造函数并传参 this.a = ["a","b","c"]; //添加一个属性为一个数组 this.b = b; //添加属性得到传进去的值 } function Second (b) { //同上 First.call(this,b); //对象冒充 } var second = new Second(100); //实例化子类并赋值给变量 alert(second.a); //返回a,b,c alert(second.b); //返回100
从上面的代码我们可以看出,我们解决了父类传参问题,也解决了引用共享问题。但是没有原型。而且call方法只能冒充构造函数里面的属性和方法而无法冒充原型对象里面的属性和方法
还有最大的问题就是重复使用。
我们来用代码证明上面的话,就是call冒充只是冒充构造函数里面的方法和属性。
/*alert(second.a); 返回a,b,c */ second.a.push("d"); //给数组末尾添加一个d alert(second.a); //返回a,b,c,d
从上面代码看出,并没有继承原型,也就是共享。重复使用更是不可能的。
原型链+冒充
当然我们可以变通一下,将上面两种方法结合一下不就达到效果了么!我们大概的思想是该私有化的属性和方法就私有化,该共享的公有化的方法就放在原型里面不就得了!
function First (b) { this.a = ["a","b","c"]; this.b = b; } First.prototype.c = function () { //公有化方法放在原型中 return this.a + this.b; }; function Second (b) { First.call(this,b); //对象冒充 } Second.prototype = new First(); //子类的原型对象添加父类的实例 var second = new Second(100); //实例化并赋值给变量 alert(second.c()); 返回a,b,c10
从上面的例子用可以看出,我们将我们不想共享的属性和方法放在构造函数中,而我们想私有化的方法放在原型对象中,达到了清晰代码的作用,而且解决了重复使用和传参的问题并且有了原型!
总结:
说了这么多,其实Javascript中实现继承是十分灵活的,并没有一种最好的方法,需要根据不同的需求实现不同方式的继承,最重要的是要理解Javascript中实现继承的原理,也就是原型和原型链的问题,只要理解了这些,自己也就可以很轻松实现继承了。
Brian.Lee
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/91320.html
摘要:构造函数上一章我们讲了工厂模式,它的缺点就是无法识别到底哪个属于哪个的问题。我们可以用构造函数来解决这个识别问题。来比较构造函数内的值就可以看出到底是什么类型。 构造函数 上一章我们讲了工厂模式,它的缺点就是无法识别到底哪个属于哪个的问题。我们可以用构造函数来解决这个识别问题。 //构造函数 function Create(a,b) { this.a =a; this...
摘要:工厂模式优点集中实例化,可以传参等缺点分不清属于哪个对象我们先来谈谈优点,看例子集中实例化返回实例化对象返回返回不难看出,工厂模式比上面的例子减少了很多代码。 ECMAscript开发的两种模式:1.过程化 2.OOP(面向对象) 面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性的方法的对象。但是ECMAscript中没有类的概念! 又谈作用域 首先...
摘要:上一章我们谈了构造函数,他的唯一特点就是比较了地址不相同,因为大家知道引用类型是比较的引用。也就是说不用在构造函数中定义对象实例,而是直接将这些添加到原型当中。如果构造函数实例里面没有,就去原型里面查找,如果有就立即返回。 上一章我们谈了构造函数,他的唯一特点就是比较了地址不相同,因为大家知道引用类型是比较的引用。我们来谈谈原型。 原型 我们每创建一个函数都有一个原型(prototyp...
摘要:面向对象面向对象编程的全称是,简称,面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式。面向对象编程的三个主要特征是封装继承多态。 面向对象 面向对象编程的全称是Object Oriented Programming,简称OOP,面向对象编程是用抽象方式创建基于现实世界模型的一种编程模式。面向对象编程可以看做是使用一系列对象相互协作的软件设计,面向对象程序设计的目的是在编程中促...
摘要:而哈士奇区别于普通狗,又有新的特征逗比,爱捣乱为了保证类之间的松绑定,通常会继承抽象类,而且是浅继承只有一层子类。如果知道所有类都会共享一个公共的行为实现,就使用抽象类,并在其中实现该行为。 为什么使用OOP OOP是一个模块化的过程,目的是为了把复杂问题简单化,一个模块解决一个复杂问题的某一个方面,即一个类应当只有一个职责 OOP区别于顺序式编程与过程式编程,在于: 1.顺序编程...
阅读 6724·2021-09-22 15:36
阅读 5612·2021-09-02 10:20
阅读 1843·2019-08-30 15:44
阅读 2620·2019-08-29 14:06
阅读 1106·2019-08-29 11:17
阅读 1537·2019-08-26 14:05
阅读 3046·2019-08-26 13:50
阅读 1520·2019-08-26 10:26