简体   繁体   English

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

[英]How can I add a property to Object.prototype without it being applied to Number.prototype?

My goal is to create a master_script.js . 我的目标是创建一个master_script.js A handler file mainly used in development. 主要用于开发的处理程序文件。

A subsection of this file is dedicated to customizing the prototypes of the foundation objects: 该文件的一个小节专门用于自定义基础对象的原型:

  1. String
  2. Number
  3. Array 数组
  4. Object 宾语
  5. Date 日期
  6. Function 功能
  7. Boolean 布尔型

So as I'm writing out my code blocks... 所以当我写我的代码块时...

/********************************************************/
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__
)
/********************************************************/

Works fine! 工作正常!

  • when I expand n.__proto__ in the console it displays the len: (...) property and it's getter function get len: function (){ . 当我在控制台中展开n.__proto__时,它显示len: (...)属性,并且它是getter函数get len: function (){
  • and when I type n. 当我输入n. into the console it is clearly visible on the list of properties|methods. 控制台上 ,可以在属性列表中清晰可见。

The problems start when I configure the same setup for the o variable: 当我为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__
)
/********************************************************/

The first thing I notice is that when I now type n. 我注意到的第一件事是当我现在键入n. or o. o. into the console the popup list of properties|methods no longer contains a reference to the len property, but if I type in the full extension n.len or o.len I get the desired result of 3 or 2 ... 控制台中,属性|方法的弹出列表不再包含对len属性的引用,但是如果我输入完整扩展名n.leno.len我将得到期望的结果32 ...

So I know the code is legit but I need the console popup as there is about 40 different properties & methods for each of the 7 foundation objects... 所以我知道代码合法,但是我需要控制台弹出窗口,因为7个基础对象中的每一个都有大约40种不同的属性和方法...

So I wrote a test block to try & identify the problem: 所以我写了一个测试块来尝试并找出问题所在:

/********************************************************/
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__
)
/********************************************************/

Immediately after expanding the .__proto__ in the console for o , n and now e , I noticed that all 3 had been given the dis property I had originally tried to assign to solely the o object. 控制台中将.__proto__扩展为on以及现在为e ,我立即注意到,这3个对象均已获得了最初尝试仅分配给o对象的dis属性。

Then I cracked it: Number.prototype itself is an object, ergo it inherits the dis property from the Object.prototype 然后我破解了它: Number.prototype本身是一个对象,因此,它继承了Object.prototypedis属性。

How can I append the dis property solely to the o object without it being inherited by n from Object.prototype ? 我如何才能将dis属性仅附加到o对象,而不能由nObject.prototype继承呢?

A subsection of this file is dedicated to customizing the prototypes of the foundation objects 该文件的一个小节专门用于自定义基础对象的原型

Oy vey. OY合租。 Not the greatest idea IMHO. 不是最伟大的主意恕我直言。 Especially modifying the Object prototype. 特别是修改Object原型。 Yeesh. esh

So I know the code is legit but I need the console popup as there is about 40 different properties & methods for each of the 7 foundation objects... 所以我知道代码合法,但是我需要控制台弹出窗口,因为7个基础对象中的每一个都有大约40种不同的属性和方法...

Why? 为什么? Are you doing your development in a browser console? 您是否正在浏览器控制台中进行开发?

Do you have the nous to show me how to append the dis property solely to the o object without it being inherited by n from Object.prototype? 您是否有向我展示如何将dis属性仅附加到o对象而不被n从Object.prototype继承的方法?

Ok... 好...

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

How's that? 怎么样?

Anything you add to the Object prototype is going to show up on pretty much everything (that's why it's a bad idea). 您添加到Object原型的所有内容都会显示在几乎所有内容上 (这就是为什么这是一个坏主意)。

