javascript 继承机制设计思想
作者: 阮一峰
原文链接:http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html
我一直很难理解Javascript语言的继承机制。
它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instance)的区分,全靠一种很奇特的"原型链"(prototype chain)模式,来实现继承。
我花了很多时间,学习这个部分,还做了很多笔记。但是都属于强行记忆,无法从根本上理解。

直到昨天,我读到法国程序员Vjeux的解释,才恍然大悟,完全明白了Javascript为什么这样设计。
下面,我尝试用自己的语言,来解释它的设计思想。彻底说明白prototype对象到底是怎么回事。其实根本就没那么复杂,真相非常简单。
一、从古代说起
要理解Javascript的设计思想,必须从它的诞生说起。
1994年,网景公司(Netscape)发布了Navigator浏览器0.9版。这是历史上第一个比较成熟的网络浏览器,轰动一时。但是,这个版本的浏览器只能用来浏览,不具备与访问者互动的能力。比如,如果网页上有一栏"用户名"要求填写,浏览器就无法判断访问者是否真的填写了,只有让服务器端判断。如果没有填写,服务器端就返回错误,要求用户重新填写,这太浪费时间和服务器资源了。

因此,网景公司急需一种网页脚本语言,使得浏览器可以与网页互动。工程师Brendan Eich负责开发这种新语言。他觉得,没必要设计得很复杂,这种语言只要能够完成一些简单操作就够了,比如判断用户有没有填写表单。

