本文深入解析 JavaScript 中 prototype 属性的核心概念与使用方法。通过 Number、Array、String 和 Date 等内置对象的扩展实例,详细演示如何利用 prototype 添加新功能、增强现有方法以及实现复杂逻辑如递归和日期计算,帮助开发者掌握原型链在面向对象编程中的实际应用。
JavaScript prototype 属性详解:从基础用法到实战应用
这一概念初看可能略显复杂,无需担心,接下来将通过具体实例逐步展开讲解。
首先需理解类的概念。JavaScript 作为一门面向对象语言,其元素依据属性差异依附于特定类。常见类包括数组变量(Array)、逻辑变量(Boolean)、日期变量(Date)、结构变量(Function)、数值变量(Number)、对象变量(Object)及字符串变量(String)等。程序员常使用相关类的方法,例如数组的 push 方法、日期的 get 系列方法及字符串的 split 方法等(此处需区分类的注意和属性发方法)。
在实际编程中,若觉得现有方法存在不足,prototype 方法便应运而生!下文将通过由浅入深的实例,具体讲解 prototype 的使用方法。
基础示例:Number 与 Boolean 扩展
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
操作是否简单?本节旨在向读者展示该方法的存在及其基本运用方式。
增强现有方法:Array 与 String 操作
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 方法中也是可行的!