[英]Factory functions prototype
Learning constructors I came with this question:学习构造函数我提出了这个问题:
Why not to use just normal functions returning an object instead of constructors?
为什么不使用返回 object 而不是构造函数的普通函数?
Reading a bit, I found about factory functions (ff).读了一下,我发现了工厂函数(ff)。 The differences with constructors are:
与构造函数的区别是:
this
that replaces the object literal { }
,this
替换 object 文字{ }
,new
replacing the return
of the object.new
return
的object。 But that's not enough simplification I believe, it's just a bit tidier, but not much.但我相信这还不够简化,它只是有点整洁,但不多。
Take this example:举个例子:
function box(x,y,z){
return {
x:x , y:y , z:z ,
volume: function (){return x*y*z}
}
}
We can easily write a constructor with same function.我们可以很容易地编写一个具有相同 function 的构造函数。
Now, I know one of the differences might be the prototype.现在,我知道其中一个差异可能是原型。 So here is my question:
所以这是我的问题:
The prototype object that is created together with the function is indeed making the difference.与 function 一起创建的原型 object 确实有所作为。 When you call the function with
new
, the this
object will get that prototype object as its prototype.当您使用
new
调用 function 时, this
object 将得到该原型 object 作为其原型。 So the prototype chain for that new object is one step longer than what you get with the factory function.因此,新 object 的原型链比工厂 function 的原型链长了一步。
The language offers the instanceof
operator and the constructor
property, which are useful when you use constructors, as they give information about the instance's constructor.该语言提供了
instanceof
运算符和constructor
属性,这在您使用构造函数时很有用,因为它们提供了有关实例构造函数的信息。 In the case of an object literal (as used in your box
function), that determines that the constructor is Object
and not box
.对于 object 文字(在您的
box
函数中使用),它确定构造函数是Object
而不是box
。
To bring the two versions of the functions a bit closer together, so that only the essential differences are highlighted, you could write them as follows:为了使两个版本的函数更接近一点,以便仅突出显示本质上的区别,您可以将它们编写如下:
function box(x,y,z) {
let obj = {};
obj.x = x;
obj.y = y;
obj.z = z;
// Better reference the properties here, ...in case they are changed:
obj.volume = function () { return obj.x * obj.y * obj.z }
return obj;
}
The constructor could look like this:构造函数可能如下所示:
function Box(x,y,z) {
// `this` is already initialised as a new object with a specific prototype
this.x = x;
this.y = y;
this.z = z;
this.volume = function () { return this.x * this.y * this.z }
// `this` is returned by default, so no `return` is needed
}
Notice the difference in the prototype chains (run the snippet) and the usefulness of instanceof
:注意原型链(运行代码片段)和
instanceof
的用处的区别:
function box(x,y,z) { let obj = {}; obj.x = x; obj.y = y; obj.z = z; obj.volume = function () { return obj.x * obj.y * obj.z } return obj; } function Box(x,y,z) { this.x = x; this.y = y; this.z = z; this.volume = function () { return this.x * this.y * this.z } } let a = box(1,2,3); let b = new Box(1,2,3); // Print prototype chains console.log("a-->" + Object.getPrototypeOf(a).constructor.name); let protB = Object.getPrototypeOf(b); console.log("b-->" + protB.constructor.name + "-->" + Object.getPrototypeOf(protB).constructor.name); // Print use of `instanceOf` console.log("a instanceof box?", a instanceof box); console.log("b instanceof Box?", b instanceof Box);
So far I ignored the fact that the volume
function could be reused instead of defined separately for each instance.到目前为止,我忽略了一个事实,即
volume
function 可以重复使用,而不是为每个实例单独定义。 You can in both cases define the volume
function as a (more) global function.在这两种情况下,您都可以将
volume
function 定义为(更多)全局 function。 Note that you now could use the this
keyword, since normally you would call volume
as instance.volume()
:请注意,您现在可以使用
this
关键字,因为通常您会将volume
称为instance.volume()
:
function volume { return this.x * this.y * this.z }
function box(x,y,z) {
let obj = {};
obj.x = x;
obj.y = y;
obj.z = z;
obj.volume = volume;
return obj;
}
Still, you have the explicit obj.volume = volume
assignment.尽管如此,您仍然有明确的
obj.volume = volume
分配。 In the constructor pattern, you don't need to create that instance property.在构造函数模式中,您不需要创建该实例属性。 It is enough the define the method on the prototype object:
在原型 object 上定义方法就足够了:
function Box(x,y,z) {
this.x = x;
this.y = y;
this.z = z;
// No need here to define `volume`
}
Box.prototype.volume = function { return this.x * this.y * this.z };
So, actually you only have one reference to the method.所以,实际上你只有一个对该方法的引用。
Finally, there is the class
syntax, which is an alternative to use constructors:最后,还有
class
语法,这是使用构造函数的替代方法:
class Box(x,y,z) {
constructor(x,y,z) {
this.x = x;
this.y = y;
this.z = z;
}
volume() {
return this.x * this.y * this.z;
}
}
In this syntax volume
is also defined on the prototype, not on the instance.在这个语法中,
volume
也是在原型上定义的,而不是在实例上。
So far, the comparison was favourable to using constructors (in my opinion).到目前为止,比较有利于使用构造函数(在我看来)。
But:但:
this
object can be avoided completely by using factory functions.this
object。 Using this
can be confusing (as the many questions on that topic on Stack Overflow demonstrate).this
可能会令人困惑(正如 Stack Overflow 上关于该主题的许多问题所展示的那样)。 Some coders feel this is good reason to abandon constructors.Being
from which Animal
is derived, from which Mammal
is derived, from which...etc, etc, can get confusing.Animal
的Being
,从哪个Mammal
派生,从哪个...等等等等,可能会让人感到困惑。 A flat data structure can then feel like a relief.YES, Prototype is a difference between the so called factory functions and constructors.是的,原型是所谓的工厂函数和构造函数之间的区别。
In the sample code that you had given, you won't be able to access the prototype of box
, even if that is added.在您提供的示例代码中,您将无法访问
box
的原型,即使添加了该原型也是如此。 When you call a function with new
keyword, the first job that it would do internally is to create an object and create its prototype chain based on the references that you given via box.prototype
and after setting that up the process will return the object created.当您使用
new
关键字调用 function 时,它在内部执行的第一项工作是创建 object 并根据您通过box.prototype
提供的引用创建其原型链,并且在设置完该过程后,该过程将返回 ZA8CFDE6331BD59EB66ZC94 . But here in your code, the access has been restricted to the object that you are returning and it will override the return of the originally created object.但在您的代码中,访问权限仅限于您返回的 object,它将覆盖最初创建的 object 的返回。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.