如何创建其行为像一个真正的数组构造? [英] How to create a constructor which behaves like a true Array?

查看:94
本文介绍了如何创建其行为像一个真正的数组构造?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何创建一个自定义的数组构造,这是原生Array构造函数的扩展版本?

jQuery的,例如,看起来像其他方法,如 $()数组。addClass 。然而,它并没有修改 Array.prototype ,因为新的Array()。hasClass 未定义

所以,我怎样才能创建一个扩展阵列实现,而无需修改 Array.prototype

示例:

 员工(...)//  - > [{名称:'约翰',年龄:32},{名称:'鲍勃',年龄:29}];
员工(...).byAge(32)// - > [{名称:'约翰',年龄:32}];
//和
。阵列()// byAge - >未定义


解决方案

jQuery是不是真正的数组实现:<!code>的jQuery的instanceof阵列为假

如果你想创建一个数组的真实情况下,添加自定义的方法,使用这个code。它采用 Function.prototype.bind 调用构造函数参数的任意数量。

的实施行为的究竟作为一个真正的数组,除了在一个点上:


  • 阵列构造函数带一个参数,它的创建与此参数的长度数组。

  • 由于此功能往往是错误的根源,我决定忽略它在执行。您仍然可以通过设置长度属性设置中的 N 的长度。

code: http://jsfiddle.net/G3DJH/

 职能部门的员工(){
    //缺少新新政
    如果(!(这个的instanceof员工)){
        //转换参数数组,因为我们有1至所有索引转移
        变参= Array.prototype.slice.call(参数);
        args.unshift(本); //移所有索引,设置本
        返回新(Function.prototype.bind.apply(雇员,参数));
    }其他{
        //设置length属性。
        VAR LEN =与arguments.length,
            / *
             * fn_internalLength:用于计算长度内部方法
             ** /
            fn_internalLength,
            / *
             * explicitLength:涉及明确的长度设定
             ** /
            explicitLength = 0;        //设置所有的数字键
        而(len--){
            这个[LEN] =参数[LEN]
        }        //定义长度内部方法
        fn_internalLength =功能(){
            VAR allKeys = Object.keys(本)的.sort(函数(X,Y){
                //排序列表。顶部最高指标。
                返回是 - X;
            }),I = -1,长度= allKeys.length,的tmpKey,
            foundLength = 0;            //循环遍历所有的键
            而(+ I&所述;长度&放大器;及(的tmpKey = allKeys [I])&GT; = 0){
                //是关键是INTEGER?
                如果(的tmpKey - 的tmpKey === 0安培;&放大器;的tmpKey%1 === 0){
                    foundLength = 1 *的tmpKey + 1;
                    打破;
                }
            }
            //返回MAX(实际长度,显式地设置长度)
            返回foundLength&GT; explicitLength? foundLength:explicitLength;
        } .bind(本);        //定义魔法length属性
        Object.defineProperty(这一点,长度,
        {
            得到:fn_internalLength,
            设置:功能(满足newLength){
                VAR长度= fn_internalLength();
                如果(满足newLength&LT;长度){
                    对于(VAR I =满足newLength; I&LT;长度;我++){
                        删除[I]
                    }
                }
                //设置明确的长度
                explicitLength =满足newLength;
            },
            枚举:假的,
            配置:假的
        });
    }
}
Employees.prototype =新的阵列;
//例:自定义的方法:
Employees.prototype.print =功能(){
    返回this.join(' - '); //使用继承Array.prototype.join
};//就像阵列,`new`是可选
的console.log(新员工(1,2).PRINT());
的console.log(雇员(1,2).PRINT());//是对象的数组?
的console.log(新员工()的instanceof阵列); //真!
//不能相信吗?
的console.log(新员工()的instanceof员工); //真!

How can I create a custom array constructor, which is an extended version of the native Array constructor?

jQuery, for example, looks like an array with additional methods, such as $().addClass. However, it didn't modify Array.prototype, because new Array().hasClass is undefined.

So, how can I create an extended array implementation, without modifying Array.prototype?

Example:

Employees( ... )          //-> [{name: 'John', age: 32}, {name: 'Bob', age: 29}];
Employees( ... ).byAge(32)//-> [{name: 'John', age: 32}];
// and
Array().byAge             //-> undefined

解决方案

jQuery is not a true Array implementation: jQuery instanceof Array is false!

If you want to create a true instance of an array, and add custom methods, use this code. It uses Function.prototype.bind to call a constructor with an arbitrary number of parameters.

The implementation behaves exactly as a true array, except at one point:

  • When the Array constructor is called with a single argument, it's creating an array with a length of this argument.
  • Since this feature is often a source of bugs, I have decided to omit it in the implementation. You can still set a length of n by setting the length property.

Code: http://jsfiddle.net/G3DJH/

function Employees() {
    // Deal with missing "new"
    if (!(this instanceof Employees)) {
        // Convert arguments to an array, because we have to shift all index by 1
        var args = Array.prototype.slice.call(arguments);
        args.unshift(this); // Shift all indexes, set "this" 
        return new (Function.prototype.bind.apply(Employees, args));
    } else {
        // Set length property.
        var len = arguments.length,
            /*
             * fn_internalLength: Internal method for calculating the length
             **/
            fn_internalLength,
            /*
             * explicitLength: Deals with explicit length setter
             **/
            explicitLength = 0;

        // Setting all numeric keys
        while (len--) {
            this[len] = arguments[len];
        }

        // Internal method for defining lengths
        fn_internalLength = function() {
            var allKeys = Object.keys(this).sort(function(x, y) {
                // Sort list. Highest index on top.
                return y - x;
            }), i=-1, length = allKeys.length, tmpKey,
            foundLength = 0;

            // Loop through all keys
            while (++i < length && (tmpKey = allKeys[i]) >= 0) {
                // Is the key is an INTEGER?
                if (tmpKey - tmpKey === 0 && tmpKey % 1 === 0) {
                    foundLength = 1*tmpKey + 1;
                    break;
                }
            }
            // Return MAX(actual length, explictly set length)
            return foundLength > explicitLength ? foundLength : explicitLength;
        }.bind(this);

        // Define the magic length property
        Object.defineProperty(this, 'length',
        {
            get: fn_internalLength,
            set: function(newLength) {
                var length = fn_internalLength();
                if (newLength < length) {
                    for (var i=newLength; i<length; i++) {
                        delete this[i];
                    }
                }
                // Set explicit length
                explicitLength = newLength;
            },
            enumerable: false,
            configurable: false
        });
    }
}
Employees.prototype = new Array;


// Example: Custom method:
Employees.prototype.print = function() {
    return this.join('--'); // Using inherit Array.prototype.join
};

// Just like the Array, `new` is optional
console.log(new Employees(1,2).print());
console.log(Employees(1,2).print());

// Is the object an array?
console.log(new Employees() instanceof Array);    // True!
// Can't believe it?
console.log(new Employees() instanceof Employees); // True!

这篇关于如何创建其行为像一个真正的数组构造?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