javascript入门:prototype和面向对象的实现
由于工作需要,需要大量使用javascript,于是对其进行了一下学习。
学习任何一个语言,最重要的是掌握其和其他语言不同的关键特性。对javascript来说,我总结就是prototype。就像metatable之于lua的地位,如果理解了prototype,再加上其他语言的使用经验,javascript将很容易掌握。
首先,明确一个概念,javascript中所有东西皆是对象,包括函数。这是后面讨论的基础。
关于prototype,相关的概念有两个:
1 一切函数对象,都有一个默认的属性:prototype。
2 一切对象,都有一个默认的属性:__proto__。
比如我写一个函数:
function Speak()
{
alert("speak!");
}
这个函数将会有一个叫做prototype的属性。
prototype更多的只是一个普通的对象(只有在使用new关键字的时候,它才会显出语法层面的特殊性);而__proto__则有特殊的语法意义:
当访问一个对象的属性,而这个属性不存在的时候,将在这个对象的__proto__中寻找这个属性,如果再找不到,就继续找__proto__的__proto__,直到最顶层(Object)。设置时则在对象上增加这个属性。
这个功能,类似于lua中的metatable中的index,如果metatable的index指定了一个表,那么找不到字段时会从那个表里找。
明白了__proto__的意义之后,再说prototype,事实上prototype就是为了设置__proto__而存在的:当使用new关键字调用函数,将把该函数对象的prototype设置到新实例的__proto__上。
例如:
function Animal(hp)
{
this.hp = hp;
} var a = new Animal(20);
此时,a的__proto__将是Animal的prototype。
prototype预置了一个属性叫constructor,constructor如果不主动修改,默认指向自己(本函数对象)。
因此,如果需要添加类成员,只需要在prototype上面加,prototype作为原型,只有一份,所有new出来的对象都使用它的属性。
function Animal(hp)
{
this.hp = hp;
} Animal.prototype.getHP = function() { return this.hp; } var a = new Animal(20);
此时,a.getHP()将调用到Animal.prototype.getHP。
关于类与实例,到这里就没问题了。可以认为prototype就是类模板,Animal(hp)就是构造函数。当调用new的时候,javascript做了下面的事情:
1 创建一个新的对象(Object)。
2 将该对象的__proto__赋值为new后所调用函数的prototype。
3 将该对象赋值给this参数(隐含在参数表中),调用该函数。
4 函数返回后,将该对象作为new表达式的返回值返回。
由于所有对象共享一个prototype,因此,此时要注意一点:如果要定义的类中有属性引用到可能被修改的对象,如:
function Animal(hp)
{
} Animal.prototype.family = {father:"a", mother:"b" }; var a = new Animal();
var b = new Animal();
此时,如果修改了a的father,b的也一起被修改了。因此,这个family字段必须在Animal构造函数中设置,不能放在prototype中。如果该对象不太可能被修改,如纯粹的数值或字符串,就可以放到prototype中。
如果要实现继承,就要利用__proto__的链条形式往上查找属性的特性。将prototype指定为父类的实例。
function Animal(hp)
{
this.hp = hp;
} Animal.prototype.getHP = function() { return this.hp; } function Person(name)
{
this.name = name;
} Person.prototype = new Animal();
Person.prototype.constructor = Person;
Person.prototype.getName = function() { return this.name; } var personInstance = new Person("Eagle");
此时,当我们访问personInstance.getHP,首先personInstance找不到,到personInstance.__proto__中寻找,即Person.prototype,因为Person.prototype是在Animal实例的基础上修改的,其__proto__是Animal.prototype,因此找到了Animal.prototype中的getHP。
解决了继承的问题,但是依然存在一个问题:如何调用父类的构造函数。上面说的getHP实际上调用会出错,因为Animal函数没有被调用过,因此,this.hp = hp这一句没有执行,其实是没有hp属性的。
此时,我们需要在构造函数中嵌套调用父类构造函数,如下:
function Animal(hp)
{
this.hp = hp;
} function Person(name, hp)
{
Animal.call(this, hp); //注意这句话:函数对象的call方法可以显式的修改this指针。如果直接调用Animal(hp),this指向的是global。
this.name = name;
} var a = new Person("Eagle", 100);
到此为止,通过prototype的一套体系,实现了javascript的类,实例和继承。
javascript入门:prototype和面向对象的实现的更多相关文章
- JavaScript入门经典(第7版)读书笔记
断断续续看了十来天,终于看完了,还是学到些东西,这本书还是不错的,各方面都有涉及. 补充了下之前不完善的JS 知识 笔记一般只记必要的东西. Table of Contents 1. JavaScr ...
- 悟透JavaScript(理解JS面向对象的好文章)
引子 编程世界里只存在两种基本元素,一个是数据,一个是代码.编程世界就是在数据和代码千丝万缕的纠缠中呈现出无限的生机和活力. 数据天生就是文静的,总想保持自己固有的本色:而代码却天生活泼,总想改变这个 ...
- JavaScript入门基础
JavaScript基本语法 1.运算符 运算符就是完成操作的一系列符号,它有七类: 赋值运算符(=,+=,-=,*=,/=,%=,<<=,>>=,|=,&=).算术运 ...
- JavaScript入门介绍(一)
JavaScript入门介绍 [经常使用的调试工具][w3school.com.cn在线编辑] [Chrome浏览器 开发调试工具]按F121.代码后台输出调试:console.log("t ...
- 开心菜鸟系列----函数作用域(javascript入门篇)
1 <!DOCTYPE html> 2 <html> 3 <script src="./jquery-1.7.2.js"></ ...
- JavaScript - 基于原型的面向对象
JavaScript - 基于原型的面向对象 1. 引言 JavaScript 是一种基于原型的面向对象语言,而不是基于类的!!! 基于类的面向对象语言,比如 Java,是构建在两个不同实体的概念之上 ...
- 第五章 JavaScript对象及初识面向对象
第五章 JavaScript对象及初识面向对象 一.对象 在JavaScript中,所有事物都是对象,如字符串.数值.数组.函数等. 在JavaScript对象分为内置对象和自定义对象,要处理一些 ...
- JAVAScript对象及初始面向对象
javaScript对象及初始面向对象 1:内置对象 例:Date String Array 类等... 2:自定义对象 方法1:var newObj=new Object(); ...
- JavaScript游戏中的面向对象的设计
简介: 从程序角度考虑,许多 JavaScript 都基于循环和大量的 if/else 语句.在本文中,我们可了解一种更聪明的做法 — 在 JavaScript 游戏中使用面向对象来设计.本文将概述原 ...
- Javascript中prototype属性详解 (存)
Javascript中prototype属性详解 在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不 ...
随机推荐
- 跟着百度学PHP[5]函数篇1-参数
ps:俺的文章俺懂就行.大家不要拿来学习不然每个人的学习思路不一样.看视屏文章的老师不同笔记不同加上我也是新手上路,还怕误导!请大家看行且思考,帮忙挖Bug也可以. 案例要求:你可以写一个两行三列的表 ...
- BestCoder Round #90
有生以来第一场在COGS以外的地方打的比赛.挂成dog了. 主要是没有经验,加之代码能力过弱.还有最后的瞎hack三次,Too Young Too Simple...... 言归正传. (抄一发题解先 ...
- androi手机解锁引导程序
1.重启手机进入fastboot模式 一般关机状态下按手机音量减+开机键,成功后会显示fastboot字提示. 2.查看设备信息 fastboot devices 说明:fastboot是一个工具软 ...
- PHP - xhprof+Graphviz 安装配置
简介:XHProf是Facebook放出的轻量级调试工具.和Xdebug相比,XHProf更加易用和可控,尤其是生成流程图和调试数据对比的功能很好很强大. 参考:http://us2.php.net/ ...
- Delete,Update与LEFT Join
UPDATE:UPDATE A SET ApproverID=NULL FROM [SH_MaterialApplyBuyBill] A LEFT JOIN [SH_MaterialApplyBuyB ...
- python smtplib email
监控系统需要触发报警邮件, 简单笔记一下的用到的库. smtplib class smtplib.SMTP([host[, port[, local_hostname[, timeout]]]]) 返 ...
- SQL查询第m条到第n条的方法
SQL查询第m条到第n条的方法 如表名为GOOD Sselect top (n-m) * from GOODS where (某一列名) not in (select top m (某一列名) fro ...
- iOS - XIB之AutoLayout添加约束
XIB--AutoLayout添加约束 仿QQ登录界面: 说明:以下各图背景红色只是方便看清楚: 1.创建工程:创建xib文件 2.打开xib文件: (1).创建头像: 拖控件:uiimageview ...
- MSSQ调优所需用的语句
看一下各项指标是否正常,是否有阻塞,这个语句选取了前10个最耗CPU时间的会话语句 [session_id], [request_id], [start_time] AS '开始时间', [statu ...
- java Collection.shuffle()随机打乱一个顺序数组
如何打乱一个顺序的数组,其实集合的帮助类Collection就有现成的方法可用,而且效率还蛮高的,总比自定义随机数等等方法要好很多.其实乱序就这么简单,步骤如下: 1. 将一个顺序排列的数组添加到集合 ...