Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
383 views
in Technique[技术] by (71.8m points)

javascript - 将.apply()与'new'运算符配合使用。 这可能吗?(Use of .apply() with 'new' operator. Is this possible?)

In JavaScript, I want to create an object instance (via the new operator), but pass an arbitrary number of arguments to the constructor.(在JavaScript中,我想创建一个对象实例(通过new运算符),但是将任意数量的参数传递给构造函数。)

Is this possible?(这可能吗?) What I want to do is something like this (but the code below does not work):(我想做的是这样的(但是下面的代码不起作用):) function Something(){ // init stuff } function createSomething(){ return new Something.apply(null, arguments); } var s = createSomething(a,b,c); // 's' is an instance of Something The Answer(答案) From the responses here, it became clear that there's no built-in way to call .apply() with the new operator.(从这里的响应中可以明显看出,没有使用new运算符调用.apply()内置方法。) However, people suggested a number of really interesting solutions to the problem.(但是,人们提出了一些非常有趣的解决方案。) My preferred solution was this one from Matthew Crumley (I've modified it to pass the arguments property):(我更喜欢的解决方案是Matthew Crumley的解决方案(我已对其进行了修改以传递arguments属性):) var createSomething = (function() { function F(args) { return Something.apply(this, args); } F.prototype = Something.prototype; return function() { return new F(arguments); } })();   ask by Premasagar translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

With ECMAScript5's Function.prototype.bind things get pretty clean:(使用ECMAScript5的Function.prototype.bind一切变得很干净:)

function newCall(Cls) { return new (Function.prototype.bind.apply(Cls, arguments)); // or even // return new (Cls.bind.apply(Cls, arguments)); // if you know that Cls.bind has not been overwritten } It can be used as follows:(可以如下使用:) var s = newCall(Something, a, b, c); or even directly:(甚至直接:) var s = new (Function.prototype.bind.call(Something, null, a, b, c)); var s = new (Function.prototype.bind.apply(Something, [null, a, b, c])); This and the eval-based solution are the only ones that always work, even with special constructors like Date :(即使基于Date特殊构造方法,此方法和基于eval的解决方案仍然是唯一可以正常使用的解决方案。) var date = newCall(Date, 2012, 1); console.log(date instanceof Date); // true edit(编辑) A bit of explanation: We need to run new on a function that takes a limited number of arguments.(一点解释:我们需要在带有有限数量参数的函数上运行new 。) The bind method allows us to do it like so:(bind方法允许我们这样做:) var f = Cls.bind(anything, arg1, arg2, ...); result = new f(); The anything parameter doesn't matter much, since the new keyword resets f 's context.(anything参数无关紧要,因为new关键字会重置f的上下文。) However, it is required for syntactical reasons.(但是,出于语法原因,它是必需的。) Now, for the bind call: We need to pass a variable number of arguments, so this does the trick:(现在,对于bind调用:我们需要传递可变数量的参数,所以就可以了:) var f = Cls.bind.apply(Cls, [anything, arg1, arg2, ...]); result = new f(); Let's wrap that in a function.(让我们将其包装在一个函数中。) Cls is passed as arugment 0, so it's gonna be our anything .(Cls作为arugment 0传递,所以它将成为我们的anything 。) function newCall(Cls /*, arg1, arg2, ... */) { var f = Cls.bind.apply(Cls, arguments); return new f(); } Actually, the temporary f variable is not needed at all:(实际上,根本不需要临时f变量:) function newCall(Cls /*, arg1, arg2, ... */) { return new (Cls.bind.apply(Cls, arguments))(); } Finally, we should make sure that bind is really what we need.(最后,我们应该确保bind确实是我们所需要的。) ( Cls.bind may have been overwritten).(( Cls.bind可能已被覆盖)。) So replace it by Function.prototype.bind , and we get the final result as above.(因此,将其替换为Function.prototype.bind ,我们得到如上的最终结果。)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...