本人对于ECMAScript继承机制有些见解,如果说的不对,敬请赐教~~~~

继承是OO语言(面向对象)挺好的概念,许多OO语言都支持两种继承方式(接口只继承方法签名、实际继承则继承实际的方法),但是ECMAScript由于没有签名,只支持实现继承。

1、原型链继承

就是一个引用类型继承另一个引用类型的属性和方法。简单回顾下构造函数、原型和实例的关系,每一个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。如果我们让一个原型对象等于另一个类型的实例,显然,此时的原型对象将要包含另一个原型的指针,相对的,另一个原型中也包含着一个指向另一个构造函数的指针,另一个原型又是另一个类型的实例,如此层层递进,就构成了原型的链条,这就是原型链的概念。

实现原型链有一种基本模式,如下

function Father(){
this.property = true;
}
Father.prototype.getFatherValue = function(){
return this.property;
}
function Son(){
this.property = false;
}
//继承了Father
Son.prototype = new Father();
Son.prototype.getSonValue = function(){
return this.property;
}
var instance = new Son();
alert(instance.getFatherValue()); //true

  先从实例中查找属性和方法,如果找不到,在从实例的原型中查找(原型property   原型链 __proto__);

上面的其实是Son继承了Father,而继承则是通过创建Father的实例,并将该实例赋给Son.prototype实现的,实现的本质就是重写原型对象,代之一个新类型的实例。

上面的代码没有使用Son默认的原型,而是给他换一个新原型,这个新原型就是Father的实例,所以新原型不但具有作为一个Father的实例所有的属性和方法,而且内部还有一个内部指针,指向Father的原型。故instance指向Son的原型,Son的原型有指向Father的原型,但是getFatherValue()方法仍然存在Father.property中,但是property则位于Son.property中,而getFatherValue()是一个原型的方法,Son.property是property的实例,那么property就位于该实例中。注意:intance.constructor现在指向的是Father,这是因为Son.property中的constructor被重写的缘故。

查找的步骤:1、搜索实例,2、搜索Son.property,3、搜索Father.property; (原型链是Object,),如果最后还是没有找到,那就是underfined或是null。

1、默认的原型

所有的函数的默认原型都是Object的实例,因此默认原型都会包含一个内部指针,指向Object.property,这就是所有自定义类型都会继承toString()、valueOf()等默认方法的根本原因。当你调用instance.toString()就是调用Object.toString()。

2、确定原型和实例的关系

第一种方式是 使用 instanceOf操作符 来测试 实例与原型链中出现的构造函数

alert(instance instanceOf Object); //true
alert(instance instanceOf Son); //true
alert(instance instanceOf Father); //true

第二种方式 是使用 isPrototypeOf() 只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型

alert(Object.prototype.isPrototypeOf(instance)); //true
alert(Son.prototype.isPrototypeOf(instance)); //true
alert(Father.prototype.isPrototypeOf(instance)); //true

3、谨慎使用定义的方法

function Father(){
this.property = true;
}
Father.prototype.getFatherValue = function(){
return this.property;
}
function Son(){
this.property = false;
}
//继承了Father
Son.prototype = new Father();
//添加新的方法
Son.prototype.getSonValue = function(){
return this.property;
}
//重写超类型的中的方法
Son.prototype.getFatherValue = function(){
return false;
}
var instance = new Son();
alert(instance.getFatherValue()); //false

第一个方法getSonValue()被添加到Son中,第二个方法getFathervalue()是原型链中已经存在的,但是后来重写了这个方法,屏蔽原来的那个方法,换句话讲,就是Son的实例调用getFatherValue()时,调用的就是重新定义的方法,但是用Father的实例仍然会调用原来的那个方法,需要注意的是,必须是用Father的实例替换原型后,再定义这两个方法。

注意:不能使用字面量创建原型方法,因为这样就会重写原型链

function Father(){
this.property = true;
}
Father.prototype.getFatherValue = function(){
return this.property;
}
function Son(){
this.sonproperty = false;
}
//继承了Father
Son.prototype = new Father(); //使用字面量添加新方法,会导致上一行代码无效
Son.prototype.getSonValue = function(){
getSonValue: function(){
return this.sonproperty;
},
someOtherMethod: function(){
return false;
}
}

var instance = new Son();
alert(instance.getFatherValue()); //error

会出现error,就是因为,使用字面量就是把Son和Father之间的关系切断了。

4、原型链的问题

