我试图更深入地抓住原型继承和类创建(我知道,还有其他方法,但为了这个目的,我试图掌握原型。)我的问题是:使用以下代码示例,是否有一种方法可以在Tree
和Fruit
内部创建私有变量,这些变量不会随函数返回,但仍可由原型函数genus
访问,并且bulk
?
var Tree = function ( name, size ) {
this.name = name;
this.size = size;
};
Tree.prototype.genus = function(){
return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus');
};
Tree.prototype.bulk = function(){
return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft';
};
var Fruit = function( name, size ) {
this.name = name;
this.size = size;
};
Fruit.prototype = new Tree();
// Fruit.prototype = Tree.prototype; -- I know this can be used, too.
Fruit.prototype.bulk = function(){
return ((typeof this.size !== 'undefined') ? Math.floor(this.size / 2) : '4') + ' lbs';
};
var pine = new Tree('Pine', 9);
var apple = new Fruit('Apple', 6);
console.log(pine.genus(), pine.bulk()); // Outputs: "Pine 9 ft"
console.log(apple.genus(), apple.bulk()); // Outputs: "Apple 3 lbs"
编辑:我尝试将this.name
和this.size
替换为可在原型函数中访问的私有变量。抱歉缺乏清晰度!
答案 0 :(得分:13)
是。你可以这样做:
(function() {
var private = "hi";
Tree.prototype.genus = function(){
return ((typeof this.name !== 'undefined') ? this.name : 'Hybridicus Maximus');
};
Tree.prototype.bulk = function(){
return ((typeof this.size !== 'undefined') ? this.size : '8') + ' ft';
};
})();
现在,它将提供这些函数可以看到的私有变量,但它将是一个私有的“类”变量 - 换句话说,所有实例将共享相同的变量。如果你想要每个实例的私有变量,你必须在构造函数(或“init”方法,或其他)中这样做,这意味着必须在那里创建共享这些私有的方法。 (你当然可以在原型上放置一个函数,在构造时创建实例方法。)
编辑 - 你可以做的一件事是使用这样的技术来构建像jQuery的“.data()”这样的机制,这样你就有了一个充当地方的类变量保持每个实例的值。它有点笨重,但它是可行的。
答案 1 :(得分:2)
这是我在关于Classes, Private Members, & Prototypal Inheritance in JavaScript的博文中所写的内容。基本上你想创建一个对每个对象都唯一的私有变量访问器函数,然后让那些原型方法调用那个私有访问器函数,为它提供只在闭包中可用的密钥:
(function(_) {
Tree = function ( name, size ) {
var hidden = {
name: name,
size: size
};
this._ = function($) {
return _ === $ && hidden;
};
};
Tree.prototype.genus = function(){
return ((typeof this._(_).name !== 'undefined') ? this._(_).name : 'Hybridicus Maximus');
};
Tree.prototype.bulk = function(){
return ((typeof this._(_).size !== 'undefined') ? this._(_).size : '8') + ' ft';
};
Fruit = function( name, size ) {
Tree.apply(this, arguments);
};
Fruit.prototype = new Tree();
// Fruit.prototype = Tree.prototype; -- I know this can be used, too.
Fruit.prototype.bulk = function(){
return ((typeof this._(_).size !== 'undefined') ? Math.floor(this._(_).size / 2) : '4') + ' lbs';
};
})({});
var pine = new Tree('Pine', 9);
var apple = new Fruit('Apple', 6);
console.log(pine.genus(), pine.bulk()); // Outputs: "Pine 9 ft"
console.log(apple.genus(), apple.bulk()); // Outputs: "Apple 3 lbs"
console.log(pine._(), pine._({})); // Outputs: "false false" because outside of closure
您会注意到最后一行显示私有变量在闭包之外是不可访问的,因此除非由访问者函数提供,否则无法通过第三方代码检索。
答案 2 :(得分:0)
可以像这样轻松实现
function SharedPrivate(){
var private = "secret";
this.constructor.prototype.getP = function(){return private}
this.constructor.prototype.setP = function(v){ private = v;}
}
var o1 = new SharedPrivate();
var o2 = new SharedPrivate();
console.log(o1.getP()); // secret
console.log(o2.getP()); // secret
o1.setP("Pentax Full Frame K1 is on sale..!");
console.log(o1.getP()); // Pentax Full Frame K1 is on sale..!
console.log(o2.getP()); // Pentax Full Frame K1 is on sale..!
o2.setP("And it's only for $1,795._");
console.log(o1.getP()); // And it's only for $1,795._
显然,关键点是通过利用闭包创建到私有变量的访问路由,然后在要创建的对象之间共享此访问点。利用接入点作为要为自然共享创建的对象的原型是理想的情况。因此,通过利用工厂模式和Object.create()
可以实现相同的功能,如下所示;
function SharedPrivate(){
var priv = "secret";
return {gp : function(){return priv},
sp : function(v){priv = v}
}
}
sharedProto = SharedPrivate(); // priv is now under closure to be shared
var p1 = Object.create(sharedProto); // sharedProto becomes o1.__proto__
var p2 = Object.create(sharedProto); // sharedProto becomes o2.__proto__
JavaScript原型结构是金色的!!
答案 3 :(得分:-1)
我根据您的问题标题而不是您提供的内容编写此内容。我在这里有同样的问题。
var Tree = function(){
var outprivatename = "bigsecret"
var Tre = function(nickname){
var privatename = "secret that no one should know"
this.nickname = nickname
outprivatename = outprivatename + "-->" + nickname
this.deepsecret=function(){return privatename + "---" + nickname}
}
Tre.prototype.getname=function(){
console.log(outprivatename+'-----'+this.nickname)
// console.log(privatename)
return this.nickname
}
return Tre
}
//case one: each has unique closure; `outprivatename` is different for them
var pine = new (Tree())('pine')
var apple = new (Tree())('apple')
pine.getname() //bigsecret-->pine-----pine
apple.getname() //bigsecret-->apple-----apple
console.log(pine.deepsecret()) //secret that no one should know---pine
console.log(apple.deepsecret()) //secret that no one should know---apple
//case one: two share one closure; `outprivatename` is same for both
var Hybrid = Tree()
var hybrid1 = new Hybrid("pinapple1")
var hybrid2 = new Hybrid("pinapple2")
hybrid1.getname() //bigsecret-->pinapple1-->pinapple2-----pinapple1
hybrid2.getname() //bigsecret-->pinapple1-->pinapple2-----pinapple2
console.log(hybrid1.deepsecret()) //secret that no one should know---pinapple1
console.log(hybrid2.deepsecret()) //secret that no one should know---pinapple2
基本上Tree
函数为其中的构造函数Tre
提供了一个闭包。您可以使用privatename
之外但在匿名函数Tre
内的那个,而不是使用最深的Tree
。