js对面向对象的支持很弱,所以在ES6之前实现继承会绕比较多的弯(类似于对面向对象支持弱,然后强行拼凑面向对象的特性)
es5中实现继承的几种方式,父类定义为Super
    function Super(name){
this.name=name;
this.age=;
this.array=[,,];
this.obj={a:'prop'};
this.say=function(){
console.log(this.name);
}
}
Super.prototype.testInherit=function(){
console.log('I am method of super prototype')
}
 1.构造函数继承
简单的在子类构造函数调用父类构造函数,类似就是直接把父类构造函数执行一遍,属性拷贝一份过来此种继承方式导致原型链断了,无法实现真正意义上的继承,
child1.testInherit();
这个调用会报错,因为child1并没有在Super的原型链上,导致无法调用其原型的方法;同时因为是拷贝的一份父类的属性方法,所以子类改动引用类型的属性并不会影响其他子类的属性
    function Child1(name){
Super.apply(this,arguments);
this.name=name;
this.sayName=function(){
console.log(this.name);
}
}
var parent=new Super('lucy');
var child1=new Child1('jack');
var child1=new Child1('jack2');
console.log(parent,child1);
console.log(child1.__proto__===Child1.prototype,child1 instanceof Super);//true flase
child1.array.push();
console.log(child1.array,child2.array,s1.array,);
child1.testInherit();
2.使用原型链继承
最基本的思想,把子类的原型设置为父类的实例
   function Child2(name){
this.name=name;
this.sayName=function(){
console.log(this.name);
}
}
var parent=new Super('lucy');
Child2.prototype=parent;
var child1=new Child2('jack');
var child2=new Child2('jack2');
child1.array.push();
child1.obj.b="prop2";
console.log(child1.array,child2.array,child1.obj,child2.obj);
console.log(child1.constructor);
修改一个实例继承的引用属性,可以看到其他所有实例所继承的属性都被修改了(他们引用的都是同一个地址),并且子类实例的构造函数被修改了
前面1和2是继承的两种基本模式,也是其他继承实现的基础
 
3.使用组合继承方式
保证实例继承属性私有化并且保证原型链不断
   function Child3(name){
Super.apply(this,arguments);
this.name=name;
}
var parent=new Super('lucy');
Child3.prototype=parent;
var child1=new Child3('jack');
var child2=new Child3('jack2');
child1.array.push();
console.log(child1.array,child2.array);
console.log(child1.constructor);
 此种方式可以实现继承可以保证原型回溯,同时实例继承的引用类型的属性互不影响;不过父类的构造函数调用了两次,子类的实例的构造函数变成了Super,可以做进一步优化
 
4. 针对上面的组合继承父类的构造函数调用了2次的改进,可以将子类的原型直接设置为父类的原型,如下所示
    function Child4(name){
Super.apply(this,arguments);
this.test=;
}
Child4.prototype=Super.prototype;//改进父类构造函数调用两次问题
Child4.prototype.constructor=Child4;
var child1=new Child4('bob');
var child2=new Child4('bob2');
console.log(child1.__proto__===Child4.prototype);
console.log(child1.__proto__.constructor,'\n',Child4.prototype.constructor,'\n',Super.prototype.constructor); console.log(Super.prototype.constructor); //这种方法改变了父类的构造函数
for(var itm in Child4.prototype){
console.log(itm);
}
    // 或者使用Object.create()创建一个过渡对象--这样子类重新定义构造函数,就能使父类和子类各有自己的构造函数
function Child5(name){
Super.apply(this,arguments);
this.test=;
} Child5.prototype=Object.create(Super.prototype);
Child5.prototype.constructor=Child5;
Object.defineProperty(Child5.prototype,'constructor',{//Child5的原型是一个实例对象,所以显示的定义constructor会改变其不可枚举的特性,这里修正一下
enumerable:false
});
var child=new Child5('end');
console.log(Child5.prototype.constructor,Super.prototype.constructor);
console.log(child instanceof Child5,child instanceof Super);
console.log(child.constructor,Child5.prototype.isPrototypeOf(child),Super.prototype.isPrototypeOf(child));
for(var itm in Child5.prototype){
console.log(itm);
}
5.组合寄生继承模式(js高程中推荐的实现)
其实这种模式跟上面的第4-2的实现没有大的区别,不过上边的中间对象是Object.create()创建的,这里是自己创建
    function inheritProperty(sup,child){
function F(){};
F.prototype=sup.prototype;
var inner=new F();
inner.constructor=child;
child.prototype=inner;
Object.defineProperty(child.prototype,'constructor',{
enumerable:false
});
}
function Child6(name){
this.age=;
this.name=name;
}
inheritProperty(Super,Child6);
Child6.prototype.sayAge=function(){
return this.age;
}
var child=new Child6('end');
console.log(child.constructor);
console.log(Child6.prototype.constructor);
console.log(child.sayAge());

以上继承都是以1,2为基础的,具体说实现继承的方式就这两种,其他只是对这两种的组合改造优化

 

