JavaScript面向对象编程(二)构造函数和类
new关键字和构造函数
在文章JavaScript面向对象编程(一)原型与继承中讨论啦JavaScript中原型的概念,并且提到了new关键字和构造函数。利用new关键字构造对象的实例代码如下:
//define a constructor
var Func = function(name,id){
this.name = name;
this.id = id;
}
Func.prototype.className = "Func"
var obj = new Func("obj",1);//{name: "obj", id: 1, className: "Func"}
obj.hasOwnProperty("name");//true
obj.hasOwnProperty("id");//true
obj.hasOwnProperty("className");//false
new Func()生成一个对象,用跟在new后面的函数Func对所生成的对象进行初始化,并且将Func.prototype作为所生成对象的原型。在Func函数中的this指向的就是new所生成的对象,代码的第3和第4行是给这个对象添加两个属性name和id。在第6行中,给Func.prototype添加了属性为className,因为Func.prototype是所生成对象obj的原型,所以可以从obj中访问className的值。因为className属性是从原型Func.prototype中访问的,所以obj.hasOwnProperty("className")===false。
这样以来,就生成了一个原型链:obj->Func.prototype.
需要注意的是,构造函数中通过this.name给对象添加了属性,这个name属性将是生成对象所拥有的。虽然JavaScript没有强调类的概念,但是从某种意义上,定义了构造函数即是定义了类。构造函数是类的公共标识[1]。
constructor属性
每个JavaScript函数都自动拥有prototype属性,这个属性的值是一个对象(prototype属性的值可以被重新赋值)。prototype对象中包含一个属性,名为constructor。
Func.prototype.constructor === Func;//true
obj.constructor === Func;//true
可以看到,构造函数预定义的(可以重新赋值)prototype中的constructor属性是函数本身。因为new所构造的对象以Func.prototype为原型,所以也可以从obj中访问constructor属性。调用obj.constructor可以重新对obj进行“构造”。
1 obj.constructor("new name",2);//{name: "new name", id: 2, className: "Func"}
obj.constructor就是Func,因此Func中的this.name = name;this.id = id;重新对obj的属性进行了赋值。(初次使用new Func("obj",1)时因为对象没有name和id属性,所以是给对象添加属性)。
instanceof 运算符
obj instanceof Func//true
运算符可以判断obj是否以Func.prototype 为原型。需要注意的是,只需要以Func.prototype 为原型即可,不一定需要通过new关键字构造。如:
var obj2 = Object.create(Func.prototype);
obj2 instanceof Func//true
“继承”类
上文提到,定义了构造函数即是定义了类。并且将构造函数的prototype属性作为所构造的对象的原型。那么,如果用另外一个构造函数生成的对象给构造函数的prototype属性赋值,就可以在原型链中再添加一个节点,达到类继承的效果。
//a function which is used to generate a derived class
var inheritClass = function(baseClass){
if( typeof baseClass === "function"){
var derivedClass = function(){};
derivedClass.prototype = new baseClass();
derivedClass.prototype.constructor = derivedClass;
return derivedClass;
}
else{
throw TypeError();
}
}
//define the base class
var TransportTool = function(){};
TransportTool.prototype.accelerate = function(){
console.log("speed up!");
};
//define a derived class
var Plane = inheritClass(TransportTool);
Plane.prototype.rise = function(){
console.log("rise up!");
};
//define the object
var thePlane = new Plane();
thePlane.accelerate();
thePlane.rise();
上述代码中首先定义了一个函数inheritClass用于生成一个派生类。首先在代码的第5行将derivedClass的prototype赋值为new baseClass。这样一来就在原型链中加了一个节点:实例对象->derivedClass.prototype->baseClass.prototype。代码第6行derivedClass.prototype.constructor设置为derivedClass。因为第5行将derivedClass预设的prototype值修改了,所以在第6行之前derivedClass.prototype.constructor === baseClass。这不符合一个类的行为,所以要将其值修改。修改之后,对象thePlane.constructor === Plane,是make sense的。
thePlane是派生类Plane的实例,也是TransportTool的实例,原因是原型链为thePlane ->Plane.prototype->TransportTool.prototype
thePlane instanceof Plane//true
thePlane instanceof TransportTool//true
因为原型链的作用,thePlane可以同时进行“accelerate”和“rise”操作。
总结
主要从理论角度讨论了JavaScript的面向对象编程的方法,就是基于原型链。new操作符可以将构造函数的prototype属性作为所构造的函数的原型。派生的构造函数的prototype属性可以以另一个构造函数的prototype属性作为原型,形成了原型链。这就是类的“继承”。既然理论已经介绍了,那么接下来的文章JavaScript 面向对象编程(三)如何写类和子类
会介绍如何用JavaScript进行面向对象编程,如何模拟传统的类、成员、静态成员等。
参考文献
1)《JavaScript:The Definitive Guide》第六章,第九章
2)JavaScript的大师的个人博客:http://javascript.crockford.com/prototypal.html
3)将JavaScript OOP介绍的很好的文章:http://phrogz.net/JS/classes/OOPinJS2.html
4)JavaScript Garden:http://bonsaiden.github.io/JavaScript-Garden/
5)介绍原型及原型链的文章:http://blog.vjeux.com/2011/javascript/how-prototypal-inheritance-really-works.html
JavaScript面向对象编程(二)构造函数和类的更多相关文章
- (二)Javascript面向对象编程:构造函数的继承
Javascript面向对象编程:构造函数的继承 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生成实例. 今天要介绍的是,对象之间的"继承 ...
- JavaScript面向对象编程(2)-- 类的定义
最近这一段时间事情太多了,没有时间再继续写,幸好这两天有点小闲,先小写一下JavaScript中面向对象一中推荐的方法.本文承接上一篇JavaScript面向对象编程(1) -- 基础. 上篇说过,J ...
- Javascript面向对象编程:构造函数的继承
今天要介绍的是,对象之间的"继承"的五种方法. 比如,现在有一个"动物"对象的构造函数. function Animal(){ this.species = & ...
- JavaScript面向对象编程学习笔记
1 Javascript 面向对象编程 所谓"构造函数",其实就是一个普通函数,但是内部使用了this变量.对构造函数使用new运算符,就能生成实例,并且this变量会绑定在实例 ...
- Javascript面向对象编程(二):构造函数的继承 作者:yuan一峰
Javascript面向对象编程(二):构造函数的继承 作者: 阮一峰 日期: 2010年5月23日 这个系列的第一部分,主要介绍了如何"封装"数据和方法,以及如何从原型对象生 ...
- JavaScript 面向对象编程(三)如何写类和子类
在JavaScript面向对象编程(一)原型与继承和JavaScript面向对象编程(二)构造函数和类中,我们分别讨论了JavaScript中面向对象的原型和类的概念.基于这两点理论,本篇文章用一个简 ...
- 《JavaScript面向对象编程指南(第2版)》读书笔记(二)
<JavaScript面向对象编程指南(第2版)>读书笔记(一) <JavaScript面向对象编程指南(第2版)>读书笔记(二) 目录 一.基本类型 1.1 字符串 1.2 ...
- (三)Javascript面向对象编程:非构造函数的继承
Javascript面向对象编程:非构造函数的继承 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现"继承". 今天是最后一个部分,介绍不使 ...
- Javascript面向对象编程(三):非构造函数的继承(对象的深拷贝与浅拷贝)
Javascript面向对象编程(三):非构造函数的继承 作者: 阮一峰 日期: 2010年5月24日 这个系列的第一部分介绍了"封装",第二部分介绍了使用构造函数实现&quo ...
随机推荐
- ftk学习记录(button一片)
[ 声明:版权所有所有.欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 前面,我们说到了label,这里能够看一下label执行的效果是怎么样的. waterma ...
- 使用C语言编写windows服务一般框架
原文:使用C语言编写windows服务一般框架 编写windows服务和编写windows应用程序一样,有一些回调函数必须填写且向windows 服务管理器(service manager)进行注册, ...
- ElasticSearch 与 Solr 的对比测试
ElasticSearch 与 Solr 的对比测试 本文从两个方面对ElasticSearch和Solr进行对比,从关系型数据库中的导入速度和模糊查询的速度. 单机对比 1. Solr 发布了4.0 ...
- Installshield停止操作系统进程的代码--IS5版本适用
原文:Installshield停止操作系统进程的代码--IS5版本适用 出处:http://www.installsite.org/pages/en/isp_ext.htm这个地址上有不少好东西,有 ...
- 一些javascript常用方法
1.输入一个正整数n,从1累加到n,返回结果.(如果输入为非正整数,如:小数.0.负数.NaN或其它非数字则返回false) function f(n){ return ~~+n == n & ...
- JavaScript的基准测试
JavaScript的基准测试 原文:Bulletproof JavaScript benchmarks 做JavaScript的基准测试并没有想的那么简单.即使不考虑浏览器差异所带来的影响,也有很多 ...
- [探索]点点轻博客搬家到WordPress(一)
摘要:点点博客备份XML通过DiandianToWordpress-beta.sh(文末给出)搬家到Wordpress博客 本人曾使用过点点轻博客,也深知像点点博客,Lofter博客导出的XML文件不 ...
- Linux下PHP开发环境搭建
平时写程序时都是在服务器已经搭建好的PHP环境进行的.出于对未知知识的好奇,这几天在自己的机器上搭建起了PHP开发环境.本想轻松顺利的看到phpinfo显示在我的页面上,没想到安装环境时一路的erro ...
- AJAX跨域调用ASP.NET MVC或者WebAPI服务
关于AJAX跨域调用ASP.NET MVC或者WebAPI服务的问题及解决方案 作者:陈希章 时间:2014-7-3 问题描述 当跨域(cross domain)调用ASP.NET MVC或者ASP. ...
- java入门学习(十二)运算语句 if switch
这两天在网上做兼职,耽误了些博客见谅哈 欢迎来我的博客:www.taomaipin.com java中的运算语句而且频繁用到的无法就是条件语句和循环语句,包括if,for,while,switch,b ...