使用具有显示模块模式的 ECMAScript 5 get/set 属性
Using ECMAScript 5 get/set properties with revealing module pattern
考虑以下 contrived bit of JavaScript based on the revealing module pattern:
var RevealingModuleSample = function () {
var moduleName = "DefaultModuleName",
init = function (name) {
moduleName = name
},
issueAlert = function () {
alert(moduleName + " module is running");
}
return {
init: init,
issueAlert: issueAlert
};
} ();
RevealingModuleSample.init("SampleModule");
RevealingModuleSample.issueAlert();
有没有办法使用 getter 和 setter 方法 将 moduleName 转换为 属性 并让内部调用那些 getter/setter 方法引用 moduleName? 举一个具体的例子,考虑以下 similarly contrived C# example:
public class ContrivedCsharpExample
{
private string _moduleName;
protected string moduleName
{
get {
// Perhaps some logging code here that records the moduleName was retrieved.
return this._moduleName;
}
set {
// Some code here that ensure that a valid moduleName was passed.
this._moduleName = value;
}
}
public void init(string moduleName) {
this.moduleName = moduleName;
}
public void issueAlert() {
Console.WriteLine(this.moduleName);
}
public static void Main()
{
var module = new ContrivedCsharpExample();
module.init("SampleC#Module");
module.issueAlert();
}
}
请注意,在 class 内部,这些方法正在调用具有 getter/setter 的属性。这允许我们在那些 getter/setter 方法中添加额外的代码,而如果我们只使用 class 之外可用的属性,"init" 和 "issueAlert" 方法将不得不直接检查该字段以及我们添加到 getter/setter 的任何逻辑都将被绕过。
我看到的问题是,在揭示模块模式中,"moduleName" 变量不是对象上的 属性——它只是一个当前在范围内的变量。因此,您不能只是将其拉出并用 get/set 对替换它。对吗?
There is a related question on Whosebug,但在那种情况下,发问者正在寻找一种方法来 return 具有 属性 和 getter/setter 代码,以便模块的外部用户通过 get/set 方法路由他们的 属性 访问。问题中列出了一个解决方案,但提供的解决方案不允许模块内部的代码访问 属性 而不直接对变量进行操作,绕过 get/set 函数。
我认为这对于显示模块模式来说根本不可能,对吗?有没有办法让模块内部的调用通过 get/set 函数路由?
你是对的,因为你不能在变量上定义 setter/getter
。它必须是对象的 属性。解决方案是将模块的内部转换为一个对象,同时仍然暴露相同的 public API:
var RevealingModuleSample = function () {
var self = {
_moduleName: "DefaultModuleName",
set moduleName(name) {
console.log("setting module name: " + name);
self._moduleName = name;
},
get moduleName() {
return self._moduleName;
},
init: function (name) {
self.moduleName = name;
},
issueAlert: function () {
alert(self.moduleName + " module is running");
}
};
return {
init: self.init,
issueAlert: self.issueAlert
};
}();
RevealingModuleSample.init("SampleModule");
RevealingModuleSample.issueAlert();
公开对象方法的一个后果是,在调用方法时,this
的上下文或值会丢失。因此在对象内部使用 self
,这是对 this
.
的简单引用
我想另一种方法是将所有私有变量存储在一个单独的对象中,但这对我来说似乎不太优雅。
是一种使用 IIFE 来接近您想要的东西的方法,尽管我认为它有点矫枉过正。但是,您必须做出妥协——您总是必须使用函数而不是使用属性:
var Example = function () {
var moduleName = (function(moduleName){
return function(value){
if (val === undefined) return moduleName;
moduleName= val;
};
})("DefaultModuleName");
init = function (name) {
moduleName(name);
},
issueAlert = function () {
alert(moduleName() + " module is running");
}
return {
init: init,
issueAlert: issueAlert
};
} ();
Example.init("SampleModule");
Example.issueAlert();
诀窍是使用 IIFE return 访问函数。如果不带参数调用,该函数是 getter,如果带参数调用,它是 setter。访问函数改变了 IIFE 闭包中隐藏变量的值,IIFE 之外的任何东西都无法访问它,除非通过访问函数。
在这种情况下,揭示模块模式是一个转移注意力的问题 -- 它与问题没有任何关系,它是一个 anti-pattern as it's the worst of the implementations of the module pattern。
考虑以下 contrived bit of JavaScript based on the revealing module pattern:
var RevealingModuleSample = function () {
var moduleName = "DefaultModuleName",
init = function (name) {
moduleName = name
},
issueAlert = function () {
alert(moduleName + " module is running");
}
return {
init: init,
issueAlert: issueAlert
};
} ();
RevealingModuleSample.init("SampleModule");
RevealingModuleSample.issueAlert();
有没有办法使用 getter 和 setter 方法 将 moduleName 转换为 属性 并让内部调用那些 getter/setter 方法引用 moduleName? 举一个具体的例子,考虑以下 similarly contrived C# example:
public class ContrivedCsharpExample
{
private string _moduleName;
protected string moduleName
{
get {
// Perhaps some logging code here that records the moduleName was retrieved.
return this._moduleName;
}
set {
// Some code here that ensure that a valid moduleName was passed.
this._moduleName = value;
}
}
public void init(string moduleName) {
this.moduleName = moduleName;
}
public void issueAlert() {
Console.WriteLine(this.moduleName);
}
public static void Main()
{
var module = new ContrivedCsharpExample();
module.init("SampleC#Module");
module.issueAlert();
}
}
请注意,在 class 内部,这些方法正在调用具有 getter/setter 的属性。这允许我们在那些 getter/setter 方法中添加额外的代码,而如果我们只使用 class 之外可用的属性,"init" 和 "issueAlert" 方法将不得不直接检查该字段以及我们添加到 getter/setter 的任何逻辑都将被绕过。
我看到的问题是,在揭示模块模式中,"moduleName" 变量不是对象上的 属性——它只是一个当前在范围内的变量。因此,您不能只是将其拉出并用 get/set 对替换它。对吗?
There is a related question on Whosebug,但在那种情况下,发问者正在寻找一种方法来 return 具有 属性 和 getter/setter 代码,以便模块的外部用户通过 get/set 方法路由他们的 属性 访问。问题中列出了一个解决方案,但提供的解决方案不允许模块内部的代码访问 属性 而不直接对变量进行操作,绕过 get/set 函数。
我认为这对于显示模块模式来说根本不可能,对吗?有没有办法让模块内部的调用通过 get/set 函数路由?
你是对的,因为你不能在变量上定义 setter/getter
。它必须是对象的 属性。解决方案是将模块的内部转换为一个对象,同时仍然暴露相同的 public API:
var RevealingModuleSample = function () {
var self = {
_moduleName: "DefaultModuleName",
set moduleName(name) {
console.log("setting module name: " + name);
self._moduleName = name;
},
get moduleName() {
return self._moduleName;
},
init: function (name) {
self.moduleName = name;
},
issueAlert: function () {
alert(self.moduleName + " module is running");
}
};
return {
init: self.init,
issueAlert: self.issueAlert
};
}();
RevealingModuleSample.init("SampleModule");
RevealingModuleSample.issueAlert();
公开对象方法的一个后果是,在调用方法时,this
的上下文或值会丢失。因此在对象内部使用 self
,这是对 this
.
我想另一种方法是将所有私有变量存储在一个单独的对象中,但这对我来说似乎不太优雅。
是一种使用 IIFE 来接近您想要的东西的方法,尽管我认为它有点矫枉过正。但是,您必须做出妥协——您总是必须使用函数而不是使用属性:
var Example = function () {
var moduleName = (function(moduleName){
return function(value){
if (val === undefined) return moduleName;
moduleName= val;
};
})("DefaultModuleName");
init = function (name) {
moduleName(name);
},
issueAlert = function () {
alert(moduleName() + " module is running");
}
return {
init: init,
issueAlert: issueAlert
};
} ();
Example.init("SampleModule");
Example.issueAlert();
诀窍是使用 IIFE return 访问函数。如果不带参数调用,该函数是 getter,如果带参数调用,它是 setter。访问函数改变了 IIFE 闭包中隐藏变量的值,IIFE 之外的任何东西都无法访问它,除非通过访问函数。
在这种情况下,揭示模块模式是一个转移注意力的问题 -- 它与问题没有任何关系,它是一个 anti-pattern as it's the worst of the implementations of the module pattern。