Since o only inherits from Object , there's no way to define a property that would only show up on plain objects and not on everything else. 由于o 继承自Object ,因此无法定义仅显示在普通对象上而不显示在其他所有对象上的属性。 Your choices are to: 您的选择是:

  • Define the property directly on o , or 直接在o上定义属性,或
  • Instead of using a plain object for o , create o from your own custom type and put your property on the prototype of that custom type (much better than modifying the built-in types' prototypes). 不用对o使用普通对象,而是从您自己的自定义类型创建o并将属性放在该自定义类型的原型上(比修改内置类型的原型要好得多)。


Note: Of course, you could modify Number.prototype to have a dis property of undefined : 注意:当然,您可以将Number.prototype修改为具有undefineddis属性:

 Object.defineProperty(Number.prototype, 'dis', { value: void 0 }); console.log((9).dis); 

That would solve your problem as far as numbers go, but that dis property is still going to be on pretty much everything else in existence. 就数字而言,这将解决您的问题,但是dis财产仍然将存在于几乎所有其他事物上。

And please, for goodness' sake, use semicolons. 而且,出于善意,请使用分号。 Think of the children. 想想孩子们。

Check this out: 看一下这个:

/********************************************************
⇒   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...
/********************************************************/

Rundown: 撞倒:

  • Let's say for example we define a property on Object.prototype called len & set its value to 5 . 例如,假设我们在Object.prototype上定义了一个名为len的属性,并将其值设置为5
  • Now if we call {}.len , we get a result of 5 & if we call [].len or "".len or #.len etc, we get the same result due to inheritance from Object.prototype on instantiation. 现在,如果调用{}.len ,则得到5的结果;如果调用[].len"".len#.len等,则由于在实例化时从Object.prototype继承而得到相同的结果。
  • But let's say we then define a property on Array.prototype with the same name:- len & set its value to 50 . 但是,假设我们随后在Array.prototype上定义了一个具有相同名称的属性: len并将其值设置为50
  • Now if we call {}.len etc, we get the same result of 5, but if we call [].len we get 50, as the Array.prototype was created most recently and its definition of len overwrites Object.prototype 's version. 现在,如果我们调用{}.len等,我们得到的结果是5,但是如果我们调用[].len ,我们得到的结果是50,因为Array.prototype是最近创建的,并且其len定义覆盖了Object.prototype的版。

Solution: 解:

  • So if we define only 1 property to Object.prototype called for simplicity's sake _ , & set its value to a substructure object that contains the handlers specific to objects only. 因此,如果为简单起见_ ,仅为Object.prototype定义1个属性,并将其值设置为仅包含特定于对象的处理程序的子结构对象。
  • Then if we do the same for Array.prototype , but set the value of this _ property to another substructure that contains handlers specific to arrays only. 然后,如果对Array.prototype进行相同的操作,但是将此_属性的值设置为另一个仅包含特定于数组的处理程序的子结构。
  • Then as with the .len property in the rundown above Array.prototype 's version of _ overwrites Object.prototype 's version ergo we have 2 completely individual _ properties with no miscellaneous inheritances. 然后,与Array.prototype_版本上方的.len中的.len属性覆盖Object.prototype的版本ergo一样,我们拥有2个完全独立的_属性,没有其他继承。

Drawbacks: 缺点:

  • Can no longer access the properties the easy way {}.len , it now has to be prefixed {}._.len . 无法再以简单的方式{}.len访问属性,现在必须将其前缀为{}._.len

Benefits: 好处:

  • When defining properties on Object.prototype the whole task can become a paradoxical nightmare, where even errors thrown to the console inherit the properties, and if you've added 100 new properties|methods to Object.prototype then each is visible when you expand any error in the console! Object.prototype上定义属性时,整个任务可能会成为一个矛盾的噩梦,即使向控制台抛出的错误也会继承该属性,并且如果您向Object.prototype添加了100个新属性|方法,则在展开任何属性时它们都是可见的控制台错误!
  • This method ensures that only 1 property is ever visible _ , and that property is customizable to the type of owner object. 此方法确保_只能显示1个属性,并且该属性可根据所有者对象的类型进行自定义。

Expansion: 扩张:

  • I'm looking into modifying this code to accommodate the varying objects that do NOT conform to this standard, like maybe a handler for: 我正在研究修改此代码,以适应符合该标准的各种对象,例如:
x=document.getElementsByTagName('td')
y=x._.len

Like: 喜欢:

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}}
            )
        }
}

So x._.len would be available to any list of objects but not say {a:1} as this has a constructor.name of object not HTMLCollection . 因此x._.len将可用于任何对象列表,但不必说{a:1}因为它具有objectconstructor.name而不是HTMLCollection

This is a pet project. 这是一个宠物项目。 It's only in its own prototype phase and I'm looking for ideas on how to expand this concept, from those with experience on the topic, before I either go back to the old ways or break through this stigma surrounding prototype modification and come up with a new more efficient way! 它只是在自己的原型阶段,我正在寻找具有该主题经验的人如何扩展此概念的想法,然后再回到旧方法或突破围绕原型修改的污名并提出一种新的更有效的方法!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM