JavaScript中用于自定义构造函数的模块模式
当我有自己的自定义构造函数时,我尝试在JavaScript中应用模块模式。让我们举一个例子:JavaScript中用于自定义构造函数的模块模式,javascript,module-pattern,Javascript,Module Pattern,当我有自己的自定义构造函数时,我尝试在JavaScript中应用模块模式。让我们举一个例子: // Assume I need `name` as private function Dog(name){ this.name = name; } 我可以将上述内容改写为: function Dog(name) { let dogName = name; return { getName : function () { retur
// Assume I need `name` as private
function Dog(name){
this.name = name;
}
我可以将上述内容改写为:
function Dog(name) {
let dogName = name;
return {
getName : function () {
return dogName;
},
setName : function (name) {
dogName = name;
}
}
}
上面的代码没有正确的构造函数
属性和Dog.prototype
,返回的对象的prototype不匹配
为了解决这个问题,我做了两个修复:
function Dog(name) {
let dogName = name;
return {
// Fix 1
constructor : Dog,
getName : function () {
return dogName;
},
setName : function (name) {
dogName = name;
}
}
}
let d2 = new Dog("Tony");
// Fix 2 : This is painful as every time I need to set this up
Object.setPrototypeOf(d2 , Dog.prototype);
正如您所看到的,修复2是痛苦的。每次我必须创建一个对象时,我都需要这样做。
还有更好的办法吗
让我们不要偏离我们的讨论,即getter和setter应该转移到prototype。上面是我正在使用的一个简单示例。这里的问题是您在“构造函数”中返回一个对象文本,一个对象文本具有对象
原型。您不应该在构造函数中返回,您应该像在第一个代码段中那样将内容分配给this
function Dog(name) {
let dogName = name;
this.getName = function () {
return dogName;
};
this.setName = function (name) {
dogName = name;
};
}
虽然这不是实现类的常见模式,但您甚至没有使用原型
,因此不清楚为什么原型对您很重要。显然,这种方法允许您关闭一个变量,使其成为“私有”变量,而使用原型
是不可能的。但是,这种方法有更多的开销,因为Dog
的每个实例都有自己的函数用于getName
和setName
,而“私有”变量和方法的标准约定是在它们前面加下划线,以便您可以按预期使用原型
function Dog(name) {
this._name = name;
}
Dog.prototype.getName = function () {
return this._name;
};
Dog.prototype.setName = function (name) {
this._name = name;
};
免责声明:我不提倡用javascript进行封装。但这里有一些丑陋的方法
如果您想要的只是减少代码重复,那么您可以轻松地在“构造函数”中设置所有内容,使其成为自己的工厂:
function Dog(name) {
let dogName = name;
let dog = Object.create(Dog.prototype);
dog.getName = function () {
return dogName;
};
dog.setName = function (name) {
dogName = name;
};
return dog;
}
let d2 = new Dog("Tony");
如果您还想实际使用原型,可以使用符号来隐藏name属性:
Dog = function() {
const nameSymbol = Symbol("name");
function Dog(name) {
Object.defineProperty(this, nameSymbol, {
configurable: true,
enumerable: false,
writable: true,
value: name
});
}
Object.assign(Dog.prototype, {
getName : function () {
return this[nameSymbol];
},
setName : function (name) {
this[nameSymbol] = name;
}
});
return Dog;
}();
let d2 = new Dog("Tony");
但是符号仍然可以通过Object.getOwnPropertySymbols
检索。因此,如果您正在寻找一种方法,使不使用getter/setter就无法访问名称,我认为您必须使用WeakMap
:
Dog = function() {
const dogNames = new WeakMap()
function Dog(name) {
dogNames.set(this, name);
}
Object.assign(Dog.prototype, {
getName : function () {
return dogNames.get(this);
},
setName : function (name) {
dogNames.set(this, name);
}
});
return Dog;
}();
let d2 = new Dog("Tony");
您是否愿意使用类而不是函数?您应该使用类,每隔一段时间创建一次类的实例,然后在函数中直接向这个.prototype
添加属性如何?您甚至没有使用狗prototype。Object.setPrototypeOf(d2,Dog.prototype)
?您已经实现了返回对象的构造函数,对象文本具有对象
原型,您不应该在构造函数中返回。如果您需要将名称
设为“私有”,为什么要为其提供getName
和setName
访问器方法?