如何在不将其应用于Number.prototype的情况下向Object.prototype添加属性?

时间:2015-01-22 08:18:21

标签: javascript object prototype defineproperty

我的目标是创建 master_script.js 。主要用于开发的处理程序文件。

此文件的子部分专门用于自定义基础对象的原型:

  
      
  1. 字符串
  2.   
  3.   
  4. 阵列
  5.   
  6. 对象
  7.   
  8. 日期
  9.   
  10. 功能
  11.   
  12. 布尔
  13.   

所以当我写出我的代码块时......

/********************************************************/
Object.defineProperty(
    Number.prototype,'len',
    {get:function(){
        str=this.toString()
        return str.length
    }}
)
/********************************************************/
n=123
o={123:'abc',abc:123}
/********************************************************/
console.log(
    'n              ⇒ ',n,
    '\n n.len       ⇒ ',n.len,
    '\n n.__proto__ ⇒ ',n.__proto__
)
/********************************************************/

工作正常!

  • 当我在控制台中展开n.__proto__时,会显示len: (...)属性及其getter函数get len: function (){
  • 当我在控制台中输入n.时,它在属性列表中清晰可见。

当我为o变量配置相同的设置时,问题就开始了:

/********************************************************/
Object.defineProperty(
    Number.prototype,'len',
    {get:function(){
        str=this.toString()
        return str.length
    }}
)
/******************************/
Object.defineProperty(
    Object.prototype,'len',
    {get:function(){
        cnt=0
        for(i in this)  cnt++;
        return cnt
    }}
)
/********************************************************/
n=123
o={123:'abc',abc:123}
/********************************************************/
console.log(
    'n              ⇒ ',n,
    '\n n.len       ⇒ ',n.len,
    '\n n.__proto__ ⇒ ',n.__proto__
)
/******************************/
console.log(
    'o              ⇒ ',o,
    '\n o.len       ⇒ ',o.len,
    '\n o.__proto__ ⇒ ',o.__proto__
)
/********************************************************/

我注意到的第一件事是,当我现在在控制台中键入n.o.时,属性|方法的弹出列表不再包含对{的引用{1}}属性,但如果我输入完整的扩展程序lenn.len,我会得到o.len3 ...

的预期结果

所以我知道代码是合法的但我需要控制台弹出窗口,因为有大约40种不同的属性和& 7个基础对象中的每一个的方法......

所以我写了一个测试块试试&找出问题:

2

/********************************************************/ Object.defineProperty( Object.prototype,'dis', {get:function(){return this}} ) /******************************/ Object.defineProperty( Number.prototype,'len', {get:function(){return this.length}} ) /********************************************************/ o={123:'abc',abc:123} n=123 e=document.createElement('option') /********************************************************/ console.log( 'o ⇒ ',o, '\n o.__proto__ ⇒ ',o.__proto__ ) /******************************/ console.log( 'n ⇒ ',n, '\n n.__proto__ ⇒ ',n.__proto__ ) /******************************/ console.log( 'e ⇒ ',e, '\n e.__proto__ ⇒ ',e.__proto__ ) /********************************************************/ .__proto__和现在o控制台中展开n后,我立即注意到所有3个都已发出我最初尝试分配给e对象的dis属性。

然后我破解了它:o本身就是一个对象,它继承了Number.prototype

dis属性

如何将Object.prototype属性仅追加到dis对象,而不on继承?

2 个答案:

答案 0 :(得分:3)

  

此文件的子部分专门用于自定义基础对象的原型

Oy vey。不是最好的主意恕我直言。特别是修改Object原型。 Yeesh。

  

所以我知道代码是合法的,但我需要控制台弹出窗口,因为有大约40种不同的属性& 7个基础对象中的每一个的方法......

为什么呢?您是否在浏览器控制台中进行开发?

  

你有没有告诉我如何将dis属性仅仅附加到o对象而不是由Object.prototype中的n继承?

好的...

Object.defineProperty(
    o, 'dis',
    { get:function(){ return this; } }
);

怎么样?

你添加到Object原型的任何内容都会出现在所有内容上(这就是为什么这是一个坏主意)。

由于o 仅从<{1}}继承,因此无法定义仅显示在普通对象上而不显示在其他所有内容上的属性。您的选择是:

  • 直接在Object
  • 上定义属性
  • 不使用o的普通对象,而是从您自己的自定义类型创建o,并将您的属性放在该自定义类型的原型上(比修改内置类型的原型要好得多) )。

