js里每一个function都有一个prototype属性,而每一个实例都有constructor属性,并且每一个function的prototype都有一个constructor属性,这个属性会指向自身。这会形成一个非常有意思的链式结构。举例如下:

  1. function Person(){
  2. this.name =12;
  3. }
  4. console.log(Person.prototype);
  5. console.log(Person.prototype.constructor);//输出Person,指向自身
  6. console.log(Person.prototype.constructor.prototype.constructor);//输出Person,指向自身
  1. /***再看一下这个类的输出,则会出现如下情况**/
  2. function Person(){}
  3. Person.prototype.name = 'xiaoming';
  4. var p1 = new Person();
  5. console.log(p1);

输出结果如下:

会把这个实例显示出来,展开如下。p1有一个原型属性,这个属性有一个构造方法Person(),而这个构造方法又有prototype属性,这个属性有constructor方法…

这里主要让我们了解一下prototype是属于类(或者说函数function)的属性,指向这个类的共有属性和方法,而constructor是实例的属性,指向它的构造函数(也可以说是类,js里构造函数和类是一个概念)。

通过前面的两篇文章

javascript继承—继承的实现原理(1)

javascript创建对象的三种模式

我们知道用prototype来实现继承可以使子类拥有父类的共有属性和方法,其它两种不行。所以这里主要讨论如何用prototype实现继承。

由于采用prototype继承父类的实例在javascript继承—继承的实现原理(1)中已有论述,下面着重介绍用prototype继承实现的几种方式。

方案一:

直接将父类的prototype属性赋给子类,同时用call继承父类的特权属性,然后再修改子类prototype的constructor

  1. function Person(name,age){
  2. this.name = name;
  3. this.age = age;
  4. }
  5.  
  6. Person.prototype = {
  7. sayHi:function(){
  8. alert('hi');
  9. }
  10. }
  11.  
  12. function Student(name,age,grade){
  13. Person.call(this,name,age);
  14. this.grade = grade;
  15. }
  16.  
  17. Student.prototype = Person.prototype;
  18. //Student.prototype.constructor = Student;
  19. Student.prototype.study = function(){
  20. alert('study');
  21. }
  22. var p1 = new Person('xiaoming',10);
  23. var s1 = new Student('xiaohong',9,3);
  24. //p1.study();// p1.study is not a function 说明Person的实例没有study方法,即子类的共有方法没有被父类共享
  25. console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}
  26. console.log(s1);//Student { name="xiaohong", age=9, grade=3, 更多...}
  27. console.log(p1.constructor);//Object()
  28. console.log(s1.constructor);//Object() 子类父类实例相同都为Object
  29.  
  30. /**
  31. 如果在原文中加上Student.prototype.constructor = Student;

  32. console.log(p1.constructor);//Student()
  33. console.log(s1.constructor);//Student() 子类父类实例相同都为Student
  34. ***/

这种方案经测试是行不通的,因为不管怎么变,子类和父类的实例都会共有相同的constructor,这种情形下修改子类的共有方法,同时会修改了父类的共有方法,说明此法不通。

方案二:

将父类的实例赋给子类的原型对象,同时使用call方法使子类继承父类的特权属性。

  1. function Person(name,age){
  2. this.name = name;
  3. this.age = age;
  4. }
  5.  
  6. Person.prototype = {
  7. constructor:Person,
  8. sayHi:function(){
  9. alert('hi');
  10. }
  11. }
  12.  
  13. function Student(name,age,grade){
  14. Person.call(this,name,age);
  15. this.grade = grade;
  16. }
  17.  
  18. Student.prototype = new Person();
  19. Student.prototype.constructor = Student;
  20. Student.prototype.study = function(){
  21. alert('study');
  22. }
  23. var p1 = new Person('xiaoming',10);
  24. var s1 = new Student('xiaohong',9,3);
  25. //p1.study();// p1.study is not a function 说明Person的实例没有study方法,即子类的共有方法没有被父类共享
  26. console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}
  27. console.log(s1);//Student { name="xiaohong", age=9, grade=3, 更多...}
  28. console.log(p1.constructor);//Person(name,age) 父类的实例指向仍是父类
  29. console.log(s1.constructor);//Student(name,age,grade) //子类的实例指向仍是子类

得到的结果基本符合我们继承的要求,但是这个继承实现方式所继承的是父类实例所有的属性和方法,即实例方法(也可以说是特权方法),每创建一个子类对象都会把父类的特权方法都复制一遍,这样会耗费资源并且是无意义的。这时创建子类的实例就相当于javascript创建对象的三种模式 中的第二种构造函数模式。

