javascript数组(Array)类型检测-高级

今天遇到一个要完全复制数组的问题,因为用slice和concat进行数组复制的时候,是轻度的复制,当遇见二维数组的时候,就会出问题。

函数如下:

1 function extend (destination,source) { /* 常见的对象复制法 只能复制对象第一层 遇到对象中带对象就蔫了*/
2             
3             for (var attr in source) {
4                 destination[attr] = source[attr];
5             }
6             
7 }

 

因为二维数组的构造造成的,二维数组的时候,第一维是数组引用,第二维是才是实际的内容。依次类推,多维数组最后一维才是真正的值。

对象复制的时候,也会出现这样的问题。

然后看着一个extend()函数解决方案,自己想着先练着写一个函数完全复制的解决函数。

这就遇见了需要检测数据类型,要检测数组中某一位是否还是个数组,看到extend()函数中有句 Object.prototype.toString.call(o);

function extend (goal,source) { /* 完全复制数组函数(也可叫深度复制) */
    
        for (var attr in source) {

            if (Object.prototype.toString.call(source[attr]).slice(8,-1).toLowerCase() === 'array'  ) {
                goal[attr] = [];
                arguments.callee(goal[attr],source[attr]);
            }
            else {
                goal[attr] = source[attr];
            }
            
        }
    }
    
    var arr1 = [[1,2,3],4,5];
    var arr2 = [];

    extend(arr2,arr1);

    arr1[0][0] = 0;

    alert([arr1[0][0],arr2[0][0]]); // arr1修改没有影响到arr2,实现了完全复制

 

下面引用别人的一段,关于Object.prototype.toString()方法的介绍

ECMA-262 写道

Object.prototype.toString( ) When the toString method is called, the following steps are taken: 
1. Get the [[Class]] property of this object. 
2. Compute a string value by concatenating the three strings “[object “, Result (1), and “]”. 
3. Return Result (2) 



上面的规范定义了Object.prototype.toString的行为:首先,取得对象的一个内部属性[[Class]],然后依据这个属性,返回一个类似于"[object Array]"的字符串作为结果(看过ECMA标准的应该都知道,[[]]用来表示语言内部用到的、外部不可直接访问的属性,称为“内部属性”)。利用这个方法,再配合call,我们可以取得任何对象的内部属性[[Class]],然后把类型检测转化为字符串比较,以达到我们的目的。还是先来看看在ECMA标准中Array的描述吧: 

ECMA-262 写道

new Array([ item0[, item1 [,…]]]) 
The [[Class]] property of the newly constructed object is set to “Array”. 


写一个判断是否为数组的函数

function isArray(o) {  /* 检测是否为数组类型 */
  return Object.prototype.toString.call(o) === '[object Array]';   
}  

下面封装把这个检测数据类型方法封装下,并带检测内容

var str = 'str';
    var arr = new Array();
    var num = 0;
    var bool = true;
    var obj = {};
    var re = /^[0-9]/;
    

    getType(re); // 'regexp'
    getType(str); // 'string'
    getType(arr); // 'array'
    getType(num);  // 'number'
    getType(bool); // 'boolean'
    getType(obj); // 'object'
    getType(window.aa); // 'undefined'
    getType(undefined); // 'undefined'
    getType(null); // 'null'

function getType (o) { /* 检测数据类型函数 */
        return Object.prototype.toString.call(o).slice(8,-1).toLowerCase();        
    }

 

最后附上实现数组和函数深度复制的函数

function getType (o) {
            var _t;
            return ((_t = typeof(o)) == "object" ? o==null && "null" || Object.prototype.toString.call(o).slice(8,-1):_t).toLowerCase();
        }

        function  extend (destination,source) { /* 对象和数组深度复制函数 */

            for (var attr in source) {

                if (getType(source[attr]) == 'array' || getType(source[attr]) == 'object') {
                    destination[attr] = getType(source[attr]) === 'array' ? [] : {};
                    arguments.callee(destination[attr],source[attr]); //继续调用自己
                }
                else {
                    destination[attr] = source[attr];
                }

            }
            

 

对了还要介绍下里面用到的slice方法

stringObject.slice(start,end) // 如果传参为负数,则是从字符串末尾开始计算起的位置

str.slice(8,-1) // 即从第8位开始,截取到最后以为,slice方法返回的是截取后的新的字符串

 

最近学了面向对象,这里也附上面向对象的改写

View Code
 1 Array.prototype.extend = function (source) { /* 面向对象--深度复制数组 */
 2 
 3         for (var attr in source) {
 4 
 5             if (Object.prototype.toString.call(source[attr]).slice(8,-1).toLowerCase() === 'array'  ) {
 6                 this[attr] = [];
 7                 this[attr].extend(source[attr]);
 8             }
 9             else {
10                 this[attr] = source[attr];
11             }
12             
13         }
14 
15     }
16 
17     var arr1 = [[1,2,3],4,5];
18     var arr2 = [];
19 
20     arr2.extend(arr1);
21 
22     arr1[0][0] = 0;
23     
24     alert([arr1[0][0],arr2[0][0]]); // arr1修改没有影响到arr2,实现了完全复制

 

深度复制的出处找不到了,实在不好意思

Javascript数组类型检测:编写更强壮的isArray函数 这个包含了对各种检测的分析,比较详细(荐);

posted @ 2012-08-11 16:17  zzu-han  阅读(1076)  评论(0编辑  收藏  举报