Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/457.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 所需模式:创建新对象,该对象返回可执行函数并从原型继承_Javascript_Node.js - Fatal编程技术网

Javascript 所需模式:创建新对象,该对象返回可执行函数并从原型继承

Javascript 所需模式:创建新对象,该对象返回可执行函数并从原型继承,javascript,node.js,Javascript,Node.js,场景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 awesom

场景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
新的awesome对象本身应该返回一个可执行函数,这样我就可以说“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;
}
但我认为一定有更好的方式,更好的模式,这是什么

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

概述:如何创建一个函数对象

  • 可以使用新的
  • 返回可以执行的函数对象
  • 继承给定原型的所有属性和方法
?

有办法吗

thx
弗兰兹

我认为没有好办法。我会重新设计你的程序来避免它

但是,这里有一个糟糕的依赖于平台的解决方案(在V8上使用非标准的
\uuuu proto\uuu
属性):

对于必须使用“new”创建的需求,只需将其包装在函数中:

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

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

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

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

  • 检查是否在
    o
  • 检查
    p
    是否定义在
    o.\uuuuu proto\uuuuuuu
    (使用
    \uuuuuuuu proto\uuuuuuuu
    是非标准的,但得到了广泛的实现,除了我上次检查的jscript之外,它现在已在SpiderMonkey中被弃用)
  • 检查是否在
    o.constructor.prototype上定义了
    p
  • 检查
    o.constructor.prototype.prototype上是否定义了
    p
因此,一个解决方案是简单地设置
o.。\uuuuu proto\uuuuu=AwesomeClass.prototype
。将
\uuuu proto\uuu
视为对象与其原型之间隐藏的中间对象。每个实例都接收自己唯一的
\uuuuuuuuuuuuu
对象。但正如我所说,这是不推荐的和非标准的

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

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

问题是,实际上没有内置的方法将对象的属性复制到另一个对象中,也没有标准的方法来临时更改对象的原型链(
\uuuuuu proto\uuu


因此,请使用
\uuuuu proto\uuuuu
,或者迭代原型

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

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();

这个想法是你把你的功能和你的对象分成两部分。对象存在于函数的本地范围内,函数可以使用该对象

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

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


这是最干净的解决方案。

我认为只需从原型复制您需要的功能即可。您不需要使用apply();doStuff=prototype。doStuff支持
。\uuuu proto\uuuu
应该避免,因为平台依赖,动态更改对象的内部原型会导致噩梦代码。thx很多,它帮助ged摆脱了我在proto中的讨论中我在思想上的结。我现在知道了proto,现在我会尽量避免使用proto,因为其他答案也是正确的。这似乎是最干净的模式(它的工作原理与承诺的一样)。thx很多。请注意,此解决方案不会返回从自定义原型继承的对象,而是返回一个混合了某些属性的
函数
对象。
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();