问题描述
我有使用C#编程语言的经验,但是我现在还必须使用JS,这对我来说是相当新的东西.
I have an experience with the C# programming language, but I also have to work with the JS now and it's rather new for me.
我试图在JS中开发一个简单的类仿真,如下所示:
I have tried to develop a simple class emulation in JS, like this:
function A( inputValue ) {
this.Init( inputValue );
this.Print();
}
A.prototype = {
value: null,
Init: function( inputValue ) {
this.value = inputValue;
},
Print: function () {
console.log( this.value );
}
}
var obj = new A(40);
我尝试将变量value
封装在A.prototype
中,但是似乎JavaScript规范中所有对象都可用.
I've tried to encapsulate the variable value
in A.prototype
, but it seems to be by JavaScript specification that all objects are available.
所以我的问题是:
1).如何制作一个封装,它非常接近OOP/access修饰符支持的静态语言?
1). How can I make an encapsulation , which is very close to the static languages with OOP/access modifiers support?
2).如何在JS中模拟某些访问修饰符,例如private
?
2). How can I emulate some access modifiers in JS, like private
for e.g.?
推荐答案
如果要使用继承,则不能(至少AFAIK).但是对于没有继承链的对象,可以使用闭包来获得完全相同的效果.问题是您是否真的需要属性才能真正完全私有.
If you want to use inheritance, you cannot (at least AFAIK). For objects with no inheritance chain you can however use closures to get exactly the same effect. The question is if you actually really need properties to actually be completely private.
您可以执行一个函数,其中的闭包包含要私有的变量.这些私有变量实际上并不属于对象,而是只能由对象的方法访问.例如:
You can execute a function of which closure contains the variables you want to be private. These private variables do not actually belong to the object, but are only accesible by the methods of the object. For instance:
var getPersonInstance = function (name) {
// Those are "private" properties
var myName = name;
return {
getName: function () {
return myName
},
setName: function (name) {
myName = name;
},
sayHello = function () {
alert('hello! my name is ' + myName);
}
}
};
var person = getPersonInstance('Juan');
person.getName(); // Returns Juan
person.myName = 'Don Vito' // This sets the person.myName property, which is not the one in the closure
person.setName('John') // Works
person.sayHello(); // alert hello! my name is John
您可以在这里查看:
如果您对Constructor函数符号更满意,则可以执行以下操作:
If you feel more comfortable with the Constructor function notation, you can do something like this:
(未经测试)
function Person(name) {
// Anything that is not attached to this will be private
var myName = name;
this.getName = function () { return myName;};
this.setName = function (newName) {myName = newName;};
this.sayHello = function () {alert('hey there, my name is' + myName);};
}
与上面几乎相同,因为未使用原型,并且方法直接复制到对象中.
Which is pretty much the same as above, since the prototype is not used and the methods are copied directly into the object.
但是,闭包方法是内存和耗时的,而且是最坏的:它们使用的变量实际上并不属于您正在使用的对象……这是一个重要的语义"问题(这个道具是否属于我?)使继承成为一件令人头疼的事情.这样做的原因是,扩展对象的方法要么不能访问该私有伪属性(因为它们未在超对象闭包中定义),要么可以访问超对象"中的公共私有变量(即方法是在超级对象中定义的,因此可以访问超级对象的闭包).那是胡说八道.
However, the closure approach are is memory and time consuming, and the worst: they make use of variables that do not in fact belong to the object you are working with... This is an important "semantic" problem (does this prop belong to me, or not?) that makes inheritance a headache. The reason for this, is that the methods of the extended objects either dont have access to that private pseudo-property (because they are not defined in the superobject closure), or have access to a common private variable from the "superobject" (the method was defined in the superobject and therefore access the closure of the superobject). That is a nonsense.
以我的拙见,封装并不能阻止任何人在他/她真的想要的时候弄乱你的代码,因此我更喜欢遵循python的哲学:我们都是成熟的人"使用约定说我希望不从外部使用此属性".例如,我给私有属性加上'_'前缀,这意味着它们是私有的,受保护的或其他任何东西,但是要远离它.而且您不会碰触您不应该碰触的东西.
In my humble opinion, encapsulation does not prevent anybody from messing with your code if he/she really wants to, so I prefer to follow the python philosophy "we are all mature people" which consists of using a convention to say "I would like this property not to be used from the outside". For instance, I prefix the private properties with '_', meaning that they're private, protected, or whatever but just stay away from it. And you don't touch what you should not touch.
这种方法是最简单,最有效的方法,它使您可以处理继承链,因为属性在对象中,而不是在闭包中.
This approach, appart from being the simplest and the most efficient, allows you for working with inheritance chains, since the properties are in the object and not confined in the closure.
var Person = function (name) {
this._name = name;
}
Person.prototype.sayHello = function () {...};
Person.prototype.getName = function () {...};
Person.prototype.setName = function () {...};
这篇关于封装在JavaScript中,它存在吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!