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

问题描述 投票:-1回答:2

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

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

  1. 排列
  2. 宾语
  3. 日期
  4. 功能
  5. 布尔

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

/********************************************************/
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.时,属性|方法的弹出列表不再包含对len属性的引用,但如果我输入完整扩展名n.leno.len,我会得到所需的结果32 ...

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

所以我写了一个测试块来尝试识别问题:

/********************************************************/
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的控制台中扩展e后,我立即注意到所有3个都被赋予了dis属性,我原本试图仅仅分配给o对象。

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

我怎样才能将dis属性仅仅附加到o对象而不被nObject.prototype继承?

javascript object prototype defineproperty
2个回答
3
投票

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

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

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

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

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

好...

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

怎么样?

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

由于o只继承自Object,因此无法定义只出现在普通对象上而不出现在其他所有内容上的属性。您的选择是:

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


Note: Of course, you could modify Number.prototype to have a dis property of undefined:
Object.defineProperty(Number.prototype, 'dis', {
    value: void 0
});

console.log((9).dis);

就数字而言,这将解决你的问题,但dis属性仍将存在于其他所有存在的东西中。

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


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上定义一个名为len的属性,并将其值设置为5
  • 现在,如果我们调用{}.len,我们得到5的结果,如果我们调用[].len"".len#.len等,我们得到相同的结果,因为Object.prototype在实例化时继承。
  • 但是,假设我们在Array.prototype上使用相同的名称定义一个属性: - len并将其值设置为50
  • 现在如果我们调用{}.len等,我们得到相同的结果5,但如果我们调用[].len我们得到50,因为Array.prototype是最近创建的,它的定义len覆盖了Object.prototype的版本。

解:

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

缺点:

  • 无法再以简单的方式访问{}.len,它现在必须以{}._.len为前缀。

优点:

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

扩张:

  • 我正在考虑修改此代码以适应不符合此标准的各种对象,例如可能是以下处理程序:
x=document.getElementsByTagName('td')
y=x._.len

喜欢:

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.nameobject而不是HTMLCollection

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

© www.soinside.com 2019 - 2024. All rights reserved.