`
hyj1254
  • 浏览: 340203 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JS 超类和子类

阅读更多
先引一段原文,可略过..
  .....Object is the superclass of all the built-in classes, and all classes inherit a few basic methods from Object.
  Recall that objects inherit properties from the prototype object of their constructor. How do they also inherit properties from the Object class? Remember that the prototype object is itself an object; it is created with the Object( ) constructor. This means the prototype object itself inherits properties from Object.prototype! Prototype-based inheritance is not limited to a single prototype object; instead, a chain of prototype objects is involved. Thus, a Complex object inherits properties from Complex.prototype and from Object.prototype. When you look up a property in a Complex object, the object itself is searched first. If the property is not found, the Complex.prototype object is searched next. Finally, if the property is not found in that object, the Object.prototype object is searched.

    这段话前半部分描述了一个重要信息:prototype由构造函数Object()创建,所以它本身也是一个Object实例,而任何Object实例都可以从Object.prototype中继承属性;于是prototype就也具有了这种能力。
  这就引出了另一个重要的信息:基于prototype的继承不仅仅局限于单一的prototype对象,访问沿着一条prototype链逐级向上执行:假设有个Complex实例,访问其中一属性,如果本身找不到,便访问Complex.prototype对象;还找不到即在Object实例中找不到,就接着访问Complex.prototype的上一级--Object.prototype。
  这就解释了为什么JS对象都从Object对象中继承了方法:如自定义了Complex类,然后它的每个实例就都能访问toString()方法,因为它的prototype是Object实例,能访问Object.prototype。
  这就是所谓“超类和子类”的核心。拿上例来说,它所表述的是,由于Complex.prototype默认是Object的实例(由Object()初始化),于是Complex便继承了Object(即可以访问Object和Object.prototype的所有属性)
    好戏登场了:只要把Complex.prototype的构造函数换成其他的,而不是默认的Object(),那Complex便成为了那个类的子类;这就实现了自己定义的超类和子类关系。当然Complex还是Object的子类,但那是因为那个类最终也是Object的子类。
    举例说明(以Person和Man为例):
function Person(name){this.name=name;}
Person.prototype.say=function(){alert("hello");}
function Man(){}
Man.prototype=new Person("Tom");
//------------
var man = new Man();
alert(man.name);//Tom,继承了Person实例的属性:name
man.say();//hello,继承了Person.prototype的属性:say
alert(man.hasOwnProperty('name'));//false,name在Man.prototype中

完工了,Man已经成为了Person的子类。
当然,这样写虽然能达到效果,但可能不符合“标准”,那就换成标准的:
function Person(name){this.name=name;}
Person.prototype.say=function(){alert(this.hasOwnProperty('name'));}
function Man(name){
   Person.call(this,name);//多了这一步,实现实例属性的继承,要先明白call的作用
}
Man.prototype=new Person();//继承Person.prototype的属性。
//--------------
var man = new Man("Tom");
alert(man.constructor==Person);//true
Man.prototype.constructor=Man;//将Man的构造函数指回Man
alert(man.name);//Tom
alert(man.hasOwnProperty('name'));//true,通过call方法,name已经成为man的实例属性。hasOwnProperty判断man本身是否具有name属性。
man.say();//true,继承了Person.prototype的属性,this指向man
alert(Man.prototype.constructor==Person);//false
alert(Man.prototype instanceof Person);//true


这就是“标准”的做法。当然也可以突发奇想,让Man只继承Person.prototype的属性,而不包括Person的实例属性。
function Person(name){this.name=name;}
Person.prototype.say=function(){alert('hello');}
function Man(){}
Man.prototype=Person.prototype;
var man = new Man();
alert(man.name);//undefined,没有继承Person实例的属性
man.say();//hello,继承了Person.prototype的属性:say
alert(Man.prototype.constructor==Object);//true
alert(Man.prototype instanceof Object);//true

总之,Man是谁的子类就看Man.prototype是由谁的构造函数初始化的。只要把握了这点,继承关系可以随心所欲的构造。
但注意,试图通过把子类的prototype的constructor设为父类的构造函数是不行的。因为prototype并没有被父类的构造函数初始化,它还是由Object()初始化,只是它的constructor属性值改为父类了。 当子类实例访问"父类"prototype内的同名方法时,并不会到"父类"里查找,而是查找Object及Object.prototype。
Man.prototype.constructor=Person;//这样达不到继承的目的

另外说说call的作用(apply也一样):
function Man(name){Person.call(this,name);}

调用Person的构造函数Person,call的第一个参数是绑定Person函数的临时对象,后面的参数是要传给Person的。此例中this即Man实例绑定了Person函数,并调用它。然后person方法内的this指向的就不再是Person实例了,而是Man实例,最终效果就好像它是Man的构造函数一样:所有Man实例就都有了Person实例的属性。
1
0
分享到:
评论
1 楼 Hedgehogking 2013-02-20  
额~菜鸟我看的有点晕晕的了

相关推荐

    javascript闭包子类超类理解

    在JavaScript中,闭包是一种高级特性,它涉及到函数、作用域以及变量持久化等多个概念。闭包的理解对于深入掌握JavaScript编程至关重要,特别是对于初学者来说。 首先,我们要理解JavaScript中的变量作用域。变量...

    Javascript类的继承,使用this.callParent调用超类方法

    当我们谈论类的继承时,我们指的是一个类(子类)可以获取另一个类(父类或超类)的属性和方法,从而实现代码复用和扩展。在本话题中,我们将深入探讨JavaScript中的类继承,并特别关注`this.callParent`这个方法,...

    Test_invoke_super_range.rar_Superclass

    - `source.js`:虽然JavaScript不支持"super"关键字以相同的方式调用超类(JavaScript的继承机制基于原型链),但这个文件可能是与Java代码相关的辅助脚本或测试工具。 在`Test_invoke_super_range.java`中,我们...

    js继承实现示例代码

    在JavaScript中,继承是一种常见的对象间关系,它允许一个对象(子类)继承另一个对象(父类或超类)的属性和方法。通过继承,可以复用代码、提高程序的可维护性,并构建更加灵活的对象模型。JavaScript原生支持原型...

    JS面向对象之单选框实现

    【JS面向对象之单选框实现】在JavaScript中,面向对象编程是一种常用的设计模式,它允许我们通过类和对象来组织代码,使得代码更易于理解和维护。本篇内容主要讲解如何利用面向对象的方法来实现单选框的功能。 首先...

    subclass-dance-party:类和子类的实现

    在编程世界中,类和子类的实现是面向对象编程(OOP)的核心概念,尤其在JavaScript这样的语言中,它提供了构建复杂应用的基础结构。在"subclass-dance-party"项目中,我们深入探讨了如何利用类和子类来创建可扩展、...

    详解JavaScript中基于原型prototype的继承特性_.docx

    这意味着,尽管子类的原型指向了超类的实例,但创建子类实例时,只能调用自己的构造函数,无法直接调用超类构造函数。为了解决这个问题,可以使用其他继承策略,如寄生组合式继承或使用类语法(ES6的`class`关键字,...

    js遍历属性 以及 js prototype 和继承

    1. 构造函数继承(经典继承):通过`new`关键字创建一个父类(超类)的新实例,然后将其作为子类的`prototype`。 ```javascript function Student(name, grade) { Person.call(this, name); this.grade = grade;...

    100家大公司java笔试题汇总.doc

    3. 超类与子类方法调用:实例方法不能直接调用超类的实例方法,需要通过`super`关键字。选项D正确,实例方法可以直接调用本类的类方法。 4. 继承与重写:子类`Sub`重写了`Super`的`getLenght()`方法,返回类型不同...

    子类舞蹈派对

    父类(也称为超类)定义了一组方法和属性,子类可以继承这些特征,并可以选择性地添加自己的特性和行为。在描述中提到的“一对”,可能是指每个子类都与一个特定的父类相对应,或者在某种意义上,它们之间存在一对一...

    继承和接口和java访问权限修饰符总结.doc

    动态绑定可以实现多态性,通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。 四、访问权限修饰符 访问权限修饰符是指在 Java 中用来控制类、方法和变量的访问权限的关键字。常见的访问权限修饰符有:...

    Javascript 继承机制的实现

    选定基类后,就可以创建它的子类了。...子类还可添加超类中没有的新属性和方法,也可以覆盖超类中的属性和方法。 4.2.1 继承的方式 和其他功能一样,ECMAScript中实现继承的方式不止一种。这是因为JavaScr

    JS设计模式与开发实践

    综上所述,《JS设计模式与开发实践》是一本涵盖了从基础知识到高级实践的全面指南,不仅适合不同层次的JavaScript开发者阅读,也为那些希望深入理解设计模式在实际项目中应用的开发者提供了宝贵的资源。

    Javascript继承[参考].pdf

    在深入理解JavaScript继承之前,我们需要掌握几个核心概念:父类(也称作超类)是指被继承的类,子类是通过继承父类得到的类,抽象类通常不用于实例化,而是作为其他类继承的基础,基类是提供给其他类继承的类,派生...

    Java的继承、重载和多态.doc

    一个类可以扩展另一个类的功能,继承的父类称为超类或基类,而扩展的类称为子类。子类继承了父类的所有非私有(public和protected)属性和方法。例如,`ClassTwo`继承自`ClassOne`,因此`ClassTwo`可以访问`ClassOne...

    Starfield:AP计算机科学专业课程美国Simon Lomon高中的Simon的APCSA课程的编程任务

    Particle超类和Oddball子类。 所有粒子必须存储在超类类型的单个数组中。 确保您没有不必要地在Oddball子类中重复继承的变量和函数。 您的Oddball子类只需要包含一个构造函数以及void move()和/或void show()以便...

    javascript学习笔记(十) js对象 继承

    JavaScript中的对象继承是面向对象编程的关键概念,它允许我们创建基于现有对象的新对象,从而能够重用和扩展功能。在JavaScript中,有多种实现继承的方式,但最常见的是通过原型链(prototype chain)。本篇学习...

    subclass-dance-party

    子类是从超类继承属性和方法的类,这样可以实现代码重用和模块化设计。在这个项目中,“dance-party”可能代表一个具体的派对场景,而“subclass”则表示我们创建了多个派对类型的子类,比如“DiscoParty”、...

Global site tag (gtag.js) - Google Analytics