js继承的实现(es5)的更多相关文章

  1. js继承精益求精之寄生式组合继承

    一.混合/组合继承的不足 上一篇JS继承终于混合继承,认真思考一下,发现其还是有不足之处的: 空间上的冗余:在使用原型链的方法继承父类的原型属性(Animal.prototype)的同时,也在子类的原 ...

  2. JS--我发现,原来你是这样的JS:面向对象编程OOP[3]--(JS继承)

    一.面向对象编程(继承) 这篇博客是面向对象编程的第三篇,JS继承.继承顾名思义,就是获取父辈的各种"财产"(属性和方法). 怎么实现继承? 我们的JavaScript比较特别了, ...

  3. JS继承的一些见解

    JS继承的一些见解 js在es6之前的继承是五花八门的.而且要在项目中灵活运用面向对象写法也是有点别扭,更多的时候还是觉得面向过程的写法更为简单,效率也高.久而久之对js的继承每隔一段时间就会理解出现 ...

  4. js继承(自备水,这非常干货)

    讲js继承之前,想一想什么是继承? 生活中有很多例子,比方说继承财产,继承女朋友的前男友的前女友 ヽ(ー_ー)ノ ,这些和js继承差不多,但是有一个不一样的地方,就是继承过后,原先的人就没有了,js继 ...

  5. 一篇文章理解JS继承——原型链/构造函数/组合/原型式/寄生式/寄生组合/Class extends

    说实在话,以前我只需要知道"寄生组合继承"是最好的,有个祖传代码模版用就行.最近因为一些事情,几个星期以来一直心心念念想整理出来.本文以<JavaScript高级程序设计&g ...

  6. js继承的方式及其优缺点

    js继承方法 前因:ECMAScript不支持接口继承,只支持实现继承 一.原型链 概念:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针,让 ...

  7. 让我们纯手写一个js继承吧

    继承在前端逻辑操作中是比较常见的,今天我们就从零开始写一个js的继承方式 在es5中继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上Parent.call(this),在es6中则 ...

  8. 简单易懂的JS继承图解

    JS继承的实现方式一共有八种.下面我们来一个一个瞅一下.注意️:文章依据个人理解,难免有问题,还望各位及时指出!!!!! 原型链继承 借用构造函数继承 组合继承 原型式继承 寄生继承 寄生组合式继承 ...

  9. js继承

    js继承有5种实现方式: 继承第一种方式:对象冒充 function Parent(username){ this.username = username; this.hello = function ...

  10. js继承之call,apply和prototype随谈

    在js中,call,apply和prototype都可以实现对象的继承,下面我们看一个例子: function FatherObj1() { this.sayhello = "I am jo ...

随机推荐

  1. awk基础03-分支和循环语句

        awk既然是一门解释型语言,则就可以支持如分支语句.循环语句等.今天就来学习一下在awk中的分支和循环语句.如果您有过任何一门编程语言的基础,则下面所讲内容也是很好理解的. 分支语句 if-e ...

  2. D3.js的基础部分之数组的处理 映射(v3版本)

    映射(Map)   映射(Map)是十分常见的一种数据结构,由一系列键(key)和值(value)组成的.每个key对应一个value,根据key可以获取和设定value,也可以根据key来查询val ...

  3. 更改kvm虚拟机磁盘大小

    kvm 虚拟机的磁盘大小可通过命令:qemu-img resize filename size 来改,要注意的是resize只支持raw格式的磁盘文件,如果想更改qcow2等格式的磁盘大小,需先用qe ...

  4. 关于类属性值校验的一点记录 【知识点Attribute】

    好久没有进来了,之前励志坚持写博客,记录自己在做代码搬运工这段历程中点滴,可是仅仅只坚持了几天,就放弃了!果然是,世上无难事,只要肯放弃!哈哈……闲话不多说,开始进入正题,给自己留点笔记,避免将来老了 ...

  5. django系列5.3--ORM数据库的多表操作

    首先来创建一个模型,数据库的关系就清楚了 models.py from django.db import models # Create your models here. class Author( ...

  6. linux - 【LAMP环境配置安装注意安装步骤】 9

    (一)安装gcc glibc-devel glibc-headers ==>依赖项 kernel-headers ==>依赖项 libgomp gcc-c++ libstdc++-deve ...

  7. 【ocp-12c】最新Oracle OCP-071考试题库(47题)

    47.(10-6)choose two You need to calculate the number of days from 1st January 2007 till date. Dates ...

  8. 【OCP|052】OCP最新题库解析系列-2

    2.Which two are true about Optimizer Statistics? ❑ A) They do not persist across Instance restarts. ...

  9. JAVA中Date类的使用

    一. Date类 Date类对象的创建: 1.创建一个当前时间的Date对象 //创建一个代表系统当前日期的Date对象 Date d = new Date(); 2.创建一个我们指定的时间的Date ...

  10. PRINT语句详解

    首先摘自联机丛书中的PRINT语法如下: PRINT msg_str | @local_variable | string_exp  以上可看出PRINT语句的输出参数均为字符或字符串的常量或变量 - ...