this.constructor.prototype -- 不能完全覆盖,但可以写出单个道具吗?



tl; dr? 为什么我不能从构造函数中覆盖构造函数的原型?

我正在找出我的原型继承模式。我不喜欢通常如何从构造函数的外部定义原型,并且希望在逻辑上更好地封装事物。

我发现我期望工作的一条魔法线无效。

function Orifice(){
  this.exhaust=function(){};
  this.ingest=function(){};
}
var standardOrifice = new Orifice();
function Sphincter(){
  this.constructor.prototype = standardOrifice; // <-- does not work
  this.relax=function(){};
  this.tighten=function(){};
}

有趣的是,我可以将单个属性写入 this.constructor.prototype,但是我不能像在构造函数的定义之外一样覆盖整个原型对象。

这样的东西可行:

  this.constructor.prototype.exhaust = standardOrifice.exhaust;
  this.constructor.prototype.ingest = standardOrifice.ingest;

i可以创建一个简单的克隆函数来处理这一点:

function extend(target){
  return {
    from: function(obj){
      target.__proto__ = obj.constructor.prototype;
      for (key in obj) if (obj.hasOwnProperty(key)) target[key]=obj[key];
      return target;
    }
  };
}

值得庆幸的是,到目前为止,在我的测试中,这项技术看起来工作良好,尽管我不确定是否有细节或性能案例,我可能会缺少。

function Sphincter(){
  extend(this.constructor.prototype).from(standardOrifice);
  //...
}

为什么我不能从构造函数中覆盖构造函数的原型?并从构造函数中单独工作?

单独工作

为什么我不能从构造函数中覆盖构造函数的原型?

您可以,但是为时已晚。新实例已经从旧原型继承生成。也许阅读new的工作原理。

我不喜欢通常如何从构造函数的外部定义原型。

就是这样。您确实不应该从构造函数内部设置原型 - 每次创建新实例时都会执行。这是不应该应该的原型。另请参见分配原型方法 *内部 *构造函数函数 - 为什么不呢?

想要更好地封装事物。

您可能想看看各种(揭示)模块模式。甚至在某些Class框架中。

我目前正在寻找更多的具体原因,我不应该介绍我一直呈现的模式。

它在Internet Explorer中不起作用。它在不支持__proto__属性的任何符合ES5的环境中都无法使用。您永远不要使用它在现有对象上设置原型。相反,将Object.create(或其垫片)用于正确的JavaScript继承 - 它要求您覆盖构造函数外部的原型。

我的建议是在构造函数之外打电话给您的extend助手,它仍然具有不错的语法。

回答特定问题

为什么我不能从构造函数中覆盖构造函数的原型?

这是因为构造函数实际上被称为您的对象已经实例化。而且,由于您的对象已经在构造函数触摸任何内容之前就设法实例化,因此您的构造函数也已被分配为"默认"原型。

将属性添加到this.constructor.prototype似乎有效 - 因为您实际上正在操纵构造函数的预分配的默认原型对象,所有实例都从中继承了。

在我的示例中, this.constructor.prototype最终指的是构造函数的默认分配原型:因此,从那一刻开始,这意味着所有新实例都将具有新的原型 - 正如Bergi所说 - 正如Bergi所说,"太晚" - 您当前的实例将没有新的原型,因为它仍然具有旧的默认分配原型,因为它已经实例化。

避免胡说八道的更好模式

我已经明白了,我的问题中提出的技术根本不会做。问题本身通常被误导。通过将Bergi的智慧与我自己的个人偏见相结合,我想出了这种模式,以避免完全找到原始问题的答案:

function extend(p){
  return { to: function(C){ for (k in p) if (p.hasOwnProperty(k)) 
  C.prototype[k]=p[k]; return C; } };
};
var orifice = new function Orifice(){
  this.exhaust=function(){};
  this.ingest=function(){};
};
var Sphincter = extend(orifice).to(function Sphincter(){
  this.relax=function(){};
  this.tighten=function(){};
});


这是扩展功能,扩展了:

function extend(parentObject){
  return { 
    to: function(ChildConstructor){
      for (key in parentObject) 
        if (parentObject.hasOwnProperty(key)) 
          ChildConstructor.prototype[key] = parentObject[key];
      return ChildConstructor;
    }
  };
};

我用它来测试它有效:

// TESTING
var s=new Sphincter();
var tests=['relax','tighten','exhaust','ingest'];
for (var i in tests) console.log("s."+tests[i]+"() is "+(tests[i]in s?"present :)":"MISSING!"));

相关内容

最新更新