假设此代码为javascript代码
(function(){
NameSpace = new function(){} //global namespace
NameSpace.Apple = function(p_color){
var AppleInstance = this; //clarity..
AppleInstance.color = p_color;
return {
/**************
/ Public method
/**************/
//Here, we only return an access to the Method Eat
Eat : NameSpace.Apple.prototype.Eat
}
}
//Will be public
NameSpace.Apple.prototype.Eat = function(){
var AppleInstance = this; //clarity..
console.log("I'm eating a " + AppleInstance.color + " apple !")
}
//Will be private
NameSpace.Apple.prototype.PrivateMethod = function(){
var AppleInstance = this; //clarity..
console.log("This is a private method");
}
})()
new NameSpace.Apple("blue").Eat();
//I'm eating a undefined apple !
正如您所看到的,我在命名空间中有一个类,它包含1个私有变量,1个私有方法和1个公共方法。但是当访问我的公共方法时,这个方法无法访问类的变量。
我知道这是因为:
return {
/*...*/
}
但是有一种方法可以让我的公共原型方法访问我的私有变量(在我的原始代码中我想要一个常量..)而不用返回来访问它。
如果我在返回中返回属性,原型方法将可以访问它,但不是。
感谢。
答案 0 :(得分:3)
不。这两种策略有些不相容。这就是为什么私有属性通常是公共的,但在使用原型时以前缀为前缀。
Namespace.Apple = function(p_color){
this._color = p_color;
};
Namespace.Apple.prototype.eat = function(){
console.log("I'm eating a " + this._color + " apple !")
};
这告诉JS开发人员使用这个代码,他们不应该混淆_color
属性,因为它是供内部使用的。
那就是说,你还有其他大问题......
Namespace.Apple = function(p_color){
var AppleInstance = this; //clarity..
AppleInstance.color = p_color;
return {
/**************
/ Public method
/**************/
//Here, we only return an access to the Method Eat
Eat : NameSpace.Apple.prototype.Eat
}
}
这不符合你的想法。当构造函数返回一个对象时,将丢弃使用new
创建的实例。因此,您最终不会得到Apple
的实例。相反,你得到一个看起来像这样的普通对象:
{ Eat: Namespace.Apple.prototype.Eat }
那么您为其指定了颜色的对象?它消失了。
此方法不是私密的。
//Will NOT be private
Namespace.Apple.prototype.PrivateMethod = function(){
var AppleInstance = this; //clarity..
console.log("This is a private method");
}
原型上的一切都是公开的。 一切。
关于惯例的说明。
var AppleInstance = this; //clarity..
我认为根本不清楚。实例方法中使用this
来表示this
实例。任何对伤害可读性的混淆。
请为构造函数保存大写字母变量名称(Eat
坏!,Apple
好!,AppleInstance
坏!),也是为了便于阅读。由于调用没有new
关键字的构造函数会产生一些奇怪的后果。
为了避免这种情况,并且仍然拥有私有变量和方法,您根本不使用原型。您可以在构造函数中将所有变量和方法设置为函数,逐个构建实例。
var Namespace = {};
Namespace.Apple = function(color){
// color form the arguments is a local variable, bound to the methods created below
var somePrivateVar = 'privateData!'; // private instance variable
// public method, with access to private instance vars
this.eat = function(){
console.log("I'm eating a " + color + " apple!");
};
// public method, which calls private method
this.doSomethingPrivate = function() {
console.log('calling private method for you');
privateMethod()
}
// private method
var privateMethod = function(){
console.log("This is a private method for a " + color + " apple!");
};
// instance is auto-returned, no return needed.
}
var apple = new Namespace.Apple('red');
apple.eat(); // I'm eating a red apple!
apple.doSomethingPrivate(); // calling private method for you
// This is a private method for a red apple!
apple.privateMethod() // <exception> apple.privateMethod is undefined
关于这种方法,唯一需要注意的是它比使用原型时要慢得多,并且使用的内存要多得多。原型上的函数在所有实例之间共享,因此您只需要为方法创建和存储单个函数,并且每个实例都将执行该函数对象。
使用上述方法,每个实例都会创建并存储每个方法函数的新副本。并且每个函数都具有对该实例构造函数范围的特权访问,允许您使用私有变量和方法。如果你只计划有几个实例,这种差异可能不会产生很大的不同。但是,如果您计划拥有大量实例,性能差异可能会变得非常重要。
答案 1 :(得分:0)
为了实现封装,您需要建议以下结构:
(function(){
NameSpace = new function(){} //global namespace
NameSpace.Apple = function(p_color){
var AppleInstance = this; //clarity..
var color;
AppleInstance.color = p_color;
this.Eat = function(){
/**************
/ Public method
/**************/
//Here, we only return an access to the Method Eat
alert("I'm eating a " + AppleInstance.color + " apple !")
}
//Will be private
var private = function(){
var AppleInstance = this; //clarity..
alert("This is a private method");
}
function constructor(p_color){
AppleInstance.color = p_color;
}
constructor(p_color)
}
})()
new NameSpace.Apple("blue").Eat();
//I'm eating a blue apple !
new NameSpace.Apple("blue").private();
// Exception raised
我从不赞成忽略本地副本的this
变量,它对JS objcects的调用结构中的范围有重要影响,并为开发人员提供了这些可能发生变化的线索。
顺便说一句:Namespace.Apple.prototype.PrivateMethod
不会是私有方法,因为通过原型公开的所有内容都是公开的。