本人对于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. 12.18 aop身份验证

    对所有卖家页面进行身份验证,采用aop编程 步骤:1.获得request 2.查询cookie 3.查询redis 4.查询不通过时,采用抛出异常,捕捉异常,再异常里加入跳转到登陆页面的方法 准备工作 ...

  2. PostgreSQL监控脚本

    往往我们对着一堆系统状态视图不知所措,这里我整理一些学习到的脚本: 后续慢慢补充- --20170913--这部分参考了http://blog.postgresql-consulting.com pg ...

  3. Linux:declare命令详解

    declare declare命令用于声明和显示已存在的shell变量.当不提供变量名参数时显示所有shell变量.declare命令若不带任何参数选项,则会显示所有shell变量及其值.declar ...

  4. jfreechart在jsp中画图方式

    这个问题一直困扰我好久,今天算是稍微找到一点解决思路了,在网上搜了好多列子,大部分的都是用servlet来实现画图,偶然找到一个列子用的是org.jfree.chart.servlet.Servlet ...

  5. XPath element 格式

    一.xpath表达式的基本格式 xpath通过“路径表达式”(Path Expression)来选择节点. # 斜杠(/)作为路径内部的分割符. # 同一个节点有绝对路径和相对路径两种写法. # 绝对 ...

  6. HDU2037 今年暑假不AC

    解题思路:贪心问题,关键突破口是,先将节目的结束时间 从小到大排个序,然后依次判断后面一个节目的开始时间 是否大于或等于前一个符合条件的节目的结束时间.见代码: #include<cstdio& ...

  7. DevExpress相关控件中非字符数值居左显示

    用了这么长时间的DevExpress控件,今天遇到俩问题. 一个是从头到尾看了一遍编译成功的例子,只能感慨,功能太丰富了,自己所用的不过是冰山一角.有些自己一直想实现的效果,原来早就有现成的可用,汗颜 ...

  8. LOJ2421 NOIP2015 信息传递 【tarjan求最小环】

    LOJ2421 NOIP2015 信息传递 LINK 题目大意就是给你一个有向图,求最小环 有一个很奇妙的性质叫做每个点只有一条出边 然后我们考虑对每个强联通分量进行考虑 发现每个强联通分量内的边数一 ...

  9. Appium + Python App自动化(2)第一个脚本

    [1]打开你的夜神模拟器(或者连接你的手机) [2]打开桌面的Appium [3]下载你要测的App的apk文件,放到桌面 [4]拖动你的apk安装包到夜神模拟器里,然后模拟器会提示你安装.安装.原来 ...

  10. 【angularJS】Directive指令

    AngularJS 通过被称为 指令 的新属性来扩展 HTML.指令是扩展的 HTML 属性,带有前缀 ng-. 内置指令 1.ng-app 指令初始化一个 AngularJS 应用程序. 定义了 A ...