所需模式:创建返回可执行函数并继承自原型的新对象

发布于 2024-11-05 08:33:29 字数 1873 浏览 0 评论 0原文

场景 1 - 一切正常:

var AwesomeObject = function()
{
   var self = this;
   self.whatstuff = 'really awesome';
}

AwesomeObject.prototype.doStuff = function()
{
   var self = this;
   console.log('i did '+self.whatstuff+' stuff');
   return self;
}

var awesome = new AwesomeObject(); //returns a new AwesomeObject
awesome.doStuff(); // prints 'i did really awesome stuff' on the console

现在我希望它更棒:

var AwesomeObject = function()
{  
   var f = function() { console.log('i am awesome'); }
   var self = f;
   self.whatstuff = 'really awesome';
   return self;
}

AwesomeObject.prototype.doStuff = function()
{
   var self = this;
   console.log('i did '+self.whatstuff+' stuff');
   return self;
}

var awesome = new AwesomeObject(); //returns the interal f object
awesome(); // prints 'i am awesome'
awesome.doStuff(); // throws an error

新的 AwesomeObject 应该返回一个可执行函数本身,这样我就可以说“awesome();”

但我希望它也继承 AwesomeObject.prototype

添加 self.prototype = AwesomeObject.prototype; 没有帮助。

var AwesomeObject = function()
{  
   var f = function() { console.log('i am awesome'); }
   var self = f;
   self.whatstuff = 'really awesome';
   self.prototype =  AwesomeObject.prototype;
   return self;
}

好吧,我可以将 AwesomeObject.prototype 函数一个接一个地复制到 f 的范围内,

var AwesomeObject = function()
{  
   var f = function() { console.log('i am awesome'); }
   var self = f;
   self.whatstuff = 'really awesome';
   self.doStuff =  function() { AwesomeObject.prototype.doStuff.apply(self,arguments); }
   return self;
}

但我认为必须有一种更好的方法,更好的模式,什么是它?

这个问题让我发疯,非常感谢您的帮助。

一般来说:如何创建一个

  • 可以用new创建的
  • 函数对象返回一个可以执行的函数对象
  • 继承给定原型的所有属性和方法

有办法吗?

谢谢 弗朗兹

Scenario 1 - everything works:

var AwesomeObject = function()
{
   var self = this;
   self.whatstuff = 'really awesome';
}

AwesomeObject.prototype.doStuff = function()
{
   var self = this;
   console.log('i did '+self.whatstuff+' stuff');
   return self;
}

var awesome = new AwesomeObject(); //returns a new AwesomeObject
awesome.doStuff(); // prints 'i did really awesome stuff' on the console

Now i want it even awesomer:

var AwesomeObject = function()
{  
   var f = function() { console.log('i am awesome'); }
   var self = f;
   self.whatstuff = 'really awesome';
   return self;
}

AwesomeObject.prototype.doStuff = function()
{
   var self = this;
   console.log('i did '+self.whatstuff+' stuff');
   return self;
}

var awesome = new AwesomeObject(); //returns the interal f object
awesome(); // prints 'i am awesome'
awesome.doStuff(); // throws an error

new AwesomeObject should return an executable function itself, so that i can say 'awesome();'

but i want it to inherit the AwesomeObject.prototype, too.

adding self.prototype = AwesomeObject.prototype; does not help.

var AwesomeObject = function()
{  
   var f = function() { console.log('i am awesome'); }
   var self = f;
   self.whatstuff = 'really awesome';
   self.prototype =  AwesomeObject.prototype;
   return self;
}

ok i can copy the AwesomeObject.prototype functions - one after the other - into the scope of f

var AwesomeObject = function()
{  
   var f = function() { console.log('i am awesome'); }
   var self = f;
   self.whatstuff = 'really awesome';
   self.doStuff =  function() { AwesomeObject.prototype.doStuff.apply(self,arguments); }
   return self;
}

but i think there must be a better way, a better pattern, what is it?

this issue drives me crazy, help would be really appreciated.

in general: how to create a function object that

  • can be created with new
  • returns a function object that can be executed
  • inherits all properties and methods of a given prototype

?

is there a way?

thx
Franz

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

七七 2024-11-12 08:33:29

一个非常简单的模式就是工厂。

var AwesomeObject = (function() {
    var AwesomeObject = function() {
        this.whatstuff = 'really awesome';
    };

    AwesomeObject.prototype.doStuff = function() {
        console.log('i did ' + this.whatstuff + ' stuff');
        return this;
    };

    return function() {
        var o = new AwesomeObject();
        var f = function() { console.log("I am awesome"); };
        for (var k in o) {
            f[k] = o[k];    
        }

        return f;
    };

})();

var foo = AwesomeObject();
foo();
foo.doStuff();

实例

这个想法是将函数和对象分成两部分。您的对象存在于函数的本地范围内,并且该函数可以使用该对象。

对象本身完全通过原型继承。

关键是将对象的所有属性/方法转发到函数上。

这是最干净的解决方案。

A very simple pattern is a factory.

var AwesomeObject = (function() {
    var AwesomeObject = function() {
        this.whatstuff = 'really awesome';
    };

    AwesomeObject.prototype.doStuff = function() {
        console.log('i did ' + this.whatstuff + ' stuff');
        return this;
    };

    return function() {
        var o = new AwesomeObject();
        var f = function() { console.log("I am awesome"); };
        for (var k in o) {
            f[k] = o[k];    
        }

        return f;
    };

})();

