js继承机制的实现


1. 继承的概念

  1. 说明继承的最经典的例子:几何形状。实际上,几何形状只有两种,即椭圆形(是圆形的)和多边形(具有一定数量的边)。圆是椭圆的一种,它只有一个焦点。三角形、矩形和五边形都是多边形的一种,具有不同数量的边。正方形是矩形的一种,所有的边等长。这就构成了一种完美的继承关系。
  2. 在该实例中,我想阐述的并不是继承的含义,而是说明几个关键词,即:基类 子类 超类 的含义。
  3. 在该实例中,圆形是椭圆形的子类,椭圆形是圆形的超类(父类);同样,三角形(Triangle)、矩形(Rectangle)和五边形(Pentagon)都是多边形的子类,多边形是它们的超类。


2. 继承的方式

  1. 对象冒充
    // 父类 ClassA
function ClassA(aColor){
this.color = aColor;
this.showColor = function(){
console.log(this.color);
}
}
// 子类 ClassB
function ClassB(bColor,bName){
this.newMethod = ClassA; // 函数名ClassA只是指向函数的指针,所以这里是将this.newMethod也指向ClassA这个函数,所以函数ClassB就拥有了函数ClassA的方法和属性
this.newMethod(bColor);
delete this.newMethod; // 该操作使得实例化的对象不需要多次继承同一个函数了,因为继承一次就可以了。注意:新增的属性和方法最好都写在 删除对另一个函数引用的后面,因为如果在前面定义的话,如果父类刚好有该属性或者方法你就会把父类的属性和方法 给覆盖掉。
this.name = bName;
this.sayName = function(){
console.log(this.name);
}
}
// --------------------------------------
var objA = new ClassA("blue");
var objB = new ClassB("red", "John");
objA.showColor(); // blue
objB.showColor(); // red
objB.sayName(); // John
  • 对象冒充还可以实现多重继承

    例如,如果存在两个类 ClassX 和 ClassY,ClassZ 想继承这两个类,可以使用下面的代码:
    function ClassZ() {
this.newMethod = ClassX;
this.newMethod();
delete this.newMethod; this.newMethod = ClassY;
this.newMethod();
delete this.newMethod;
}
   这里存在一个弊端,如果存在两个类 ClassX 和 ClassY 具有同名的属性或方法,ClassY 具有高优先级。因为它从后面的类继承。除这点小问题之外,用对象冒充实现多重继承机制轻而易举。

  1. call、apply方法(和对象冒充类似)

    call、apply这两个方法的使用方法和原理在上一个博客写了,可以去参考一下
    // call方法
function ClassA(acolor){
this.color = acolor;
this.showColor = function(){
console.log(this.color);
}
}
function ClassB(bcolor){
ClassA.call(this,bcolor); // 这里的this指的是ClassB实例化的对象,让this调用函数ClassA,达到继承效果。第二个参数是对应ClassA的参数
}
var objA = new ClassA('blue');
var objB = new ClassB('red');
objA.showColor(); // blue
objB.showColor(); // red
    function ClassA(acolor){
this.color = acolor;
this.showColor = function(){
console.log(this.color);
}
}
function ClassB(bcolor){
// ClassA.apply(this,Array(bcolor));
ClassA.apply(this, arguments); // 这里使用上面的或者arguments都可以,arguments代表的是实参的类数组对象
}
var objA = new ClassA('blue');
var objB = new ClassB('red');
objA.showColor(); // blue
objB.showColor(); // red

  1. 原型链的方式
    function ClassA() {}

    ClassA.prototype.color = "blue";
ClassA.prototype.sayColor = function () {
alert(this.color);
}; function ClassB() {} ClassB.prototype = new ClassA(); // 这是关键

原型方式的神奇之处在于“ClassB.prototype = new ClassA()”代码行。这里,把 ClassB 的 prototype 属性设置成 ClassA 的实例。这很有意思,因为想要 ClassA 的所有属性和方法,但又不想逐个将它们 ClassB 的 prototype 属性进行手动链接。还有比把 ClassA 的实例赋予 prototype 属性更好的方法吗?

与对象冒充相似,子类的所有属性和方法都必须出现在 prototype 属性被赋值后,因为在它之前赋值的所有方法都会被删除。为什么?因为 prototype 属性被替换成了新对象,添加了新方法的原始对象将被销毁。所以,为 ClassB 类添加 name 属性和 sayName() 方法的代码如下:

    function ClassB() {
} ClassB.prototype = new ClassA(); ClassB.prototype.name = "zjy";
ClassB.prototype.sayName = function () {
alert(this.name);
};

测试代码如下:

    var objA = new ClassA();
var objB = new ClassB();
objA.color = "blue";
objB.color = "red";
objB.name = "John";
objA.sayColor(); // blue
objB.sayColor(); // red
objB.sayName(); // John

  1. 原型链和对象冒充混合使用

    用对象冒充的方法继承构造函数的属性,再用原型链的方式继承构造函数的方法。
    // 父类
