在讨论原型继承之前,先回顾一下关于创建自定义类型的方式,这里推荐将构造函数和原型模式组合使用,通过构造函数来定义实例自己的属性,再通过原型来定义公共的方法和属性。

这样一来,每个实例都有自己的实例属性副本,又能共享同一个方法,这样的好处就是可以极大的节省内存空间。同时还可以向构造函数传递参数,十分的方便。

这里还要再讲一下两种特色的构造函数模式:

1.寄生构造函数
从形式上来看,这种模式和工厂模式并无区别:

function Person(name, age, job){
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function(){
alert(this.name);
};
return o;
}
var friend = new Person("Nicholas", 29, "Software Engineer");
friend.sayName(); //"Nicholas"

都是在内部创建一个Object对象实例,再赋予属性和方法,最后返回,这种构造模式的好处是,对于原生的引用类型创建的实例,例如Array,想为实例创建新的方法或者属性时,因为不建议直接修改原生的Array引用类型的构造函数,所以可以利用寄生构造函数:

function SpecialArray(){
//创建数组
var values = new Array();
//添加值
values.push.apply(values, arguments);
//添加方法
values.toPipedString = function(){
return this.join("|");
};
//返回数组
return values;
}
var colors = new SpecialArray("red", "blue", "green");
alert(colors.toPipedString()); //"red|blue|green"

通过在内部创建一个Array实例,并添加新的方法,最后将这个实例返回,既没有修改原生的Array构造函数,又成功添加了自定义的方法和属性。

缺点:使用寄生构造函数有一个缺点,那就是返回的实例与构造函数或构造函数原型属性之间没有关系,与在构造函数外创建实例没有区别,也无法通过instanceof来确定对象类型,因此有其他更好选择的时候,不推荐使用该方法。

2.稳妥构造函数

稳妥构造函数与寄生构造函数类似,但是并不使用new和this(某些环境下禁止使用),前面的函数可以改写成这样:

function Person(name, age, job){
//创建要返回的对象
var o = new Object();

//可以在这里定义私有变量和函数
//添加方法
o.sayName = function(){
alert(name);
};
//返回对象
return o;
}

说完这些,现在来谈谈原型继承和原型链,所谓继承,基本思想是利用原型让一个引用类型继承另一个引用类型的方法和属性。每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的。大家要记住,所有函数的默认原型都是Object 的实例,因此默认原型都会包含一个内部指针,指向Object.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;
}
//继承方法
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

SuperType 构造函数定义了两个属性:name 和colors。SuperType 的原型定义
了一个方法sayName()。SubType 构造函数在调用SuperType 构造函数时传入了name 参数,紧接着
又定义了它自己的属性age。然后,将SuperType 的实例赋值给SubType 的原型,然后又在该新原型
上定义了方法sayAge()。这样一来,就可以让两个不同的SubType 实例既分别拥有自己属性——包
括colors 属性,又可以使用相同的方法了。

原型式继承(借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型)

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"

在没有必要兴师动众地创建构造函数,而只想让一个对象与另一个对象保持类似的情况下,原型式
继承是完全可以胜任的。不过别忘了,包含引用类型值的属性始终都会共享相应的值,就像使用原型模
式一样。

