JavaScript对象及继承教程之内置对象(1)(2)
indexOf 和 lastIndexOf 方法。
这两个方法从是从字符串中查找一个字符或字符子串,区别在于查找方向,前者是从位置 0 处开始查找,并返回第一个查找到的位置,后者从位置 length-1 处开始查找,并返回第一个查找到的位置。如果查找不到呢,返回 -1 。例如
- var str = "了解面向对象编程和基于对象编程是一个基础理论";
- alert(str.indexOf("对象")); //output:4
- alert(str.lastIndexOf("对象"));//output:11
- alert(str.indexOf("过程"));//output:-1
从输出的结果我可以得到以下结论:
1、 字符位置是从 0 开始索引
2、 即使是从后往前查找,返回位置时也还是位置 0 开始计算
3、 当在字符串中索引不到该子串时,返回 -1 值。
charAt 和 charCodeAt 方法根据一个位置索引来返回字符,其中前者是返回字符本身,后者返回字符编码。我们简单的看个例子后结束他们:
- var str = "了解面向对象编程和基于对象编程是一个基础理论";
- alert(str.charAt(5)); //output:象
- alert(str.charCodeAt(5));//output:35937
接下来轮到 slice , substr 和 substring 方法,说实话很多熟悉 JavaScript 的程序员也经常会混淆两者的用法,并非是我夸张,而是 substring 和很多后台语言的 substring 方法区别很大的哦。先看看 slice 方法。
slice(start[,end]) 方法需要提供至少一个整数参数,作用是返回从 start 的位置开始到 end 位置的字符子串。接下来几句话请仔细看清楚了,以防造成曲解,当参数 start 为负数的时候他将从字符串尾部开始计算,当 end 没有指定时, end 即为字符串的结尾。如果为负数呢,他也要从字符串尾部开始计算。所以当我们需要一个字符串的之后 3 个字符时只需 slice(-3); 由此可见,合理的使用负数让我们的程序变得简单。但是在此之前,请确保自己了解了他的作用。
据我所知的编程语言中,有很大一部分的 substring 方法设计为 substring(beginposition,length) ,而在 JavaScript 中正好也有这么一个方法,可惜真正与之对应的是 substr 方法。 substr(pos[,length]) 方法中,如果 pos 为负数,则与 slice 的负数解释相同, length 省略时与 slice 的 end 省略也相同。
到了 substring 方法, substring(from[,to]); 从定义上就可以看到,后一个参数是一个位置,而非长度,因此他更像 slice ,但是与之有一点重要的区别,那就是 substring 方法不包含 to 位置。即是一个半开半闭区间。另一个区别是 substring 不支持负向位置,如果第一个参数为负数,那么就是从位置 0 开始。后一个位置如果是负数,则返回空串,如果第二个参数小于第一个参数,那么同样返回空串,但是如果相等呢,还是空串,因为这是一个半开半闭区间 [from,to) 。
另外几个查找的方法 :match 、 search 将在后面介绍正则表达式和 RegExp 类的时候详细介绍。替换方法 replace 也将在介绍正则表达式时介绍。另外一对有用的方法是 toLowerCase 和 toUpperCase 。他们就是将字符串进行大小写转换的。
字符串操作的另一个领悟的连接字符串。字符串对象是长度不可变的,仔细回顾下之前所有的方法中没有一个是修改对象本身的方法。关于这点将于稍后一个思考题单独会展开来介绍。现在你要做的就是知道这点。字符串对象的连接方法常见的三种,第一种是使用 concat 方法,在介绍 Array 类的时候我们也见过这个方法,他们其实是一样的东西,连接字符串为一个新串,另外字符串对象重载了 + 号运算符,用来简化连接操作,因此 "abc"+"de" == "abcde"; 还有一个方法是借助 Array 对象中的 push 和 join 方法连接字符串。
- var arr = [];
- for(var i = 0; i < 10; i++) {
- arr.push("<img alt="test" src="pic" + i + ".jpg" />");
- }
- arr = arr.join("");
这种方法很类似与 C# 中的 StringBuilder 的 append 和 ToString 方法,而好处也很类似。不要忘了在 join 的方法中加上参数""哦,否则的话,多出的逗号可能就有点事与愿违了。为了方便操作,我们通常还会扩展一个方法来模拟 printf(in c) 和 format(in c#):
- function formatString() {
- var args = arguments;
- if(args.length > 1) {
- return args[0].replace(new RegExp
- ("{([0-" + (args.length-2).toString() + "])}","g"),function(s,m){
- return args[+m+1];
- });
- }
- }
首先我要说明,这个方法与原来的方法相比丑陋了许多,但是更容易理解,其次,这个方法有自身的 bug 存在,即当参数过多(>10)时,正则表达式将不能正确运转。因此我们换个解决方案来解决这个 bug (感谢zswang 的仔细,下面的解决方案也是仿照zswang的。)
- function formatString(str,params) {
- return str.replace(/{(d+)}/g,function(s,m){
- return params[+m];
- });
- }
- alert(formatString("{0} is {1} old",['JeeChang',25]));
JavaScript 中没有一个 trim 方法,让我们很是苦恼,没有例外,我们自己写一个 trim 方法吧
- String.prototype.trim = function(which){
- var pattern = {
- "left":"^s*",
- "right":"s*$",
- "both":"^s*|s*$"
- }
- return this.replace(new RegExp(pattern[which],'g'),"");
- };
字符串的操作一直都不仅限于此,比如字符串截取往往还有这样的需求,即我们在浏览器显示的时候往往需要根据全半角来截断字符串,但是最后一个字符是全角的话则需要全部截断。看上去一定很复杂吧。没关系我们来添加这个方法。
- String.prototype.splitCount = function(count){
- var str = this;
- var signs =
- ['~','!','|','`',':','$','#','&','*','@','.','?'];
- var sign = '';
- for(var i = 0; i < signs.length; i++) {
- if(str.indexOf(signs[i]) < 0) {
- sign = signs[i];
- break;
- }
- }
- str = str.replace(/[^u0000-u00FF]/g,sign + sign);
- var ig = count;
- for(var i = 0; i < count; i++) {
- if(str[i] == sign)
- ig-=0.5;
- }
- return this.substr(0,Math.floor(ig));
- };
这个方法很可惜,替换字符不够全面,如果恰巧这些字符都存在于其中,那么结果就很可悲了。所以这个方法不是那么的可靠。其实可以通过初步判断总字符长度来截取掉后面的字符串然后再查找是否有替换字符。这样概率就相对小些。
介绍完了数组对象和字符串对象之后,我们看下面一个例子:
- var a = "abc";
- var b = "abc";
- alert(a.valueOf() === b.valueOf);
- alert(a.toString() === b.toString());
- alert(a.valueOf() == b.valueOf());
- var arr1 = ['a','b','c'];
- var arr2 = ['a','b','c'];
- alert(arr1.toString() === arr2.toString());
- alert(arr1.valueOf() === arr2.valueOf());
请问输出结果是什么呢?
4、 Date类
日期类恐怕是我见过最无奈的JavaScript内置类(对象)。因为他的浏览器不同表现,时间日期的操作处理都显得那么的不友好。幸好,JavaScript固有的机制可以让我们自己来解决这些问题。不过在此之前我们还是先大致了解下他的一些方法和属性。
创建一个日期对象可以有这些方法
方法一:
- var d = new Date(ms);//ms代表从1970.1.1凌晨0点的毫秒数
方法二:
- var d = new Date(year,month[,day,hour,minute,second,millisecond]);
方法三:
- var d = new Date("localDateString");//这里不是那么的通用。2011/5/5格式相对通用
如果我们需要创建一个当前时间的日期对象。直接new Date()用无参数的构造函数即可。当然我们不能忽略这个new,前面提到String和Array可以省略,然而这里千万不能这样做。因为Date()的结果是浏览器实现的一个日期对象的toString返回的表示日期的字符串。故此,这里两者不能混用。
日期对象的方法大致分为获取和设置日期时间的某一(几)个部分。获取方法相对好用一些,然后设置方法则显得不那么够用。这里有几个需要拿出来先说说。
getDate/setDate。该方法操作的是天数,而非日期值。这个还是有点不大直观的。
getDay/setDay。该方法操作的是周数,序数从0开始,即周日的值是0。
getMonth/setMonth。该方法操作的是月数没有疑问,但是月数是从0开始。
getFullYear/setFullYear。我通常建议用这组方法来代替直观的getYear/setYear。
toDateString/toTimeString==输出日期的方法。但是并不是那么的好用。
接下来,让我们一步一步来打造更适合自己的一套方法。
首先,我们来格式化输出
- var conf = {
- syslang : "cn" //设置系统语言
- };
- Date.prototype.toFormatString = function(format) {
- var weeks = {};
- weeks['cn'] = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
- weeks['en'] =
- ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
- var self = this;
- var fix = {
- 'yyyy':self.getFullYear(),
- 'MM':self.getMonth()+1,
- 'dd':self.getDate(),
- 'wk':weeks[conf.syslang][self.getDay()],
- 'hh':self.getHours(),
- 'min':self.getMinutes(),
- 'ss':self.getSeconds()
- };
- return format.replace(/[a-zA-Z]+/g,function(m){
- return fix[m];
- });
- };
嗯,这个方法多了个全局的配置对象,但是这个不是必须的,只是在这里提示大家如果实现个性化定制,但是如果是自己的项目使用,我更建议减少代码(把en或cn去掉)来打造适合自己项目的精简代码。该方法的使用一目了然,在这里也不多解释了。
接下来是日期的操作,第一组是日期的加减。熟悉.net的朋友都知道AddXXX的一组方法,因此我们也可以打造一组这样的代码,在此我只列举一个,有需要的可以自己实现其他的。其实这套方法可以使用伪泛型的方式将Add方法组并到一个方法。但是我更愿意用一目了然的方法名来提供。
- Date.prototype.addMonth = function(n){
- var month = this.getMonth();
- this.setMonth(month+n);
- };
怎么样,很简单吧。不用担心溢出(13月)或者负月份(-1月)会造成什么不良后果,日期对象会自己为了通过调整年数来得到合适的结果。
接下来是日期比较。纯粹的日期比较不是问题,因为getTime获取毫秒数之后进行加减操作即可。然而如果要是比较相差的天数怎么办呢。其实也简单。那就是相差的毫秒数换算到天数即可
- Date.prototype.compareTime = function(time) {
- var ticks = time.getTime() - this.getTime();
- return Math.floor(ticks/(1000*60*60*24));
- }
至于比较周数同理,但是月数和年数呢?对不起,考虑到闰年和大小月等问题,这个方法比较复杂,在这里就不贴出来了,如果您有兴趣不妨尝试着自己写写看。
原文链接:http://blog.csdn.net/cj205/archive/2011/01/23/6159709.aspx