ECMAScript有6种继承方式(实现继承)的更多相关文章

  1. C++ 继承方式 //语法:class 子类 :继承方式 父类 //继承方式 三种: //1.公共继承 //2.保护继承 //3.私有继承

    1 //继承方式 2 //语法:class 子类 :继承方式 父类 3 //继承方式 三种: 4 //1.公共继承 5 //2.保护继承 6 //3.私有继承 7 8 #include <ios ...

  2. c++三种继承方式public,protect,private

    C++中的三种继承public,protected,private 三种访问权限 public:可以被任意实体访问 protected:只允许子类及本类的成员函数访问 private:只允许本类的成员 ...

  3. Java多线程的三种实现方式

    java多线程的三种实现方式 一.继承Thread类 二.实现Runnable接口 三.使用ExecutorService, Callable, Future 无论是通过继承Thread类还是实现Ru ...

  4. Service组件 总结 + 绑定理Service三种实现方式 Messager + Binder + AIDL

    在Android中进程按优先级可以分为五类,优先级从高到低排列: - 前台进程 该进程包含正在与用户进行交互的界面组件,比如一个Activity - 可视进程 该进程中的组件虽然没有和用户交互,但是仍 ...

  5. c++继承详解:共有(public)继承,私有继承(private)继承,保护(protected)继承

    公有继承(public)继承.私有继承(private).保护继承(protected)是常用的三种继承方式. 1.公有继承(public) 公有继承的特点是基类的公有成员和保护成员作为派生类的成员时 ...

  6. java多线程的几种实现方式

    java多线程的几种实现方式 1.继承Thread类,重写run方法2.实现Runnable接口,重写run方法,实现Runnable接口的实现类的实例对象作为Thread构造函数的target3.通 ...

  7. JavaScript几种继承方式的总结

    1.原型链继承 直接将子类型的原型指向父类型的实例,即"子类型.prototype = new 父类型();",实现方法如下: //父类构造函数 function father(n ...

  8. js的三种继承方式及其优缺点

    [转] 第一种,prototype的方式: //父类 function person(){ this.hair = 'black'; this.eye = 'black'; this.skin = ' ...

  9. 重新理解JS的6种继承方式

    写在前面 一直不喜欢JS的OOP,在学习阶段好像也用不到,总觉得JS的OOP不伦不类的,可能是因为先接触了Java,所以对JS的OO部分有些抵触. 偏见归偏见,既然面试官问到了JS的OOP,那么说明这 ...

随机推荐

  1. L147 Low Cost Study Has High Impact Results For Premature Babies

    No one knows exactly why some babies are born prematurely(早产), but some of the smallest premature ba ...

  2. 报错:java.lang.IllegalArgumentException: object is not an instance of declaring class

    反射的报错信息如下: java.lang.IllegalArgumentException: object is not an instance of declaring class at sun.r ...

  3. Deepgreen DB简介(转)

    原文链接   Deepgreen DB 全称 Vitesse Deepgreen DB,它是一个可扩展的大规模并行(通常称为MPP)数据仓库解决方案,起源于开源数据仓库项目Greenplum DB(通 ...

  4. Linux:wc命令详解

    wc 用来计算数字 利用wc指令我们可以计算文件的Byte数.字数或是列数,若不指定文件名称,或是所给予的文件名为“-”,则wc指令会从标准输入设备读取数据. 语法 wc(选项)(参数) 选项 -c或 ...

  5. 有关php的session

    From:http://blog.csdn.net/sayigood/article/details/4850480 php中session的用法 PHP中的session默认情况下是使用客户端的Co ...

  6. 依存可视化︱Dependency Viewer——南京大学自然语言处理研究组

    来源网页:http://nlp.nju.edu.cn/tanggc/tools/DependencyViewer.html 视频演示网页:http://nlp.nju.edu.cn/tanggc/to ...

  7. Android内存优化(三)避免可控的内存泄漏

    相关文章 Android性能优化系列 Java虚拟机系列 前言 内存泄漏向来都是内存优化的重点,它如同幽灵一般存于我们的应用当中,有时它不会现身,但一旦现身就会让你头疼不已.因此,如何避免.发现和解决 ...

  8. libcurl 错误码总结

    下载出现这种错误(Requested range was not delivered by the server  ),说明是重复下载,删掉本地的再下载就不会出现了

  9. OPEN(SAP) UI5 学习入门系列之二: 最佳实践练习(上)

    这篇博文难产了很久,原来是打算一周更新一篇的,上周原计划写MVC,但是写了一半,发现带入了太多的细节,不太符合这个入门系列的主题. 当我们学习一个新的技能的时候,如果一开始就面对大量的细节,很容易陷入 ...

  10. jQuery插件实现表格隔行换色且感应鼠标高亮行变色

    实现表格隔行换色,且感应鼠标行变色的方法有很多,在本文将为大家介绍的是使用jQuery插件来实现,具体如下 看代码: : css代码: