学习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 相关文章推荐
Jquery选中或取消radio示例
Sep 29 Javascript
angularjs中的单元测试实例
Dec 06 Javascript
简介JavaScript中strike()方法的使用
Jun 08 Javascript
node.js入门实例helloworld详解
Dec 23 Javascript
Bootstrap每天必学之滚动监听
Mar 16 Javascript
JS 事件绑定、事件监听、事件委托详细介绍
Sep 28 Javascript
概述如何实现一个简单的浏览器端js模块加载器
Dec 07 Javascript
JavaScript字符串对象(string)基本用法示例
Jan 18 Javascript
vue实现树形菜单效果
Mar 19 Javascript
脚手架vue-cli工程webpack的作用和特点
Sep 29 Javascript
微信网页登录逻辑与实现方法
Apr 29 Javascript
Node使用Selenium进行前端自动化操作的代码实现
Oct 10 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
不要轻信 PHP_SELF的安全问题
2009/09/05 PHP
jQuery+PHP实现的掷色子抽奖游戏实例
2015/01/04 PHP
php使用post数组的键值创建同名变量并赋值的方法
2015/04/03 PHP
PHP结合jQuery实现找回密码
2015/07/22 PHP
ThinkPHP5分页paginate代码实例解析
2020/11/10 PHP
被jQuery折腾得半死,揭秘为何jQuery为何在IE/Firefox下均无法使用
2010/01/22 Javascript
JS小功能(onmouseover实现选择月份)实例代码
2013/11/28 Javascript
javascript 用函数语句和表达式定义函数的区别详解
2014/01/06 Javascript
JS+CSS实现自动改变切换方向图片幻灯切换效果的方法
2015/03/02 Javascript
实例详解angularjs和ajax的结合使用
2015/10/22 Javascript
jQuery中$.ajax()方法参数解析
2016/10/22 Javascript
使用localStorage替代cookie做本地存储
2019/09/25 Javascript
[01:06] DOTA2英雄背景故事第三期之秩序法则光之守卫
2020/07/07 DOTA
Python中的生成器和yield详细介绍
2015/01/09 Python
详解Python中的Numpy、SciPy、MatPlotLib安装与配置
2017/11/17 Python
python3 爬取图片的实例代码
2018/11/06 Python
Python操作redis实例小结【String、Hash、List、Set等】
2019/05/16 Python
详解Python 切片语法
2019/06/10 Python
PyQt5组件读取参数的实例
2019/06/25 Python
python scrapy重复执行实现代码详解
2019/12/28 Python
python连接PostgreSQL过程解析
2020/02/09 Python
python中数据库like模糊查询方式
2020/03/02 Python
django执行原始查询sql,并返回Dict字典例子
2020/04/01 Python
基于python实现简单网页服务器代码实例
2020/09/14 Python
如何用python 操作zookeeper
2020/12/28 Python
CSS3 实现弹跳的小球动画
2020/10/26 HTML / CSS
周鸿祎:教你写创业计划书
2013/12/30 职场文书
党支部对照检查材料
2014/08/25 职场文书
个人整改措施书面材料
2014/10/24 职场文书
12.4全国法制宣传日活动方案
2014/11/02 职场文书
写给医院的感谢信
2015/01/22 职场文书
十二生肖观后感
2015/06/12 职场文书
高考要来啦!用Python爬取历年高考数据并分析
2021/06/03 Python
Python 详解通过Scrapy框架实现爬取CSDN全站热榜标题热词流程
2021/11/11 Python
Python+Tkinter制作专属图形化界面
2022/04/01 Python
win10此电脑打不开怎么办 win10双击此电脑无响应的解决办法
2022/07/23 数码科技