学习javascript面向对象 javascript实现继承的方式


Posted in Javascript onJanuary 04, 2016

本文实例为大家介绍了javascript实现继承的6种方式,分享给大家供大家参考,具体内容如下

1、【原型链继承】实现的本质是重写原型对象,代之以一个新类型的实例。实际上不是SubType的原型的constructor属性被重写了,而是SubType的原型指向了另一个对象——SuperType的原型,而这个原型对象的construtor属性指向的是SuperType

function SuperType(){
 this.property = true;
}
SuperType.prototype.getSuperValue = function(){
 return this.property;
};
function SubType(){
 this.subproperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function(){
 return this.subproperty;
}
var instance = new SubType();
alert(instance.getSuperValue());//true

[注意1]谨慎地定义方法,给原型添加方法的代码一定要放在替换原型的语句之后

function SuperType(){
 this.property = true;
}
SuperType.prototype.getSuperValue = function(){
 return this.property;
};
function SubType(){
 this.subproperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();

//添加了新方法
SubType.prototype.getSubValue = function(){
 return this.subproperty;
}
//重写超类型的方法
SubType.prototype.getSuperValue = function(){
 return false;
}
var instance = new SubType();
alert(instance.getSuperValue());//false

[注意2]通过原型链实现继承时,不能使用对象字面量创建原型方法,这样做会重写原型链

function SuperType(){
 this.property = true;
}
SuperType.prototype.getSuperValue = function(){
 return this.property;
};
function SubType(){
 this.subproperty = false;
}
//继承了SuperType
SubType.prototype = new SuperType();

//使用字面量方法添加新方法会导致上一行代码无效
SubType.prototype = {
 getSubValue : function(){
  return this,subproperty;
 },
 someOtherMethod : function(){
  return false;
 }
};
var instance = new SubType();
alert(instance.getSuperValue());//error

[缺点1]在创建子类型的实例时,不能向超类型的构造函数中传递参数
[缺点2]包含引用类型值的原型属性会被所有实例共享

function SuperType(){
 this.colors = ['red','blue','green'];
}
function SubType(){}
//继承了SuperType
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push('black');
alert(instance1.colors);//'red,blue,green,black'
var instance2 = new SubType();
alert(instance2.colors);//'red,blue,green,black'

2、【借用构造函数继承(又叫伪造对象或经典继承)】在子类型构造函数的内部调用超类型构造函数,因此通过使用apply()和call()方法也可以在将来新创建的对象上执行构造函数

function SuperType(){
 this.colors = ['red','blue','green'];
}
function SubType(){
 //继承了SuperType
 SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push('black');
alert(instance1.colors);//'red,blue,green,black'
var instance2 = new SubType();
alert(instance2.colors);//'red,blue,green'

[优点]传递参数

function SuperType(name){
 this.name = name;
}
function SubType(){
 //继承了SUperType,同时还传递了参数
 SuperType.call(this,"Nicholas");
 //实例属性
 this.age = 29;
}
var instance = new SubType();
alert(instance.name);//"Nicholas"
alert(instance.age);//29

[注意]为了确保SuperType构造函数不会重写子类型的属性,可以在调用超类型构造函数后,再添加应该在子类型中定义的属性

function SuperType(name){
 this.name = name;
 this.age = 30;
}
function SubType(){
 //实例属性
 this.age = 29;
 //继承了SUperType,同时还传递了参数
 SuperType.call(this,"Nicholas");
}
var instance = new SubType();
//实例属性被重写为SuperType构造函数的属性
alert(instance.age);//30

[缺点1]无法实现函数复用
[缺点2]在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式
3、【组合继承(又叫伪经典继承)】将原型链和借用构造函数的技术组合到一起,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性,成为JavaScript中最常用的继承模式。

function SuperType(name){
 this.name = name;
 this.colors = ['red','blue','green'];
}
SuperType.prototype.sayName = function(){
 alert(this.name);
};
function SubType(name,age){
 //继承属性
 SuperType.call(this,name);
 this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
 alert(this.age);
}
var instance1 = new SubType("Nicholas",29);
instance1.colors.push("black");
alert(instance1.colors);//'red,blue,green,black'
instance1.sayName();//"Nicholas"
instance1.sayAge();//29
var instance2 = new SubType("Greg",27);
alert(instance2.colors);//'red,blue,green'
instance2.sayName();//"Greg"
instance2.sayAge();//27

[缺点]无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。子类型最终会包含超类型对象的全部实例属性,但不得不在调用子类型构造函数时重写这些属性。

function SuperType(name){
 this.name = name;
 this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
 alert(this.name);
};
function SubType(name,age){
 SuperType.call(this,name); // 第二次调用SuperType()
 this.age = age;
}
SubType.prototype = new SuperType(); //第一次调用SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
 alert(this.age);
};

4、【原型式继承】借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。从本质上讲,object()对传入其中的对象执行了一次浅复制。

[注意]原型式继承要求必须有一个对象可以作为另一个对象的基础,如果有这么一个对象的话,可以把它传递给object()函数,然后再根据具体需求对得到的对象加以修改即可

function object(o){
  function F(){};
  F.prototype = o;
  return new F();
}
var person = {
  name: "Nicholas",
  friends: ["Shelby","Court","Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");

alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"

【4.1】【Object.create()方法】:ECMAScript5新增Object.create()方法规范化了原型式继承。这个方法接收两个参数:一个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数情况下,Object.create()与object()方法的行为相同

function object(o){
 function F(){};
 F.prototype = o;
 return new F();
}
var person = {
 name: "Nicholas",
 friends:["Shelby","Court","Van"]
};
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"

[注意]Object.create()方法的第二个参数与Object.defineProperties()方法的第二个参数格式相同:每个属性都是通过自己的描述符定义的。以这种方式指定的任何属性都会覆盖原型对象上的同名属性。

var person = {
 name: "Nicholas",
 friends:["Shelby","Court","Van"]
};
var anotherPerson = Object.create(person,{
 name: {
  value: "Greg"
 }
});
alert(anotherPerson.name);//"Greg"

【4.2】低版本浏览器下兼容Object.create()方法

if(typeof Object.create != "function"){
 (function(){
  var F = function(){};
  Object.create = function(o){
   if(arguments.length > 1){
    throw Error('Second argument noe supported');
   }
   if(o === null){
    throw Error("Cannot set a null [[Prototype]]");
   }
   if(typeof o != 'Object'){
    throw TypeError("Arguments must be an object");
   }
   F.prototype = o;
   return new F();
  }
 })();
}

5、【寄生式继承】创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象
[缺点]无法实现函数复用

function object(o){
 function F(){};
 F.prototype = o;
 return new F();
}
function createAnother(original){
 var clone = object(original);//通过调用函数创建一个新对象
 clone.sayHi = function(){ //以某种方式来增强这个对象
  alert("hi");
 };
 return clone;//返回这个对象
}
var person = {
 name: "Nicholas",
 friends: ["Shelby","Court","Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();//"hi"

6、【寄生组合式继承】通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,所需的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承是引用类型最理想的继承范式。

//这个例子中的高效率体现在它只调用了一次Super构造函数,并且因此避免了在SubType.prototype上面创建不必要的、多余的属性。与此同时,原型链还能保持不变。
function object(o){
 function F(){};
 F.prototype = o;
 return new F();
}
function inheritPrototype(subType,superType){
 var prototype = object(superType.prototype);//创建对象
 prototype.constructor = subType;//增强对象
 subType.prototype = prototype;//指定对象
}
function SuperType(name){
 this.name = name;
 this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
 alert(this.name);
};
function SubType(name,age){
 SuperType.call(this,name);
 this.age = age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function(){
 alert(this.age);
}

以上就是本文的全部内容,javascript实现继承的方式,感谢大家的阅读,小编会再接再厉!

Javascript 相关文章推荐
cookie的复制与使用记住用户名实现代码
Nov 04 Javascript
ListBox实现上移,下移,左移,右移的简单实例
Feb 13 Javascript
JavaScript实现可拖拽的拖动层Div实例
Aug 05 Javascript
jQuery隐藏和显示效果实现
Apr 06 Javascript
第七章之菜单按钮图标组件
Apr 25 Javascript
全面理解JavaScript中的继承(必看)
Jun 16 Javascript
jquery  实现轮播图详解及实例代码
Oct 12 Javascript
angular实现图片懒加载实例代码
Jun 08 Javascript
在 Node.js 中使用原生 ES 模块方法解析
Sep 19 Javascript
vue组件文档(.md)中如何自动导入示例(.vue)详解
Jan 25 Javascript
原生js实现密码强度验证功能
Mar 18 Javascript
JS数组push、unshift、pop、shift方法的实现与使用方法示例
Apr 29 Javascript
学习javascript面向对象 掌握创建对象的9种方式
Jan 04 #Javascript
jQuery自动完成插件completer附源码下载
Jan 04 #Javascript
学习javascript面向对象 理解javascript对象
Jan 04 #Javascript
基于JavaScript实现移除(删除)数组中指定元素
Jan 04 #Javascript
实例代码详解javascript实现窗口抖动及qq窗口抖动
Jan 04 #Javascript
javascript基础语法学习笔记
Jan 04 #Javascript
封装好的javascript前端分页插件pagination
Jan 04 #Javascript
You might like
制作美丽的拉花
2021/03/03 冲泡冲煮
phpExcel导出大量数据出现内存溢出错误的解决方法
2013/02/28 PHP
[原创]PHP字符串中插入子字符串方法总结
2016/05/06 PHP
thinkphp5 加载静态资源路径与常量的方法
2017/12/24 PHP
Laravel 实现密码重置功能
2018/02/23 PHP
网站上面有这种切换效果
2006/06/26 Javascript
为javascript添加String.Format方法
2020/08/11 Javascript
Node.js中对通用模块的封装方法
2014/06/06 Javascript
javascript setinterval 的正确语法如何书写
2014/06/17 Javascript
jQuery 插件开发指南
2014/11/14 Javascript
JavaScript制作简易的微信打飞机
2015/03/31 Javascript
JS实现的不规则TAB选项卡效果代码
2015/09/18 Javascript
chrome调试javascript详解
2015/10/21 Javascript
JS函数的定义与调用方法推荐
2016/05/12 Javascript
Node.js的项目构建工具Grunt的安装与配置教程
2016/05/12 Javascript
js中url对象化管理分析
2017/12/29 Javascript
Node.js学习之内置模块fs用法示例
2020/01/22 Javascript
[02:51]2014DOTA2 TI小组赛总结中国军团全部进军钥匙球馆
2014/07/15 DOTA
python使用arp欺骗伪造网关的方法
2015/04/24 Python
Django视图和URL配置详解
2018/01/31 Python
对python 中class与变量的使用方法详解
2019/06/26 Python
Python实现基于socket的udp传输与接收功能详解
2019/11/15 Python
Python如何读取、写入CSV数据
2020/07/28 Python
关于探究python中sys.argv时遇到的问题详解
2021/02/23 Python
客服端调用EJB对象的几个基本步骤
2012/01/15 面试题
口头翻译求职人自荐信
2013/12/07 职场文书
企业内部培训方案
2014/02/04 职场文书
主题婚礼策划方案
2014/02/10 职场文书
六一节目主持词
2014/04/01 职场文书
给校长的建议书100字
2014/05/16 职场文书
工程项目经理任命书
2014/06/05 职场文书
大学生安全责任书
2014/07/25 职场文书
2014党员四风对照检查材料思想汇报
2014/09/17 职场文书
怀孕辞职信怎么写
2015/02/28 职场文书
综合测评自我评价
2015/03/06 职场文书
Mongo服务重启异常问题的处理方法
2021/07/01 MongoDB