Javascript 实例是否共享同一个函数,同时又有私有变量?
我有一段代码:Javascript 实例是否共享同一个函数,同时又有私有变量?,javascript,function,ecmascript-5,Javascript,Function,Ecmascript 5,我有一段代码: var Human=function(name){ this._name=name; }; Human.prototype.Shout=function(){ alert(this._name); }; var tom=new Human("tom"); var john=new Human("john"); alert(tom.Shout===john.Shout); 现在。你的名字不是“私人的”。我想把._命名为“private”,但同时我不想为每个Human实例
var Human=function(name){
this._name=name;
};
Human.prototype.Shout=function(){
alert(this._name);
};
var tom=new Human("tom");
var john=new Human("john");
alert(tom.Shout===john.Shout);
现在。你的名字不是“私人的”。我想把._命名为“private”,但同时我不想为每个Human实例创建额外的函数(换句话说,tom.Shout必须===to john.Shout),因为为每个实例创建额外的函数很好。。不必要(ok offtopic-我们可以在另一个线程上对此进行辩论)
我的结论是,我想要实现的目标是不可能的(拥有一个“私人”的名字,同时拥有tom.Shout==john.Shout
)
但我只想在得出任何结论之前有200%的把握
(只要满足要求,我欢迎任何黑客攻击,即不为每个实例创建附加功能)
如果我们必须创建额外的函数来进行范围界定,这很好,但是这个数字应该是一个固定的数字,并且这个数字不应该随着每个人类实例的增加而增加。这怎么样
var Human = function (name) {
var _name = name;
this.getName = function () {
return _name;
}
};
Human.prototype.Shout = function () {
alert(this.getName());
};
var tom = new Human("tom");
var john = new Human("john");
tom.Shout(); // tom
john.Shout(); // john
alert(tom.Shout === john.Shout); // true
function Human(name) {
if (!(this instanceof Human)){
return new Human(name);
}
this._name = name;
if (!Human.prototype.Name){
Human.prototype.Name = function(val){
if (val){
this._name = val;
return this;
}
return this._name;
};
Human.prototype.shout = function(){
alert(this._name);
}
}
}
编辑:
前者为GET属性创建另一个函数,
如果不创建其他功能,则无法进行更新。 您正在查找哪个是实例变量。祈祷下一个是es,但我们还没有。也许两年后吧 如果您关心干净的API,那么以下是您的解决方案:
function Class(foo) {
Class.priv(this).foo = foo;
}
Class.priv = (function() {
var cache = [],
uid = 1;
return function(obj) {
if (!this.__id) {
this.__id = uid;
cache[uid++] = {};
}
return cache[this.__id];
};
}());
Class.prototype.bar = function() {
console.log(Class.priv(this).foo);
}
将所有数据作为构造函数的函数存储在缓存中。对象上没有凌乱的数据
原创
然而,没有“私人”这样的东西
您所能做的就是在函数中创建一个局部变量
构造函数
var Human = function(name) {
// local variable.
var _name = name;
}
具有一个局部变量,根据局部定义,该局部变量在构造函数之外不可用
这意味着您不能像原型一样在外部代码中访问它
但是,您可以使用ES5将其设置为只读
var Human = function(name) {
Object.defineProperty(this, "name", { value: name });
}
如果你能真正达到你的要求,你将在js上取得巨大的突破。我已经尝试了好几个小时了
另一种模式是:
var Human = function(name) {
this.name = name;
return {
Shout: this.Shout.bind(this)
};
}
Human.prototype.Shout = function() {
console.log(this.name);
}
这需要调用
.bind
并为每个实例创建一个新对象,这会带来开销。读了问题,不理解,因为这个。_name
不是私有的,所以这个问题有点奇怪。这就是如何在原型中一次性添加方法并可用于所有实例。我重复一遍:这个。_name
在这里不是私有的。如果您添加了一个局部变量,并且希望通过原型方法中的闭包来访问它,那么调用该局部变量的值将为所有实例生成相同的值
无论如何,使用此构造函数,this.\u name getter和shout方法将一次性添加到原型链中,从而可用于所有人类实例
function Human(name) {
if (!(this instanceof Human)){
return new Human(name);
}
this._name = name;
if (!Human.prototype.Name){
Human.prototype.Name = function(val){
if (val){
this._name = val;
return this;
}
return this._name;
};
Human.prototype.shout = function(){
alert(this._name);
}
}
}
这就为每个人类实例创建了一个附加函数。。违反了第一条、最后一条和唯一一条规则这是正确的,但它将_name变量保持为私有,并限制对公共财产的访问我知道,但这个问题的全部原因是为了找出是否有任何黑客允许我们进行攻击。_name“private”,但与此同时,我不希望为每个Human[/quote]实例创建额外的函数,我们设法使界面干净(使_name私有),但代价是使其变脏(添加另一个公共成员getName),这有点违背了目的,但公平地说,我没有声明这是不允许的question@Pacerier我用来清理接口的一种模式是使用一个变量
this.\u={}
和所有局部变量this.\uname
。除非你在中查看,否则会显示较少的混乱。\u
也许我遗漏了一些东西,但是在Chrome、Firefox和IE以及nodejs(v8)中运行上述代码时,都会提示“true”。@Rob Raisch是的,它应该是“true”,因为函数是同一个实例。换句话说,我们只有一个由双方“共享”的函数Humans@Pacerier,并且由于“this”是为每个实例创建的特殊上下文,所有实例都会有自己的“u名称”。@Pacerier您严重高估了(在浏览器中)创建函数的费用。@Pacerier,嗯。。。好的,从我在其他评论中读到的内容来看,你想把它命名为private,而不是“private”,这意味着类似于private的东西,但实际上不是?您是否正在寻找一种可靠的方法来使实例变量真正私有化,因为它们不能从实例外部访问?如果是的话,就没有了。Javascript允许反射,这将“刺穿”真正隐私的面纱。@Kooilncalert(tom.shout==john.shout);//false
事实上,当我说我想做的时候。_name“private”我想很清楚我的意思是:现在。_name不是“private”。我想把它命名为“私人”。无论如何,我已经编辑了这个问题的措辞,以防其他人弄糊涂。bind实际上在每次调用它时都会创建一个新函数。实际上,我对附加对象的开销没有意见,因为当我们将其与这些附加函数的伸缩方式进行比较时,它的伸缩性非常好。我想说的是,如果人类类有6个方法,每个新实例都有1个对象和6个新函数的开销。如果人类类有12个方法,则每个新实例的开销为1个对象(仍然),但有12个新实例functions@Pacerier正确的绑定确实创建了一个新方法。你意识到你不应该关心开销,对吗?任何少于10k的实例都没有问题,任何超过10k的实例都需要分析。担心这是一种微观优化。是的。我正在寻找更好的选择,以防有一个我不知道的of@Pacerier我已经实现了一个抽象来清理对象。但您的数据仍存储在对象中。这是每个对象的额外开销。