var foo = AwesomeObject();
foo();
foo.doStuff();

Live Example.

The idea is that you seperate your function and your object into two things. Your object exists in the local scope of your function and the function can use the object.

The object itself inherits completely through the prototype.

The key is do forward all properties/methods of the object onto the function.

This is the cleanest solution.

下雨或天晴 2024-11-12 08:33:29

正如您可能知道的那样,当解析属性时,将遍历原型链。
但是,如果您有一个对象 awesome 并尝试评估 awesome.doStuff,则永远不会查询 awesome.prototype 的属性。您可以在示例中验证这一点,"doStuff" in Awesome =>; false 但是 awesome.prototype => 中的“doStuff”正确。

因此,您所做的并不是更改 awesome 的隐式属性,而是更改其原型,这意味着通过执行 new Awesome 创建的任何对象都将具有该属性。验证:new Awesome() => 中的“doStuff”正确。这是有道理的,因为使用 f/awesome 时无法区分构造函数或常规函数。

解析对象o上的属性p的过程大致如下:

  • 检查o上是否定义了p >
  • 检查 p 是否在 o.__proto__ 上定义(__proto__ 的使用是非标准的,但广泛实现,除了我上次检查的 jscript现在已在 SpiderMonkey 中弃用)
  • 检查 p 是否在 o.constructor.prototype 上定义
  • 检查 p 是否在 上定义o.constructor.prototype.prototype

因此,一种解决方案是简单地设置 o.__proto__ = AwesomeClass.prototype 。将 __proto__ 视为对象与其原型之间的隐藏中间对象。每个实例都会接收自己唯一的 __proto__ 对象。但正如我所说,这已被弃用且非标准。

我们还可以在 Function.prototype 中设置值,但这会覆盖其他 Function 属性并影响所有 Function 实例。我们不希望这样。

那么还剩下什么呢?事实证明并不多。无法在保留对象继承原型的同时设置对象的完整原型。您将需要迭代原型并复制所有属性。幸运的是,这将允许 instanceof 在使用构造函数链时按预期运行,并允许正确继承/重写属性。

问题实际上是没有内置方法可以将一个对象的属性复制到另一个对象中,并且没有标准方法可以临时更改对象的原型链(__proto__)。

因此,请使用 __proto__ ,或迭代原型。

When a property is resolved the prototype chain is traversed as you probably know.
But if you have an object awesome and try to evaluate awesome.doStuff, then awesome.prototype will never be queried for the property. You can verify this in your example, "doStuff" in awesome => false but "doStuff" in awesome.prototype => true.

So what you're doing is not changing the implicit properties of awesome, you are changing its prototype, meaning any objects created by doing new awesome will have that property. Verification: "doStuff" in new awesome() => true. And this makes sense, since there is no way to distinguish between a constructor or a regular function when using f/awesome.

The procedure when resolving a property p on an object o is roughly as follows:

  • Check whether p is defined on o
  • Check whether p is defined on o.__proto__ (usage of __proto__ is non-standard but widely implemented, except for jscript last time i checked and it has now been deprecated in SpiderMonkey)
  • Check whether p is defined on o.constructor.prototype
  • Check whether p is defined on o.constructor.prototype.prototype
  • etc

So one solution would be to simply set o.__proto__ = AwesomeClass.prototype. Think of __proto__ as a hidden intermediary object between an object and its prototype. Each instance receives its own unique __proto__ object. But this is deprecated and non-standard like I said.

We could also set the values in Function.prototype but that would override other Function properties and affect all Function instances. We don't want that.

So what's left? Not much it turns out. There is no way to set the complete prototype of an object while retaining it's inherited prototype. You will need to iterate through your prototype and copy all properties. Fortunately this will allow instanceof to behave as expected when working with chains of constructors, as well as allowing inheritance/overriding of properties properly.

The problem is really that there is no built-in way to copy the properties of an object into another one, and that there is no standard way to change an object's prototype chain ad-hoc (__proto__).

So use __proto__, or iterate through the prototype.

星星的轨迹 2024-11-12 08:33:29

我认为没有一个好的方法可以做到这一点。我会重新设计你的程序来避免它。

然而,这是一个糟糕依赖于平台的解决方案(使用非标准__proto__属性在V8上工作):

var PrototypeToBeInherited = {'inheritedProperty': 'inheritedPropertyValue'};

f = function() {
  return "result";
};
f.__proto__ = PrototypeToBeInherited;

f()
 => "result";
f.inheritedProperty
 => "inheritedPropertyValue"

根据您的要求,它必须使用“new”创建,只需将其包装在函数中:

F = function() {
    return f;
}
var instance = new F();

I don't think there is a good way to do this. I would redesign your program to avoid it.

However, here is a bad, platform-dependent solution (works on V8 using non-standard __proto__ property):

var PrototypeToBeInherited = {'inheritedProperty': 'inheritedPropertyValue'};

f = function() {
  return "result";
};
f.__proto__ = PrototypeToBeInherited;

f()
 => "result";
f.inheritedProperty
 => "inheritedPropertyValue"

For your requirement that it must be created with "new", just wrap it in function:

F = function() {
    return f;
}
var instance = new F();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文