`

JAVASCRIPT基础学习篇(4)--ECMAScript Basic:prototype属性及通过该属性建立面向对象的JavaScript

阅读更多

JAVASctipt 继承机制的实现

下文引自:http://book.csdn.net/bookfiles/11/100117055.shtml

JavaScript通过一种链接机制来支持继承,而不是通过完全面向对象语言(如Java)所支持的基于类的继承模型。每个JavaScript对象都有一个内置的属性,名为prototypeprototype属性保存着对另一个JavaScript对象的引用,这个对象作为当前对象的父对象。

当通过点记法引用对象的一个函数或属性时,倘若对象上没有这个函数或属性,此时就会使用对象的prototype属性。当出现这种情况时,将检查对象prototype属性所引用的对象,查看是否有所请求的属性或函数。如果prototype属性引用的对象也没有所需的函数或属性,则会进一步检查这个对象(prototype属性引用的对象)的prototype属性,依次沿着链向上查找,直到找到所请求的函数或属性,或者到达链尾,如果已经到达链尾还没有找到,则返undefined。从这个意义上讲,这种继承结构更应是一种“has a”关系,而不是“is a”关系。

如果你习惯于基于类的继承机制,那么可能要花一些时间来熟悉这种prototype机制。prototype机制是动态的,可以根据需要在运行时配置,而无需重新编译。你可以只在需要时才向对象增加属性和函数,而且能动态地把单独的函数合并在一起,来创建动态、全能的对象。对prototype机制的这种高度动态性可谓褒贬不一,因为这种机制学习和应用起来很不容易,但是一旦正确地加以应用,这种机制则相当强大而且非常健壮。

这种动态性与基于类的继承机制中的多态概念异曲同工。两个对象可以有相同的属性和函数,但是函数方法(实现)可以完全不同,而且属性可以支持完全不同的数据类型。这种多态性使得JavaScript对象能够由其他脚本和函数以统一的方式处理。

5-15显示了实际的prototype继承机制。这个脚本定义了3类对象:VehicleSports-
Car
CementTruckVehicle是基类,另外两个类由此继承。Vehicle定义了两个属性:wheelCountcurbWeightInPounds,分别表示Vehicle的车轮数和总重量。JavaScript不支持抽象类的概念(抽象类不能实例化,只能由其他类扩展),因此,对于Vehicle基类,wheelCount默认为4curbWeightInPounds默认为3 000

5-15 VehicleSportsCarCementTruck对象之间的关系

注意,这个UML图展示了SportsCarCementTruck对象覆盖了VehiclerefuelmainTasks函数,因为一般的VehicleSportsCar(赛车)和CementTruck(水泥车)会以不同的方式完成这些任务。SportsCarVehicle的车轮数相同,所以SportsCarwheelCount属性不会覆盖VehiclewheelCount属性。CementTruck的车轮数和重量都超过了Vehicle,所以CementTruckwheelCountcurbWeightInPounds属性要覆盖Vehicle的相应属性。

代码清单5-2包含了定义这3个类的JavaScript代码。要特别注意如何在对象定义中对属性和函数附加prototype关键字,还要注意每个对象由一个构造函数定义,构造函数与对象类型同名。

代码清单5-2 inheritanceViaPrototype.js

/* Constructor function for the Vehicle object */

function Vehicle() { }


/* Standard properties of a Vehicle */

Vehicle.prototype.wheelCount = 4;

Vehicle.prototype.curbWeightInPounds = 4000;


/* Function for refueling a Vehicle */

Vehicle.prototype.refuel = function() {

return "Refueling Vehicle with regular 87 octane gasoline";

}


/* Function for performing the main tasks of a Vehicle */

Vehicle.prototype.mainTasks = function() {

return "Driving to work, school, and the grocery store";

}


/* Constructor function for the SportsCar object */

function SportsCar() { }


/* SportsCar extends Vehicle */

SportsCar.prototype = new Vehicle();


/* SportsCar is lighter than Vehicle */

SportsCar.prototype.curbWeightInPounds = 3000;


/* SportsCar requires premium fuel */

SportsCar.prototype.refuel = function() {

return "Refueling SportsCar with premium 94 octane gasoline";

}


/* Function for performing the main tasks of a SportsCar */

SportsCar.prototype.mainTasks = function() {

return "Spirited driving, looking good, driving to the beach";

}


/* Constructor function for the CementTruck object */

function CementTruck() { }


/* CementTruck extends Vehicle */

CementTruck.prototype = new Vehicle();


/* CementTruck has 10 wheels and weighs 12,000 pounds*/

CementTruck.prototype.wheelCount = 10;

CementTruck.prototype.curbWeightInPounds = 12000;


/* CementTruck refuels with diesel fuel */

CementTruck.prototype.refuel = function() {

return "Refueling CementTruck with diesel fuel";

}


/* Function for performing the main tasks of a SportsCar */

CementTruck.prototype.mainTasks = function() {

return "Arrive at construction site, extend boom, deliver cement";

}

 

 

代码清单5-3是一个很小的Web页面,展示了这3个对象的继承机制。这个页面只包含3个按钮,每个按钮创建一个类型的对象(VehicleSportsCarCementTruck),并把对象传递到describe函数。describe函数负责显示各个对象的属性值,以及对象函数的返回值。注意,describe方法并不知道它描述的对象是VehicleSportsCar,还是CementTruck,它只是认为这个对象有适当的属性和函数,并由这个对象返回自己的值。

代码清单5-3 inheritanceViaPrototype.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"

"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>JavaScript Inheritance via Prototype</title>


<script type="text/javascript" src="inheritanceViaPrototype.js"></script>


<script type="text/javaScript">


function describe(vehicle) {

var description = "";

description = description + "Number of wheels: " + vehicle.wheelCount;

description = description + "\n\nCurb Weight: " + vehicle.curbWeightInPounds;

description = description + "\n\nRefueling Method: " + vehicle.refuel();

description = description + "\n\nMain Tasks: " + vehicle.mainTasks();

alert(description);

}


function createVehicle() {

var vehicle = new Vehicle();

describe(vehicle);

}

function createSportsCar() {

var sportsCar = new SportsCar();

describe(sportsCar);

}


function createCementTruck() {

var cementTruck = new CementTruck();

describe(cementTruck);

}

</script>

</head>


<body>

<h1>Examples of JavaScript Inheritance via the Prototype Method</h1>

<br/><br/>

<button onclick="createVehicle();">Create an instance of Vehicle</button>


<br/><br/>

<button onclick="createSportsCar();">Create an instance of SportsCar</button>


<br/><br/>

<button onclick="createCementTruck();">Create an instance of CementTruck</button>


</body>

</html>

 

 

分别创建3个对象,并用describe函数描述,结果如图5-16所示。

5-16 创建VehicleSportsCarCementTruck 对象并使用describe函数分别描述的结果

 

prototype 详解

下文引自:http://www.cnblogs.com/athrun/archive/2008/06/05/1214168.html

prototype 是在 IE 4 及其以后版本引入的一个针对于某一类的对象的方法,而且特殊的地方便在于:它是一个给类的对象添加方法的方法!这一点可能听起来会有点乱,别急,下面我便通过实例对这一特殊的方法作已下讲解:

  首先,我们要先了解一下类的概念,JavaScript 本身是一种面向对象的语言,它所涉及的元素根据其属性的不同都依附于某一个特定的类。我们所常见的类包括:数组变量(Array)、逻辑变量 (Boolean)、日期变量(Date)、结构变量(Function)、数值变量(Number)、对象变量(Object)、字符串变量 (String) 等,而相关的类的方法,也是程序员经常用到的(在这里要区分一下类的注意和属性发方法),例如数组的push方法、日期的get系列方法、字符串的 split方法等等,

  但是在实际的编程过程中不知道有没有感觉到现有方法的不足?prototype 方法应运而生!下面,将通过实例由浅入深讲解 prototype 的具体使用方法:


1、最简单的例子,了解 prototype:
(1) Number.add(num):作用,数字相加
实现方法:Number.prototype.add = function(num){return(this+num);}
试验:alert((3).add(15)) -> 显示 18


(2) Boolean.rev(): 作用,布尔变量取反
实现方法:Boolean.prototype.rev = function(){return(!this);}
试验:alert((true).rev()) -> 显示 false

是不是很简单?这一节仅仅是告诉读者又这么一种方法,这种方法是这样运用的。


2、已有方法的实现和增强,初识 prototype:
(1) Array.push(new_element)
  作用:在数组末尾加入一个新的元素
  实现方法:
  Array.prototype.push = function(new_element){
this[this.length]=new_element;
return this.length;
}
  让我们进一步来增强他,让他可以一次增加多个元素!
  实现方法:
  Array.prototype.pushPro = function() {
var currentLength = this.length;
for (var i = 0; i < arguments.length; i++) {
this[currentLength + i] = arguments[i];
}
return this.length;
}
  应该不难看懂吧?以此类推,你可以考虑一下如何通过增强 Array.pop 来实现删除任意位置,任意多个元素(具体代码就不再细说了)

(2) String.length
  作用:这实际上是 String 类的一个属性,但是由于 JavaScript 将全角、半角均视为是一个字符,在一些实际运用中可能会造成一定的问题,现在我们通过 prototype 来弥补这部不足。
  实现方法:
  String.prototype.cnLength = function(){
var arr=this.match(/[^\x00-\xff]/ig);
return this.length+(arr==null?0:arr.length);
}
  试验:alert("EaseWe空间Spaces".cnLength()) -> 显示 16
  这里用到了一些正则表达式的方法和全角字符的编码原理,由于属于另两个比较大的类别,本文不加说明,请参考相关材料。


3、新功能的实现,深入 prototype:在实际编程中所用到的肯定不只是已有方法的增强,更多的实行的功能的要求,下面我就举两个用 prototype 解决实际问题的例子:
(1) String.left()
  问题:用过 vb 的应该都知道left函数,从字符串左边取 n 个字符,但是不足是将全角、半角均视为是一个字符,造成在中英文混排的版面中不能截取等长的字符串
  作用:从字符串左边截取 n 个字符,并支持全角半角字符的区分
  实现方法:
  String.prototype.left = function(num,mode){
if(!/\d+/.test(num))return(this);
var str = this.substr(0,num);
if(!mode) return str;
var n = str.Tlength() - str.length;
num = num - parseInt(n/2);
return this.substr(0,num);
}
  试验:
alert("EaseWe空间Spaces".left(8)) -> 显示 EaseWe空间
alert("EaseWe空间Spaces".left(8,true)) -> 显示 EaseWe空
  本方法用到了上面所提到的String.Tlength()方法,自定义方法之间也能组合出一些不错的新方法呀!

(2) Date.DayDiff()
  作用:计算出两个日期型变量的间隔时间(年、月、日、周)
  实现方法:
  Date.prototype.DayDiff = function(cDate,mode){
try{
cDate.getYear();
}catch(e){
return(0);
}
var base =60*60*24*1000;
var result = Math.abs(this - cDate);
switch(mode){
case "y":
result/=base*365;
break;
case "m":
result/=base*365/12;
break;
case "w":
result/=base*7;
break;
default:
result/=base;
break;
}
return(Math.floor(result));
}
  试验:alert((new Date()).DayDiff((new Date(2002,0,1)))) -> 显示 329
alert((new Date()).DayDiff((new Date(2002,0,1)),"m")) -> 显示 10
  当然,也可以进一步扩充,得出响应的小时、分钟,甚至是秒。

(3) Number.fact()
  作用:某一数字的阶乘
  实现方法:
  Number.prototype.fact=function(){
var num = Math.floor(this);
if(num<0)return NaN;
if(num==0 || num==1)
return 1;
else
return (num*(num-1).fact());
}
  试验:alert((4).fact()) -> 显示 24
  这个方法主要是说明了递归的方法在 prototype 方法中也是可行的!


分享到:
评论

相关推荐

    unicode-match-property-ecmascript:根据ECMAScript中用于RegExp Unicode属性转义的算法,将给定的Unicode属性或属性别名与其规范属性匹配

    unicode匹配属性的电子书 unicode-match-property-ecmascript将给定的Unicode属性或与其规范的属性名称,而无需用于的算法应用。 认为它是松散匹配的严格替代方案。安装要以编程方式使用unicode-match-property-...

    JavaScript-学习笔记.pdf

    以上是JavaScript学习笔记中提到的一些核心知识点,通过对这些知识点的理解和熟练应用,可以为进一步学习和掌握JavaScript打下坚实的基础。在实际开发过程中,结合具体的项目需求,这些知识会得到更深入的拓展和应用...

    2017 page661 JavaScript_Novice to Ninja, 2nd Edition-SitePoint(2017)

    - **属性删除:** 删除对象属性的操作。 - **嵌套对象:** 处理包含其他对象的对象。 - **命名空间:** 使用命名空间管理大型项目中的对象。 以上是《JavaScript: Novice to Ninja》第二版的部分内容概述,本书...

    史上最全JavaScript基础篇.doc

    ### JavaScript基础知识点详解 #### 一、简介 **JavaScript**是一种广泛使用的脚本语言,它在Web开发中占据着至关重要的...以上就是《史上最全JavaScript基础篇》中的核心知识点总结,希望对学习JavaScript有所帮助。

    JavaScript基础大全 (1-4) 学习必备珍藏品

    这个名为"JavaScript基础大全 (1-4) 学习必备珍藏品"的资源显然是一个系列教程,包含了从初级到进阶的JavaScript基础知识。让我们深入探讨一下JavaScript的核心概念和技术。 1. **基础语法**:JavaScript是一种...

    JavaScript面向对象编程指南.pdf

    4. 继承:在JavaScript中,对象可以通过原型链继承其他对象的属性和方法。原型链是一个对象的原型可以指向另一个对象的原型,这样就在不同对象间形成了一条链,从而实现继承。 5. 封装:封装是面向对象编程的一个...

    JAVASCRIPT 面向对象编程精要

    在ECMAScript 5中,`Object.defineProperty()` 方法提供了一种更精细的方式来控制对象属性的读取和写入行为。例如: ```javascript let obj = {}; Object.defineProperty(obj, 'age', { get: function () { ...

    Object-Oriented JavaScript

    在JavaScript中,虽然它本身是一种基于原型的语言,但也可以通过构造函数、类等机制实现面向对象编程。 - **特点**: - **封装**:将数据和操作数据的方法绑定在一起,隐藏内部细节。 - **继承**:子类可以继承...

    JavaScript基础入门

    ### JavaScript基础入门知识点详解 #### 一、JavaScript的起源与发展 **1.1 JavaScript的背景** - **历史沿革:** - 在互联网早期,Web技术相对单一且缺乏交互性,仅依靠HTML来构建网页。 - Netscape公司为了...

    EcmaScript面向对象1

    在ECMAScript中,面向对象是一种重要的编程范式,允许开发者通过创建和操作对象来组织代码。本文主要围绕标题"EcmaScript面向对象1"展开,探讨ECMAScript中的数据类型,特别是与面向对象密切相关的部分。 首先,...

    proposal-object-rest-spread, ECMAScript的rest/扩展属性.zip

    proposal-object-rest-spread, ECMAScript的rest/扩展属性 对象的对象 rest/扩展属性ECMAScript 6为 array literals分配了 rest元素和扩展元素( 用于 array 文本。这个建议引入了类似的rest属性对象literals分配和...

    javascript-978-1-7858-8268-5:学习ECMAScript 6

    总的来说,"javascript-978-1-7858-8268-5:学习ECMAScript 6"这本书覆盖了ES6的关键特性,通过学习这些内容,开发者能够提升JavaScript编程能力,写出更现代、更高效、更易于维护的代码。结合提供的视频教程,学习...

    Ecma-262.rar_ECMA-262_ECMAScript_javascript

    标题中的"Ecma-262.rar"指的是这个规范的文档集合,而"ECMA-262"是该规范的正式版本号,它定义了JavaScript编程语言的语法和语义规则。"ECMAScript_javascript"表明此规范与JavaScript语言密切相关,JavaScript是...

    第15章 javascript面向对象与原型

    最后,面向对象的基础知识也是不可或缺的,由于JavaScript的面向对象实现方式比较特殊,所以学习者需要了解正统的面向对象编程基础。 创建对象是面向对象编程的基础。在JavaScript中创建对象有多种方式,最简单的一...

    javascript面向对象编程PDF

    ### JavaScript面向对象编程知识点 #### 一、现代JavaScript的发展与特性 **1.1 JavaScript的演变** - **简史概述**:自诞生以来,JavaScript经历了一系列显著的变化和发展,从最初被视为一个简单的脚本语言,...

    「大学Javascript网络课考试题答案」.docx

    - **知识点:** JavaScript与Java的区别在于它们是基于对象与面向对象的区别、编译与解释的区别、类型系统的区别以及代码格式和嵌入方式的不同。 - **解析:** JavaScript是基于对象的语言,而Java是面向对象的语言;...

    Javascript知识点汇总.doc

    - ECMAScript:定义了JavaScript的基础语法和数据类型,包括变量、函数、对象等。 - DOM(Document Object Model):提供了一种结构化的表示HTML或XML文档的方式,允许JavaScript操作网页元素。 - BOM(Browser ...

    JS:prototype用法

    2. **`prototype`属性**:每个函数都有一个`prototype`属性,该属性是一个对象,包含了由构造函数创建的所有实例共享的属性和方法。 **基本使用示例**: - **数字相加**:可以通过`Number.prototype.add`为所有...

Global site tag (gtag.js) - Google Analytics