A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

Array 对象属性
属性                         描述                                FF     IE
constructor        返回对创建此对象的数组函数的引用。       1        4
index                                                         1        4
input                                                         1        4
length                设置或返回数组中元素的数目。                 1        4
prototype        使您有能力向对象添加属性和方法。         1        4

1.1         length
          说明:Length属性表示数组的长度,即其中元素的个数。因为数组的索引总是由0开始,所以一个数组的上下限分别是:0和length-1。和其他大多数语言不同的是,JavaScript数组的length属性是可变的,这一点需要特别注意。当length属性被设置得更大时,整个数组的状态事实上不会发生变化,仅仅是length属性变大;当length属性被设置得比原来小时,则原先数组中索引大于或等于length的元素的值全部被丢失。

下面是演示改变length属性的例子:
var arr=[12,23,5,3,25,98,76,54,56,76];//定义了一个包含10个数字的数组
        alert(arr.length); //显示数组的长度10
         arr.length=12; //增大数组的长度
        alert(arr.length); //显示数组的长度已经变为12
         alert(arr[8]); //显示第9个元素的值,为56
         arr.length=5; //将数组的长度减少到5,索引等于或超过5的元素被丢弃
        alert(arr[8]); //显示第9个元素已经变为"undefined"
         arr.length=10; //将数组长度恢复为10
         alert(arr[8]); //虽然长度被恢复为10,但第9个元素却无法收回,显示"undefined"

         由上面的代码我们可以清楚的看到length属性的性质。但length对象不仅可以显式的设置,它也有可能被隐式修改。JavaScript中可以使用一个未声明过的变量,同样,也可以使用一个未定义的数组元素(指索引超过或等于length的元素),这时,length属性的值将被设置为所使用元素索引的值加1。

例如下面的代码:
var arr=[12,23,5,3,25,98,76,54,56,76];//定义了一个包含10个数字的数组
alert(arr.length);// 显示10
arr[15]=34;
alert(arr.length);//显示16

代码中同样是先定义了一个包含10个数字的数组,通过alert语句可以看出其长度为10。随后使用了索引为15的元素,将其赋值为15,即 arr[15]=34,这时再用alert语句输出数组的长度,得到的是16。无论如何,对于习惯于强类型编程的开发人员来说,这是一个很令人惊讶的特性。事实上,使用new Array()形式创建的数组,其初始长度就是为0,正是对其中未定义元素的操作,才使数组的长度发生变化。

由上面的介绍可以看到,length属性是如此的神奇,利用它可以方便的增加或者减少数组的容量。因此对length属性的深入了解,有助于在开发过程中灵活运用。

1.2         prototype
说明: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(arguments) {
          var currentLength = this.length;
          for (var i = 0; i < arguments.length; i++) {
              this[currentLength + i] = arguments;
        }
          return this.length;
      }
 
(2)javascript中无法通过一个索引去移除一个无素.通过对ARRAY的扩展.实现了对javascript Array对象通过索引移除数组中的一个元素.
让我们来实现他!
实现方法:
Array.prototype.remove=function(index)
   {
     if(isNaN(index)|| index >this.length){return false;}
     for(var i=0,n=0;i<this.length;i++)
     {
         if(this!=this[index])
         {
             this[n++]=this
         }
     }
     this.length-=1
}

(3) 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 方法中也是可行的!
1.3         Constructor
说明:表示创建对象的函数。始终指向创建当前对象的构造函数。
比如下面例子:
// 等价于 var foo = new Array(1, 56, 34, 12);  
var arr = [1, 56, 34, 12];  
console.log(arr.constructor === Array); // true  
// 等价于 var foo = new Function();  
var Foo = function() { };  
console.log(Foo.constructor === Function); // true  
// 由构造函数实例化一个obj对象  
var obj = new Foo();  
console.log(obj.constructor === Foo); // true   
// 将上面两段代码合起来,就得到下面的结论  
console.log(obj.constructor.constructor === Function); // true

但是当constructor遇到prototype时,有趣的事情就发生了。
我们知道每个函数都有一个默认的属性prototype,而这个prototype的constructor默认指向这个函数。
如下例所示:
  function Person(name) {
         this.name = name;
   };
   Person.prototype.getName = function() {
        return this.name;
   };
var p = new Person("ZhangSan");
console.log(p.constructor === Person);  // true
console.log(Person.prototype.constructor === Person); // true
// 将上两行代码合并就得到如下结果
console.log(p.constructor.prototype.constructor === Person); // true
当时当我们重新定义函数的prototype时(注意:和上例的区别,这里不是修改而是覆盖),constructor属性的行为就有点奇怪了,
如下示例:
function Person(name) {
    this.name = name;
};
Person.prototype = {
    getName: function() {
       return this.name;
    }
};
var p = new Person("ZhangSan");
console.log(p.constructor === Person);  // false
console.log(Person.prototype.constructor === Person); // false
console.log(p.constructor.prototype.constructor === Person); // false
怎么修正这种问题呢?方法也很简单,重新覆盖Person.prototype.constructor即可,
如下示例:
function Person(name) {
    this.name = name;
};
Person.prototype = new Object({
    getName: function() {
        return this.name;
    }
});
Person.prototype.constructor = Person;
var p = new Person("ZhangSan");
console.log(p.constructor === Person);  // true
console.log(Person.prototype.constructor === Person); // true
console.log(p.constructor.prototype.constructor === Person); // true

0 个回复

您需要登录后才可以回帖 登录 | 加入黑马