1994年正是面向对象编程(object-oriented programming)最兴盛的时期,C++是当时最流行的语言,而Java语言的1.0版即将于第二年推出,Sun公司正在大肆造势。
Brendan Eich无疑受到了影响,Javascript里面所有的数据类型都是对象(object),这一点与Java非常相似。但是,他随即就遇到了一个难题,到底要不要设计"继承"机制呢?
二、Brendan Eich的选择
如果真的是一种简易的脚本语言,其实不需要有"继承"机制。但是,Javascript里面都是对象,必须有一种机制,将所有对象联系起来。所以,Brendan Eich最后还是设计了"继承"。
但是,他不打算引入"类"(class)的概念,因为一旦有了"类",Javascript就是一种完整的面向对象编程语言了,这好像有点太正式了,而且增加了初学者的入门难度。
他考虑到,C++和Java语言都使用new命令,生成实例。
C++的写法是:
ClassName *object = new ClassName(param);
Java的写法是:
Foo foo = new Foo();
因此,他就把new命令引入了Javascript,用来从原型对象生成一个实例对象。但是,Javascript没有"类",怎么来表示原型对象呢?
这时,他想到C++和Java使用new命令时,都会调用"类"的构造函数(constructor)。他就做了一个简化的设计,在Javascript语言中,new命令后面跟的不是类,而是构造函数。
举例来说,现在有一个叫做DOG的构造函数,表示狗对象的原型。
function DOG(name){
this.name = name;
}
对这个构造函数使用new,就会生成一个狗对象的实例。
var dogA = new DOG('大毛');
alert(dogA.name); // 大毛
注意构造函数中的this关键字,它就代表了新创建的实例对象。
三、new运算符的缺点
用构造函数生成实例对象,有一个缺点,那就是无法共享属性和方法。
比如,在DOG对象的构造函数中,设置一个实例对象的共有属性species。
function DOG(name){
this.name = name;
this.species = '犬科';
}
然后,生成两个实例对象:
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
这两个对象的species属性是独立的,修改其中一个,不会影响到另一个。
dogA.species = '猫科';
alert(dogB.species); // 显示"犬科",不受dogA的影响
每一个实例对象,都有自己的属性和方法的副本。这不仅无法做到数据共享,也是极大的资源浪费。
四、prototype属性的引入
考虑到这一点,Brendan Eich决定为构造函数设置一个prototype属性。
这个属性包含一个对象(以下简称"prototype对象"),所有实例对象需要共享的属性和方法,都放在这个对象里面;那些不需要共享的属性和方法,就放在构造函数里面。
实例对象一旦创建,将自动引用prototype对象的属性和方法。也就是说,实例对象的属性和方法,分成两种,一种是本地的,另一种是引用的。
还是以DOG构造函数为例,现在用prototype属性进行改写:
function DOG(name){
this.name = name;
}
DOG.prototype = { species : '犬科' };
var dogA = new DOG('大毛');
var dogB = new DOG('二毛');
alert(dogA.species); // 犬科
alert(dogB.species); // 犬科
现在,species属性放在prototype对象里,是两个实例对象共享的。只要修改了prototype对象,就会同时影响到两个实例对象。
DOG.prototype.species = '猫科';
alert(dogA.species); // 猫科
alert(dogB.species); // 猫科
五、总结
由于所有的实例对象共享同一个prototype对象,那么从外界看起来,prototype对象就好像是实例对象的原型,而实例对象则好像"继承"了prototype对象一样。
javascript 继承机制设计思想的更多相关文章
- javascript继承机制的设计思想(ryf)
我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...
- 转:Javascript继承机制的设计思想
我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...
- Javascript继承机制的设计思想
转自:http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.htm ...
- 【JavaScript】重温Javascript继承机制
上段时间,团队内部有过好几次给力的分享,这里对西风师傅分享的继承机制稍作整理一下,适当加了些口语化的描述,留作备案. 一.讲个故事吧 澄清在先,Java和Javascript是雷锋和雷峰塔的关系.Ja ...
- Javascript继承机制总结 [转]
转自:http://bbs.csdn.net/topics/260051906 Javascript继承 一直想对Javascript再次做一些总结,正好最近自己写了一个小型Js UI库,总结了一下J ...
- javascript继承机制 & call apply使用说明
一.继承机制 1.对象冒充:构造函数使用 this 关键字给所有属性和方法赋值,可使 ClassA 构造函数成为 ClassB 的方法,然后调用它. function ClassZ() { this. ...
- Javascript继承机制的设计
写软工作业时各种蛋疼:主要在于Javascript没有“子类”“父类”“接口”的概念,只能使用prototype来实现,看了下面一篇文章,感觉写得很不错~ http://www.ruanyifeng. ...
- JavaScript 继承机制小记
读<JavaScript: the good parts>, 关于对象继承这块小记一笔: function Base(v){ this.baseValue = v; this.getBas ...
- Javascript prototype 及 继承机制的设计思想
我一直很难理解Javascript语言的继承机制. 它没有"子类"和"父类"的概念,也没有"类"(class)和"实例" ...
随机推荐
- DOS命令大全--具体解释
在Linux和Windows下都能够用nslookup命令来查询域名的解析结果 DOS命令大全一)MD--建立子文件夹 1.功能:创建新的子文件夹 2.类型:内部命令 3.格式:MD[盘符:][路径名 ...
- Android Action Bar 详解篇 .
作者原创,转载请标明出处:http://blog.csdn.net/yuxlong2010 作为Android 3.0之后引入的新的对象,ActionBar可以说是一个方便快捷的导航神器.它可以作为活 ...
- highcharts的使用
步骤: 1. 去highcharts官网下载最新版本 2. 在.aspx页面添加引用 例: <link href="../JS/highcharts/css/highslide.css ...
- FileShare文件读写锁解决“文件XXX正由另一进程使用,因此该进程无法访问此文件”(转)
开发过程中,我们往往需要大量与文件交互,读文件,写文件已成家常便饭,本地运行完美,但一上到投产环境,往往会出现很多令人措手不及的意外,或开发中的烦恼,因此,我对普通的C#文件操作做了一次总结,问题大部 ...
- Server.HTMLEncode用法
Server.HTMLEncode用法!! Server.HTMLEncode HTMLEncode 一.HTMLEncode 方法对指定的字符串应用 HTML 编码. 语法 Server.HTMLE ...
- UIButton和UIImageView的区别
1.显示图片 1> UIImageView只能一种图片(图片默认会填充整个UIImageView) image\setImage: 2> UIButton能显示2种图片 * 背景 (背景 ...
- Fun with dynamicobject dynamic and the settings table
What came before In my previous post I discussed ways of making the settings table using Generics to ...
- NAS4Free 安装配置(六)配置transmission实现BT(PT)下载
配置transmission transmission是一个跨平台的BT客户端 首先我们建立一个存放transmission配置文件的目录 可以通过SSH,也可以通过网页来完成 注意:最好是通过SSH ...
- HDU 5417 Victor and Machine
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5417 Problem Description Victor has a machine. When t ...
- UIAppearance使用详解-备
iOS5及其以后提供了一个比较强大的工具UIAppearance,我们通过UIAppearance设置一些UI的全局效果,这样就可以很方便的实现UI的自定义效果又能最简单的实现统一界面风格,它提供如下 ...