寄生式继承(寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象

function createAnother(original){
var clone = object(original); //通过调用函数创建一个新对象
clone.sayHi = function(){ //以某种方式来增强这个对象
alert("hi");
};
return clone; //返回这个对象
}

寄生组合式继承

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

关于JavaScript的原型继承与原型链的更多相关文章

  1. JS面向对象(2) -- this的使用,对象之间的赋值,for...in语句,delete使用,成员方法,json对象的使用,prototype的使用,原型继承与原型链

    相关链接: JS面向对象(1) -- 简介,入门,系统常用类,自定义类,constructor,typeof,instanceof,对象在内存中的表现形式 JS面向对象(2) -- this的使用,对 ...

  2. JavaScript中的继承(原型链)

    一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.pro ...

  3. 深入理解JavaScript中的继承:原型链篇

    一.何为原型链 原型是一个对象,当我调用一个对象的方法时,如果该方法没有在对象里面,就会从对象的原型去寻找.JavaScript就是通过层层的原型,形成原型链. 二.谁拥有原型 任何对象都可以有原型, ...

  4. JavaScript中的继承与原型链

    先看一个例子 function User(){} var u1 = new User(); console.log(u1.prototype);// undefined 使用对象实例无法访问到prot ...

  5. JavaScript 类式继承与原型继承

    交叉着写Java和Javascript都有2年多了,今天来总结下自己所了解的Javascript类与继承. Javascript本身没有类似Java的面向对象的类与继承术语,但其基于原型对象的思想却可 ...

  6. 闲聊javascript继承和原型

    javascript继承已经是被说烂的话题了,我就随便聊一点~ 一.javascript的复制继承 javascript的继承有复制继承和原型继承,基于复制继承用的不太多,而且无法通过instance ...

  7. 面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统

    面向对象的JavaScript --- 原型模式和基于原型继承的JavaScript对象系统 原型模式和基于原型继承的JavaScript对象系统 在 Brendan Eich 为 JavaScrip ...

  8. JS高级. 03 混入式继承/原型继承/经典继承、拓展内置对象、原型链、创建函数的方式、arguments、eval、静态成员、实例成员、instanceof/是否在同一个原型链

    继承:当前对象没有的属性和方法,别人有,拿来给自己用,就是继承 1 混入式继承 var I={ }; var obj = { name: 'jack', age:18, sayGoodbye : fu ...

  9. call()和原型继承的方法

    1.call() call()方法接受两个参数,obj和arg 比如functionA.call(obj,arg)   就是说现在运行(执行)functionA这个方法,但是functionA里面的方 ...

随机推荐

  1. 查看php相关信息

    1.最常见的就是 创建一个  php页面  ,例如 test.php,  内容如下 <?php phpinfo();?> 直接访问 这个页面,就可以看到php的 信息了 2.其它方法  直 ...

  2. 【转】关于apt源配置的问题

    涉及的基本配置文件: apt核心配置文件集中在 /etc/apt 其中,管理软件来源的配置文件如下 sources.list                           // 主要软件源 so ...

  3. codewars--js--Write Number in Expanded Form—filters、map、reduce、forEach

    问题描述: you will be given a number and you will need to return it as a string in Expanded Form. For ex ...

  4. Shiro知识初探(更新中)

    Shiro 是当下常见的安全框架,主要用于用户验证和授权操作. RBAC 是当下权限系统的设计基础,同时有两种解释:一: Role-Based Access Control,基于角色的访问控制即,你要 ...

  5. centos5,6的GRUB简介

    grub:GRand Unified Bootloader grub 0.x:grub legacy(centos5,6) grub 1.x:grub2(centos7) grub legacy(gr ...

  6. Python爬虫实战教程:爬取网易新闻;爬虫精选 高手技巧

    前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. stars声明很多小伙伴学习Python过程中会遇到各种烦恼问题解决不了.为 ...

  7. 小程序封装request请求

    //request.js var host = 'https://www.xxx.com';//请求域名 module.exports = function (type, params, method ...

  8. Openshift与Kubernetes的区别

    Openshift与Kubernetes的区别 Openshift首个支持企业级 Java 的 PaaS 平台,支持 JEE6 与 JBoss 和其 Eclipse 集成开发环境以及 Maven 和 ...

  9. mysql必知必会--使用MySQL

    连接 在具有可供使用的MySQL DBMS和客户机软件之后,有必要简要讨 论一下如何连接到数据库. MySQL与所有客户机 - 服务器DBMS一样,要求在能执行命令之前登 录到DBMS.登录名可以与网 ...

  10. 为什么你SQL Server中SQL日期转换出错了呢?

    开发人员有时候使用类似下面SQL将字符串转换为日期时间类型,乍一看,这样的SQL的写法是没有什么问题的.但是这样的SQL其实有时候就是一个定时炸弹,随时可能出现问题(),下面简单对这种情况进行一个简单 ...