扩展js原生对象的正确姿势

1 前言

首先个人不推荐修改原生对象。原因有两个:

  • 没有必要。第三方类库和自定义类完全可以满足需求。
  • 维护问题。

但是项目中总会遇到这样的情况,原生的js对象被修改,但是手法很拙劣。

那就开始吧。这里我们以Array为例。

2 不正确的姿势

2.1 Array.method

这样并不能为array 对象添加新的方法。

2.2 Array.prototype.method

添加了一个方法method,而且之后所有新建的Array对象都有了一个名叫method方法。

        Array.prototype.method = function(){
            console.log('I am an user defined method!');
        }

        var a = [];
        a.method();

console中输出了 I am an user defined method!。看起来很完美啊。

但是当我们for in遍历这个数组的时候,发现method也出现在结果之中了。这显然不是我们希望的结果。

        for(x in a){
            console.log(x+':'+a[x])
        }

console中输出了 :

method:function (){
            console.log('I am an user defined method!');
        }

看起来这种方法是有副作用的。以后我们使用for in的时候,必须手动过滤掉这个method。

比如利用typeof

        for(x in a){
            if(typeof a[x] === 'function') continue;
            console.log(x+':'+a[x])
        }

3 正确姿势

这是正确的方式,先上代码:

        Object.defineProperty(Array.prototype,'method',{
            writable:false,
            enumerable:false,
            configurable:true,
            value:function(){
                console.log('I am an user defined method!');
            }
        });

是否有效大家可以自己尝试,下面说明一下其中的参数。

  • Array.prototype 表示属性会添加到Array的prototype,这样,所有新建的数组对象都会拥有这个属性。
  • ‘method’ 属性名,可以使用变量。这样就可以动态的添加某些属性了。
  • {} 一个对象,包含四个属性,当某个属性未提供时,默认是false或者undefined。
    writable
    enumerable 是否可被枚举,设为false,就不能被for in遍历到啦
    configurable
    value 属性的值

writable 和 configurable 的规则比较复杂,并不像字面上那样简单。暂时不解释。

如果要一次定义多个属性
可以这样

        Object.defineProperties(Array.prototype,
            {
                method1:{
                    writable:true,
                    enumerable:false,
                    configurable:true,
                    value:function(){
                        console.log('I am an user defined method 1!');
                    }
                },
                method2:{
                    writable:true,
                    enumerable:false,
                    configurable:true,
                    value:function(){
                        console.log('I am an user defined method 2!');
                    }
                }
            }
        );

注意这种方式不方便传递动态的函数名了。

4 总结

JavaScript允许修改,扩展原生类的属性,并且在属性的特性,如可修改,可枚举,可配置上提供了一些选择。通过这些属性的组合可以设计出更加贴合实际需求的类。比如,我们可以设计一个Person类,当Person的性别被初始化之后,不允许再进行修改(个别情况还是允许的)。

你可能感兴趣的:(web前端)