- 浏览: 341078 次
- 性别:
- 来自: 北京
文章分类
最新评论
先引一段原文,可略过..
这段话前半部分描述了一个重要信息: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为例):
完工了,Man已经成为了Person的子类。
当然,这样写虽然能达到效果,但可能不符合“标准”,那就换成标准的:
这就是“标准”的做法。当然也可以突发奇想,让Man只继承Person.prototype的属性,而不包括Person的实例属性。
总之,Man是谁的子类就看Man.prototype是由谁的构造函数初始化的。只要把握了这点,继承关系可以随心所欲的构造。
但注意,试图通过把子类的prototype的constructor设为父类的构造函数是不行的。因为prototype并没有被父类的构造函数初始化,它还是由Object()初始化,只是它的constructor属性值改为父类了。 当子类实例访问"父类"prototype内的同名方法时,并不会到"父类"里查找,而是查找Object及Object.prototype。
另外说说call的作用(apply也一样):
调用Person的构造函数Person,call的第一个参数是绑定Person函数的临时对象,后面的参数是要传给Person的。此例中this即Man实例绑定了Person函数,并调用它。然后person方法内的this指向的就不再是Person实例了,而是Man实例,最终效果就好像它是Man的构造函数一样:所有Man实例就都有了Person实例的属性。
.....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实例的属性。
发表评论
-
涉及页面展示尽量少用js
2012-07-04 10:42 1327用js操作DOM元素会引起页面频繁的reflow和 ... -
inline Element相互之间多出几像素的空白
2011-10-19 05:17 2393若干个行内元素并排排列,margin,padding都设成0了 ... -
兼容各浏览器盒子模型
2011-09-24 23:36 5800各浏览器盒模型的 ... -
获取鼠标相对位置
2011-09-20 10:48 2506获取鼠标相对于html的位置: function mo ... -
判断日期格式
2011-08-17 09:34 1099var startTime = "2011-03-3 ... -
JS简易拖拽效果
2011-07-31 22:48 6903模仿《javascript权威指南》写了个简易拖拽程序,麻雀虽 ... -
IE事件注册相关的内存泄露总结
2011-06-03 17:28 1452经过一上午的艰苦试验验证,得出如下结论: 1、将元 ... -
假的,全是假的!!(更新)
2010-10-11 21:31 1495<meta http-equiv="P ... -
IE内存泄露与无法回收研究小结(持续增加中)
2010-09-21 16:19 6299一、内存泄露 之前 ... -
javascript父、子页面交互小结
2010-06-04 12:05 8556帧用来存放子页面 ... -
获取子窗口中使用jQuery.data()设置的参数
2010-04-13 17:49 5597假设在iframe子窗口中设置了$('#mydata') ... -
《JavaScript The Definitive Guide 5th》闭包读后总结
2010-03-24 10:51 1393JavaScript functions are a comb ... -
"position:relative"在IE中的Bug
2010-03-22 09:29 6048请看下图: 即子元素过高导致父元素出现滚动条时,它并不会像预 ... -
JS没有"块作用域"
2010-03-17 16:01 1427没别的意思,只是记下来而已,这在犀牛书上是明明白白地写着 ... -
jquery的data函数
2010-02-03 18:45 3345今天试着使用了下这个函数,真是万事开头难,碰了个灰头土脸, ... -
使用设计模式的目的
2009-12-09 10:24 2072为什么要用设计模式?在生搬硬套了策略模式之后产生了这种疑 ... -
jquery 整体感觉
2009-11-12 10:34 1344用了一段时间后,觉得它和Ext虽然有很大不同,但如果稍微 ... -
jquery的each函数中的break和continue功能
2009-10-20 17:06 27370each函数不能使用break和continue关键字,替代方 ... -
移除JS数组指定位置的元素
2009-10-15 10:34 18928JavaScript中splice函数方法是从一个数组 ... -
JQuery动态添加Select的Option元素
2009-09-21 10:02 12640代码贴上: var selector=$('<s ...
相关推荐
在JavaScript中,闭包是一种高级特性,它涉及到函数、作用域以及变量持久化等多个概念。闭包的理解对于深入掌握JavaScript编程至关重要,特别是对于初学者来说。 首先,我们要理解JavaScript中的变量作用域。变量...
当我们谈论类的继承时,我们指的是一个类(子类)可以获取另一个类(父类或超类)的属性和方法,从而实现代码复用和扩展。在本话题中,我们将深入探讨JavaScript中的类继承,并特别关注`this.callParent`这个方法,...
- `source.js`:虽然JavaScript不支持"super"关键字以相同的方式调用超类(JavaScript的继承机制基于原型链),但这个文件可能是与Java代码相关的辅助脚本或测试工具。 在`Test_invoke_super_range.java`中,我们...
在JavaScript中,继承是一种常见的对象间关系,它允许一个对象(子类)继承另一个对象(父类或超类)的属性和方法。通过继承,可以复用代码、提高程序的可维护性,并构建更加灵活的对象模型。JavaScript原生支持原型...
【JS面向对象之单选框实现】在JavaScript中,面向对象编程是一种常用的设计模式,它允许我们通过类和对象来组织代码,使得代码更易于理解和维护。本篇内容主要讲解如何利用面向对象的方法来实现单选框的功能。 首先...
在编程世界中,类和子类的实现是面向对象编程(OOP)的核心概念,尤其在JavaScript这样的语言中,它提供了构建复杂应用的基础结构。在"subclass-dance-party"项目中,我们深入探讨了如何利用类和子类来创建可扩展、...
这意味着,尽管子类的原型指向了超类的实例,但创建子类实例时,只能调用自己的构造函数,无法直接调用超类构造函数。为了解决这个问题,可以使用其他继承策略,如寄生组合式继承或使用类语法(ES6的`class`关键字,...
1. 构造函数继承(经典继承):通过`new`关键字创建一个父类(超类)的新实例,然后将其作为子类的`prototype`。 ```javascript function Student(name, grade) { Person.call(this, name); this.grade = grade;...
3. 超类与子类方法调用:实例方法不能直接调用超类的实例方法,需要通过`super`关键字。选项D正确,实例方法可以直接调用本类的类方法。 4. 继承与重写:子类`Sub`重写了`Super`的`getLenght()`方法,返回类型不同...
父类(也称为超类)定义了一组方法和属性,子类可以继承这些特征,并可以选择性地添加自己的特性和行为。在描述中提到的“一对”,可能是指每个子类都与一个特定的父类相对应,或者在某种意义上,它们之间存在一对一...
动态绑定可以实现多态性,通过将子类对象引用赋值给超类对象引用变量来实现动态方法调用。 四、访问权限修饰符 访问权限修饰符是指在 Java 中用来控制类、方法和变量的访问权限的关键字。常见的访问权限修饰符有:...
选定基类后,就可以创建它的子类了。...子类还可添加超类中没有的新属性和方法,也可以覆盖超类中的属性和方法。 4.2.1 继承的方式 和其他功能一样,ECMAScript中实现继承的方式不止一种。这是因为JavaScr
综上所述,《JS设计模式与开发实践》是一本涵盖了从基础知识到高级实践的全面指南,不仅适合不同层次的JavaScript开发者阅读,也为那些希望深入理解设计模式在实际项目中应用的开发者提供了宝贵的资源。
在深入理解JavaScript继承之前,我们需要掌握几个核心概念:父类(也称作超类)是指被继承的类,子类是通过继承父类得到的类,抽象类通常不用于实例化,而是作为其他类继承的基础,基类是提供给其他类继承的类,派生...
一个类可以扩展另一个类的功能,继承的父类称为超类或基类,而扩展的类称为子类。子类继承了父类的所有非私有(public和protected)属性和方法。例如,`ClassTwo`继承自`ClassOne`,因此`ClassTwo`可以访问`ClassOne...
Particle超类和Oddball子类。 所有粒子必须存储在超类类型的单个数组中。 确保您没有不必要地在Oddball子类中重复继承的变量和函数。 您的Oddball子类只需要包含一个构造函数以及void move()和/或void show()以便...
JavaScript中的对象继承是面向对象编程的关键概念,它允许我们创建基于现有对象的新对象,从而能够重用和扩展功能。在JavaScript中,有多种实现继承的方式,但最常见的是通过原型链(prototype chain)。本篇学习...
子类是从超类继承属性和方法的类,这样可以实现代码重用和模块化设计。在这个项目中,“dance-party”可能代表一个具体的派对场景,而“subclass”则表示我们创建了多个派对类型的子类,比如“DiscoParty”、...