在Javascript中扩展对象

时间:2010-05-26 14:08:21

标签: javascript oop

我正在尝试以这种方式扩展Object功能:

Object.prototype.get_type = function() {
    if(this.constructor) {
        var r = /\W*function\s+([\w\$]+)\(/;
        var match = r.exec(this.constructor.toString());
        return match ? match[1].toLowerCase() : undefined;
    }
    else {
        return typeof this;
    }
}

很棒,但有一个问题:

var foo = { 'bar' : 'eggs' };
for(var key in foo) {
    alert(key);
}

周期将有3个循环。 有什么方法可以避免这种情况吗?

6 个答案:

答案 0 :(得分:4)

我,我并不完全反对扩展原生类型和ECMA-262 5th ed。以一种很好的方式为我们解决了其他答案和链接文章中提到的问题。有关概述,请参阅这些slides

您可以扩展任何对象并定义控制这些属性行为的属性描述符。可以使该属性不可枚举,这意味着当您在for..in循环中访问对象属性时,该属性将不会包含在内。

以下是如何在Object.prototype本身上定义getType方法,并使其不可枚举:

Object.defineProperty(Object.prototype, "getType", {
    enumerable: false,
    writable: false,
    configurable: false,
    value: function() {
        return typeof this;
    }
});

// only logs "foo"
for(var name in { "foo": "bar" }) {
    console.log(name); 
}

上面的getType函数几乎没用,因为它只返回object的类型,在大多数情况下它只是对象,但它仅用于演示。

[].getType();
{}.getType();
(6).getType();
true.getType();

答案 1 :(得分:3)

您不应该扩展对象原型,原因如下:

http://erik.eae.net/archives/2005/06/06/22.13.54/

请改用静态方法。

如果您有选项,则可以使用“hasOwnProperty”方法:

Object.prototype.foo = function(){ alert('x'); }
var x = { y: 'bar' };

for(var prop in x){
  if(x.hasOwnProperty(prop)){
    console.log(prop);
  }
}

答案 2 :(得分:3)

您可以使用hasOwnProperty()方法检查属性是否属于foo对象:

var foo = { 'bar' : 'eggs' };
for (var key in foo) {
   if (foo.hasOwnProperty(key)) {
      alert(key);
   }
}

答案 3 :(得分:2)

  

有什么方法可以避免这种情况吗?

是的,不要扩展原生类型。

改为使用包装器:

var wrapper = (function(){

    var wrapper = function(obj) {
        return new Wrapper(obj);
    };

    function Wrapper(o) {
        this.obj = obj;
    }

    Wrapper.prototype = wrapper.prototype;

    return wrapper;

}());

// Define your get_type method:
wrapper.prototype.get_type = function(){
    if(this.obj.constructor) {
        var r = /\W*function\s+([\w\$]+)\(/;
        var match = r.exec(this.obj.constructor.toString());
        return match ? match[1].toLowerCase() : undefined;
    }
    else {
        return typeof this.obj;
    }
};

用法:

var obj = { 'bar' : 'eggs' };

alert(wrapper(obj).get_type());

for(var i in obj) { ... works properly }

答案 4 :(得分:1)

创建您自己的对象,而不是扩展默认对象。

另见:

答案 5 :(得分:1)

当您循环对象的可枚举属性时,您可以使用Object.hasOwnProperty()确定当前属性是否“已继承”

for ( var key in foo )
{
  if ( foo.hasOwnProperty( key ) )
  {
    alert(key);
  }
}

但是,让monkey patching的危险告诉你们,特别是在Object上,正如其他人发布的那样