<小时/> 注意:当然,您可以修改o,使Number.prototype属性为dis

undefined

就数字而言,这样可以解决你的问题,但Object.defineProperty(Number.prototype, 'dis', { value: void 0 }); console.log((9).dis); 属性仍然存在于其他所有其他属性中。

请为了善良,请使用分号。想想孩子们。

答案 1 :(得分:0)

检查出来:

/********************************************************
⇒   create the master objects.
/********************************************************/
function MasterObject(dis){
    Object.defineProperty(
        this,'this_object',
        {get:function(){return dis}}
    )
}
/******************************/
function MasterArray(dis){
    Object.defineProperty(
        this,'this_array',
        {get:function(){return dis}}
    )
}
/********************************************************
⇒   define the master properties.
/********************************************************/
Object.defineProperty(
    Object.prototype,'_',
    {get:function(){return new MasterObject(this)}}
)
/******************************/
Object.defineProperty(
    Array.prototype,'_',
    {get:function(){return new MasterArray(this)}}
)
/********************************************************
⇒   example to expand in the console.
/********************************************************/
x={a:1,b:2,c:3,d:4,e:5}
y=[]
    y['a']=1
    y['b']=2
    y['c']=3
    y['d']=4
    y['e']=5
z=[x,y]
/********************************************************
⇒   open the console, type [z], hit [enter] and expand...
/********************************************************/

流程:

  • 比方说,我们在名为Object.prototype&amp;的len上定义一个属性。将其值设置为5
  • 现在,如果我们拨打{}.len,我们会得到5&amp;如果我们调用[].len"".len#.len等,我们会因实例化Object.prototype的继承而得到相同的结果。
  • 但是,假设我们在Array.prototype上使用相同的名称定义了一个属性: - len&amp;将其值设置为50
  • 现在,如果我们拨打{}.len等,我们会得到相同的结果5,但如果我们调用[].len,我们会得到50,因为Array.prototype最近创建了它的定义len会覆盖Object.prototype的版本。

解决方案:

  • 因此,如果我们只为Object.prototype定义一个属性,那么为简单起见_,&amp;将其值设置为子结构对象,该对象包含仅特定于对象的处理程序。
  • 然后,如果我们对Array.prototype执行相同操作,但将此_属性的值设置为包含仅限于数组的处理程序的另一个子结构。
  • 然后与上面.len Array.prototype_版本Object.prototype版本_版本号{}.len版本一样,我们有2个完全独立{{1}没有其他遗产的属性。

缺点:

  • 无法再轻松访问属性{}._.len,现在必须以Object.prototype作为前缀。

优点:

  • Object.prototype上定义属性时,整个任务可能会成为一个自相矛盾的噩梦,甚至抛出到控制台的错误都会继承属性,如果你向_添加了100个新的属性方法,那么当您在控制台中展开任何错误时,每个都可见!
  • 此方法确保只有1个属性可见x=document.getElementsByTagName('td') y=x._.len ,并且该属性可根据所有者对象的类型进行自定义。

扩展:

  • 我正在考虑修改此代码以适应 NOT 符合此标准的各种对象,例如可能是以下处理程序:
function MasterObject(dis){
    if(dis.constructor.name=='HTMLCollection'){
        Object.defineProperty(
            this,'len',
            {get:function(){
                cnt=0
                for(ia in dis) cnt++;
                return cnt
            }}
        )
    }
        else{
            Object.defineProperty(
                this,'this_object',
                {get:function(){return dis}}
            )
        }
}

像:

x._.len

因此{a:1}可用于任何对象列表,但不会说constructor.name,因为object HTMLCollection而不是{{1}}。

这是一个宠物项目。它只是在它自己的原型阶段,我正在寻找关于如何扩展这个概念的想法,从那些有这个主题经验的人那里,我要么回到过去的方式,要么突破这个围绕原型修改的耻辱,并想出来一种新的更有效的方式!