是否可以在原型的对象中嵌套函数并访问基础对象? 更新:我无法回答这个问题,因为它已被锁定,但我在底部有自己的解决方案,与 Jonas' answer有没有办法让 this 或任何变量返回对基础对象的引用? document.body 在这种情况下?

问题描述

更新:我无法回答这个问题,因为它已被锁定,但我在底部有自己的解决方案,与 Jonas' answer

合作

假设我在原型中添加了这个。我将使用 HTMLElement 作为示例。

HTMLElement.prototype.MyNamespaceGetThis = function() {
  return this;
}

document.body.MyNamespaceGetThis() 将返回 document.body

但是如果我想把它嵌套在一个对象中

HTMLElement.prototype.MyNamespace = {};
HTMLElement.prototype.MyNamespace.GetThis = function() {
  return this;
}

document.body.MyNameSpace.GetThis() 将返回 document.bodyMyNameSpace ({GetThis: ƒ})

有没有办法让 this 或任何变量返回对基础对象的引用? document.body 在这种情况下?

我尝试了一些变体,例如

HTMLElement.prototype.MyNameSpace = (function() {
  let that = this
  let obj = Object.defineProperties({},{GetThis: {
    value: function() {
      console.log(that)
    },enumerable: false}})

  return obj;
})()

但是由于完全可以理解的原因,这失败了。该函数仅运行一次并返回对 window

的引用

我已经用 .bind() 尝试了一些实验,但出于可预见的原因,没有一个能返回想要的结果。


我的解决方

我不喜欢 Jonas 的回答的是,它与 MyNamespace().method 基本相同,其中 MyNamespace 返回一组方法

持久化成员也是不可能的。如果我想存储成员数据,我需要一个单独的对象来做这件事,但我不喜欢那样。

我的解决方案是使用 class,然后以一种特殊的内存轻量方式调用它。

class MyNamespace {
  constructor(parent) {
    this.parent = parent;
  }

  GetThis() {
    return this.parent;
  }
}

然后,对于这个例子,你像这样将它添加到 HTMLElement 原型

Object.defineProperties(HTMLElement.prototype,{
    MyNamespace: {
      enumerable: false,writeable: true,get: function() {
        let ret = new MyNamespace(this);
        Object.defineProperty(this,'MyNamespace',{
          enumerable: false,writeable: false,// note about this
          value: ret
        });
        return ret;
      },enumerable: false,writeable: false
    },})

第一次调用 document.body.MyNamespace.GetThis() 将返回类 MyNamespace一个新实例,然后从中调用 GetThis()。它还将更改 document.bodyMyNamespace 以直接引用创建的实例,而不是每次都创建一个新实例。这意味着持久数据。

我喜欢的其他一点是,每个元素都不会携带完整的 MyNamespace 实例,除非它在文档的生命周期中被调用

更新引用后,我将其设置为冻结,以免被覆盖,但很容易想象人们可能需要 destroy 方法的位置。您可以将 writable 更改为 true 之类的。

class MyNamespace {
  constructor(parent) {
    this.parent = parent;
  }

  GetThis() {
    return this.parent;
  }

  destroy() {
    Object.defineProperties(HTMLElement.prototype,{
        MyNamespace: {
          enumerable: false,get: MyNamespace.factory(this,true),writeable: false
        },})
  }

  renew() {
    this.parent.MyNamespace = MyNamespace.factory(this.parent,true)
    // HTMLElement.prototype.MyNamespace can also be set
    // to MyNamespace.factory(this)
  }

  static factory(parent,writeable) {
    return Object.defineProperty(parent,{
      enumerable: false,writeable: writeable,value: new MyNamespace(parent)
    }).MyNamespace;
  }
}

解决方法

MyNamespace 转换为 getter 并存储对父级的引用:

function Namespace(parent) {
   return {
     parent,/* Your functions here */
   };
 }

Object.defineProperty(HTMLElement.prototype,"namespace",{
  get() { return Namespace(this); },});

console.log( 
  document.body.namespace.parent === document.body // true
);