function ClassA(acolor){// 之所以方法通过原型链来定义是因为方法多数都是对象共享的,如果放在构造函数内部的话,多个实例化对象就会产生多个同样的方法,所以为了减少这样的浪费,将方法通过原型链定义,这样即满足了共享的原则也实现了重复利用不会浪费。不管在内部定义方法还是通过原型链定义,都可以通过其他构造函数的原型链继承到。
this.color = acolor;
}
ClassA.prototype.showColor = function(){ //属性在构造函数内定义,方法通过原型定义
console.log(this.color);
}
// 子类
function ClassB(bcolor,name){
ClassA.call(this,bcolor); // 通过call()对象冒充的方式继承构造函数的属性
this.name = name;
}
ClassB.prototype = new ClassA(); // 通过原型链的方式继承构造函数的方法
ClassB.prototype.showName = function(){
console.log(this.name);
}

测试代码如下:

    var objA = new ClassA('blue');
var objB = new ClassB('red','tom');
objA.showColor(); // blue
objB.showColor(); // red
objB.showName(); // tom

本博客参考了w3cschool相关的解释和代码,链接地址如下 w3cschool

js继承机制的实现的更多相关文章

  1. Javascript 构造函数原型继承机制

    我们先聊聊Js的历史,1994年Netscape公司发布了Navigator浏览器0.9班.这是历史上第一个比较成熟的网络浏览器.轰动一时.但是,这个版本的浏览器只能用来浏览,不具备交互功能,最主要的 ...

  2. js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。

    js最好的继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } Class ...

  3. js一种继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法。

    js一种继承机制:用对象冒充继承构造函数的属性,用原型prototype继承对象的方法. function ClassA(sColor) { this.color = sColor; } ClassA ...

  4. 27、理解js的继承机制(转载自阮一峰)

    Javascript继承机制的设计思想   作者: 阮一峰 日期: 2011年6月 5日 我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类&qu ...

  5. js继承相关

    这几天看到一篇文章详解Javascript的继承实现,发现js还是很深奥的,比如call.apply.prototype这些,问起来我也能说的头头是道的,但是看到一些复杂的代码有的时候还是会迷糊,所以 ...

  6. Javascript类继承-机制-代码Demo【原创】

    最近看到<Javascript设计模式>,对js模拟的”继承方式“有了更深一步的了解,虽然之前也总是用到prototype.new ,但只是知其然不知所以然,现在将类继承的方法整理如下,暂 ...

  7. js继承的常用方法

    写在前面的话:这篇博客不适合对面向对象一无所知的人,如果你连_proto_.prototype...都不是很了解的话,建议还是先去了解一下JavaScript面向对象的基础知识,毕竟胖子不是一口吃成的 ...

  8. JavaScript 原型与继承机制详解

    引言 初识 JavaScript 对象的时候,我以为 JS 是没有继承这种说法的,虽说 JS 是一门面向对象语言,可是面向对象的一些特性在 JS 中并不存在(比如多态,不过严格来说也没有继承).这就困 ...

  9. JS继承的从入门到理解

    开场白 大三下学期结束时候,一个人跑到帝都来参加各厂的面试,免不了的面试过程中经常被问到的问题就是JS中如何实现继承,当时的自己也是背熟了实现继承的各种方法,回过头来想想却不知道__proto__是什 ...

随机推荐

  1. java对象与java对象引用的区别

    java对象与java对象引用的区别 对象与对象引用的区别 直接用例子说话吧 Person per = new Person("张三"); 这一条语句,其实包括了四个动作: 右边的 ...

  2. Python Api接口自动化测试框架 excel篇

    工作原理: 测试用例在excel上编辑,使用第三方库xlrd,读取表格sheet和内容,sheetName对应模块名,Jenkins集成服务发现服务moduleName查找对应表单,运用第三方库req ...

  3. 【Java基础】关于枚举类你可能不知道的事

    目录 谈谈枚举 1. 枚举类的定义 2. 枚举类的底层实现 3. 枚举类的序列化实现 4. 用枚举实现单列 5. 枚举实例的创建过程是线程安全的 谈谈枚举 如果一个类的对象个数是有限的而且是不变的,我 ...

  4. hadoop之mapreduce详解(进阶篇)

    上篇文章hadoop之mapreduce详解(基础篇)我们了解了mapreduce的执行过程和shuffle过程,本篇文章主要从mapreduce的组件和输入输出方面进行阐述. 一.mapreduce ...

  5. 由"跨域"引出的一个终极思想(jsonp)

    1.什么是跨域? 当协议.子域名.主域名.端口号中任意一个不相同时,都算作不同域. 跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,但是因为浏览器存在一个"同源策略&q ...

  6. Django序列化&django REST framework

    第一章.Django序列化操作 1.django的view实现商品列表页(基于View类) # 通过json来序列化,但手写字典key代码量较大,容易出错:还有遇到时间,图片序列化会报错 from g ...

  7. Spring Security 梳理 - session

    Spring Security默认的行为是每个登录成功的用户会新建一个Session.这也就是下面的配置的效果: <http create-session="ifRequired&qu ...

  8. 调试 内存查看StringCchCopy的运行前后

    // ConsoleApplication1.cpp : 定义控制台应用程序的入口点. // #include "stdafx.h" int _tmain(int argc, _T ...

  9. mysql 最左前缀匹配原则

    1.在mysql建立联合索引时会遵循最左前缀匹配的原则,即最左优先,在检索数据时从联合索引的最左边开始匹配,示例:对列col1.列col2和列col3建一个联合索引 KEY index_col1_co ...

  10. Tornado基础学习篇

    1.1 Tornado是什么? Tornado是使用Python编写的一个强大的.可扩展的Web服务器.它在处理严峻的网络流量时表现得足够强健,但却在创建和编写时有着足够的轻量级,并能够被用在大量的应 ...