如果构造函数及其原型是在同一模块中定义的,比如AMD模块,是否可以使类私有字段全局化,以便在原型中可以访问模块,而不是在构造函数中使用下划线定义它们?
这样做更好:
define(function (require) {
"use strict";
var steps = 0;
function Constructor(_steps) {
steps = _steps;
}
Constructor.prototype.go = function () {
steps += 1;
};
然后这个:
define(function (require) {
"use strict";
function Constructor(_steps) {
this._steps = _steps;
}
Constructor.prototype.go = function () {
this._steps += 1;
};
答案 0 :(得分:2)
两种不同的解决方案。一个不一定比另一个“更好”,它们只是有不同的用例。
如果您正在使用构造函数/原型模式,那么在面向对象的意义上,在实例本身上设置构造函数参数是有意义的(使用this.<whatever-prop>
)。当您决定仅为了其副作用而使用构造函数时(通过根据传递给构造函数的参数设置someModuleVariable
),它可能会不必要地混淆代码。
然而,拥有一个可供整个模块访问的“私有”变量是一种非常常见的模式......例如,当使用单例对象时,因为当您离开函数的执行上下文时,范围变量永远不会被销毁,模块仍然可以查询“module-local”变量。
唯一让我错误的方法是使用构造函数只是为了它的副作用...为什么我会使用构造函数然后,当构造函数的一个主要目的是隐式设置属性时实例?
要区分这两个想法,一个常见的模式是在原型中使用init
方法,因为 是一个很好的地方,可以包含所有你想要的副作用。例如,人们可以建议这样做:
var Module = (function() {
var somethingPrivate;
function SomeObject(someProp) {
// rely on the constructor to set instance properties
this.someProp = someProp;
}
SomeObject.prototype = {
init: function(_somethingPrivate) {
// all of your side effects in here, such as:
somethingPrivate = _somethingPrivate;
}
};
return SomeObject;
}());
var module = new Module('Hello world! I belong to the instance');
module.init('I am a module-specific variable!');
然而,当然,这并不是说在某些情况下您可能不希望依赖构造函数来产生副作用。但是在你给出的例子中,它甚至看起来不像构造函数是必要的(尽管我理解这个例子只是为了演示问题而设计的。)
使用_
下划线的位置和方式大多不相关,只是作为旁注。在某些情况下,它们是好的,比如将伪私有属性与“公共”属性区分开来,但我认为这更像是一种约定,而不是一种刻板的模式。