方案三:

  1. function Person(name,age){
  2. this.name = name;
  3. this.age = age;
  4. }
  5. //第一种创建共有方法方式
  6. Person.prototype.sayHi = function(){
  7. alert('hi');
  8. }
  9. //第二种创建共有方法方式
  10. /*--------------------------------------------------------
  11. Person.prototype = {
  12. constructor:Person,
  13. sayHi:function(){
  14. alert('hi');
  15. }
  16. }
  17. -------------------------------------------------------*/
  18.  
  19. function Student(name,age,grade){
  20. Person.call(this,name,age);
  21. this.grade = grade;
  22. }
  23.  
  24. for(var i in Person.prototype){Student.prototype[i] = Person.prototype[i]}
  25.  
  26. //第二种创建共有方法方式继承时需要加上这句,不然子类实例会指向Person
  27. /*--------------------------------------------------------
  28. Student.prototype.constructor = Student
  29. -------------------------------------------------------*/
  30. Student.prototype.study = function(){
  31. alert('study');
  32. }
  33. var p1 = new Person('xiaoming',10);
  34. var s1 = new Student('xiaohong',9,3);
  35. //p1.study();// p1.study is not a function 说明Person的实例没有study方法,即子类的共有方法没有被父类共享
  36. console.log(p1);//Person { name="xiaoming", age=10, sayHi=function()}
  37. console.log(s1);//Student { name="xiaohong", age=9, grade=3, 更多...}
  38. console.log(p1.constructor);//Person(name,age) 父类的实例指向仍是父类
  39. console.log(s1.constructor);//Student(name,age,grade) //子类的实例指向仍是子类
  40. /*--------------------------------------------------------
  41. 第二种方式
  42. console.log(p1.constructor);//Person() 父类的实例指向仍是Person
  43. -------------------------------------------------------*/

用prototype实现原型链继承。对于第三种创建共有方法,如果创建的时候不加constructor: Person,得到的父类实例会指向Object,是因为创建共有方法的时候直接将一个包含共有方法的Object对象赋给了父类的prototype属性,将父类原有的constructor属性Person修改为Object。所以会出现这种情形。

经过测试,这种继承方式是可行的。使用这种方式继承,可以看到基本实现了子类继承父类的所有属性和方法,并且子类的构造函数仍是子类,父类的构造函数是父类。自认为这是比较完美的方案。

javascript继承(四)—prototype属性介绍的更多相关文章

  1. javascript继承(五)—prototype最优两种继承(空函数和循环拷贝)

    一.利用空函数实现继承 参考了文章javascript继承—prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...

  2. javascript 继承 inheritance prototype

      * Rectangle继承Shape function Shape() { this.x = 0; this.y = 0; } Shape.prototype.move = function(x, ...

  3. javascript继承—prototype最优两种继承(空函数和循环拷贝)

    一.利用空函数实现继承 参考了文章javascript继承-prototype属性介绍(2) 中叶小钗的评论,对这篇文章中的方案二利用一个空函数进行修改,可以解决创建子类对象时,父类实例化的过程中特权 ...

  4. JavaScript继承详解(四)

    在本章中,我们将分析Douglas Crockford关于JavaScript继承的一个实现 - Classical Inheritance in JavaScript. Crockford是Java ...

  5. 谈谈javascript中的prototype与继承

    谈谈javascript中的prototype与继承 今天想谈谈javascript中的prototype. 通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性 ...

  6. Javascript 继承 call与prototype

    function Parent(hello){ this.hello = hello; this.sayHello = function(){ alert(this.hello); } } Paren ...

  7. javascript继承机制的设计思想(ryf)

    我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...

  8. [原创]JavaScript继承详解

    原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...

  9. 【JavaScript】重温Javascript继承机制

    上段时间,团队内部有过好几次给力的分享,这里对西风师傅分享的继承机制稍作整理一下,适当加了些口语化的描述,留作备案. 一.讲个故事吧 澄清在先,Java和Javascript是雷锋和雷峰塔的关系.Ja ...

随机推荐

  1. python lambda表达式简单用法

    习条件运算时,对于简单的 if else 语句,可以使用三元运算来表示,即: 1 2 3 4 5 6 7 8 # 普通条件语句 if 1 == 1:     name = 'wupeiqi' else ...

  2. 分享一个linux环境下快速读取行数的命令

    最初是因为我需要计算一天的日志行数,如果用传统意义上的cat  a.log |wc -l的话因为是单线程,所以需要计算半小时的样子,后来同组的小伙伴教了我一个方法可以有效提高计算速度,将计算时间减半. ...

  3. hdu Flow Problem (最大流 裸题)

    最大流裸题,贴下模版 view code#include <iostream> #include <cstdio> #include <cstring> #incl ...

  4. hiveserver2 with kerberos authentication

    Kerberos协议: Kerberos协议主要用于计算机网络的身份鉴别(Authentication), 其特点是用户只需输入一次身份验证信息就可以凭借此验证获得的票据(ticket-grantin ...

  5. oracle 高水位线详解

    一.什么是水线(High Water Mark)? 所有的oracle段(segments,在此,为了理解方便,建议把segment作为表的一个同义词) 都有一个在段内容纳数据的上限,我们把这个上限称 ...

  6. 深搜+剪枝 POJ 1724 ROADS

    POJ 1724 ROADS Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 12766   Accepted: 4722 D ...

  7. Golang tool:include spider library,image library and some other db library such as mysql,redis,mogodb,hbase,cassandra

    一.Go_tool This is a tool library for Golang.Dont't worry about not understant it! All comment writes ...

  8. HOJ 1640 Mobile Phone

    题意:有一个n*n的矩阵,op==1时,在(x,y)增加值z,op==2时,求以(x1,y1)和(x2,y2)构成的矩阵的和. 思路:二维线段树. 代码: #include<stdio.h> ...

  9. Java虚拟机详解01----初识JVM

    主要内容如下: JVM的概念 JVM发展历史 JVM种类 Java语言规范 JVM规范 一.JVM的概念: JVM: Java Virtual Machine,意为Java虚拟机. 虚拟机: 指通过软 ...

  10. NGUI OnChange Event

    那些组件有OnChange? 下面这些组件都有OnChange事件,当你点击,下拉选择时,就会触发它们. NGUI中对应的组件 PopupList (下拉列表) Toggle (复选框) Input ...