我读过关于使用很好的问题和apply
来动态创建对象的文章。
确切的问题是:
我希望创建一个对象实例(通过新操作符),但是将任意数量的参数传递给构造函数。这有可能吗
关于已选择的答案,我有一个问题:
/*1*/ function construct(constructor, args) {
/*2*/ function F() {
/*3*/ return constructor.apply(this, args);
/*4*/ }
/*5*/ F.prototype = constructor.prototype;
/*6*/ return new F();
/*7*/ }
(工作jsbin)
一切都好。
但
我尝试将第3行移到第6行:所以最后的输出是:
/*1*/ function construct(constructor, args) {
/*2*/ // function F() {
/*3*/ // return constructor.apply(this, args);
/*4*/ // }
/*5*/ //F.prototype = constructor.prototype;
/*6*/ return new constructor.apply(this, args);
/*7*/ }
我的问题是为什么第二个例子行不通?有什么区别吗?
我所做的就是把代码从一个地方移到另一个地方。
示例:
function calc()
{
function a() {return 4};
return a(); // I could easily do `return 4` instead...;
}
问题
为什么移动的代码不能工作?
发布于 2014-03-15 11:11:17
你说:
function construct(constructor, args) {
function F() {
return constructor.apply(this, args);
}
F.prototype = constructor.prototype;
return new F();
}
应与下列事项相同:
function construct(constructor, args) {
return new constructor.apply(this, args);
}
但它实际上在以下几个基本方面有所不同:
1. constructor.apply
是一个本机非构造函数.New
只能从构造函数创建对象:
..。对象可以被创建..。通过构造函数创建对象,然后通过为其属性分配初始值来执行初始化全部或部分对象的代码。每个构造函数都有一个名为“prototype”的属性,用于实现基于原型的继承和共享属性。对象是通过在新表达式中使用构造函数创建的.
http://www.ecma-international.org/ecma-262/5.1/#sec-4.2.1
另一方面,F
是一个功能对象。所有函数对象都可以用作构造函数。
注意: Alon说new constructor.apply(this, args)
不能工作,因为constructor.apply(this, args).prototype
没有定义。这不是真的。如果是这样,将意味着函数调用操作符的优先级高于新运算符(即‘newconstructor.apply(this,args)与new (constructor.apply(this,args))’) 这不是真的。
2.,即使constructor.apply
是构造函数,它也不同于constructor.prototype
。F
的原型设置为constructor's
原型,以确保通过新操作符与F
组合创建的所有对象与与constructor
组合创建的对象相同。F
和constructor
的唯一不同之处在于它们是不同的函数,从而使得F
能够以更灵活的方式调用constructor
。
constructor.apply.prototype
实际上可以设置为constructor.prototype
,但constructor.apply
仍然不能用作构造函数。
3.语句中的this
参数不是指向新创建的对象,而是指向本地作用域中的this
。因此,即使您可以使用apply
函数作为构造函数,并将apply's
原型设置为constructor's
原型,您仍然会将错误的this
传递给constructor
函数。
注:示例中的
function calc()
{
function a() {return 4};
return a(); // I could easily do `return 4` instead...;
}
return
可以与任何类型的表达式一起使用,而new
不能。
发布于 2014-03-15 09:02:28
你还得告诉它才能使用父原型。
此外,将其指定为使用扩展构造函数也是一个好主意。
在功能之外,
construct.prototype = Object.create(constructor.prototype);
construct.prototype.constructor = construct;
编辑:
在第二个函数中,您试图创建一个已经实例化的对象的新实例。
应该用new调用构造函数。
发布于 2014-03-15 09:12:44
执行代码new foo(...)
时,将创建一个新对象,从foo.prototype
继承。
你想做的事:
return new constructor.apply(this, args);
..。不工作,因为constructor.apply(this, args).prototype
是undefined
。
原始construct
函数仍然工作的原因是:
F.prototype = constructor.prototype;
因为当你做return new F();
时,F仍然有一个原型。
https://stackoverflow.com/questions/22426816
复制