要创建一个带有公共方法的JavaScript类,我可以这样做:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something here
}
Restaurant.prototype.use_restroom = function(){
// something here
}
这样,我类的用户就可以:
var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();
如何创建一个私有方法,可以由buy_food和use_restroom方法调用,但不能由类的用户外部调用?
换句话说,我希望我的方法实现能够做到:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
但这是行不通的:
var r = new Restaurant();
r.private_stuff();
如何将private_stuff定义为私有方法,使两者都成立?
我读过Doug Crockford的文章几次,但它似乎不像“私有”方法可以被公共方法调用,而“特权”方法可以被外部调用。
这是我得出的结论:
需要一类糖代码,你可以在这里找到。还支持保护,继承,虚拟,静态的东西…
;( function class_Restaurant( namespace )
{
'use strict';
if( namespace[ "Restaurant" ] ) return // protect against double inclusions
namespace.Restaurant = Restaurant
var Static = TidBits.OoJs.setupClass( namespace, "Restaurant" )
// constructor
//
function Restaurant()
{
this.toilets = 3
this.Private( private_stuff )
return this.Public( buy_food, use_restroom )
}
function private_stuff(){ console.log( "There are", this.toilets, "toilets available") }
function buy_food (){ return "food" }
function use_restroom (){ this.private_stuff() }
})( window )
var chinese = new Restaurant
console.log( chinese.buy_food() ); // output: food
console.log( chinese.use_restroom() ); // output: There are 3 toilets available
console.log( chinese.toilets ); // output: undefined
console.log( chinese.private_stuff() ); // output: undefined
// and throws: TypeError: Object #<Restaurant> has no method 'private_stuff'
既然每个人都在这里张贴自己的代码,我也要这样做…
我喜欢Crockford,因为他在Javascript中引入了真正的面向对象模式。但他也产生了一个新的误解,那个“那个”。
那么他为什么要用"that = this"呢?这和私人活动完全没有关系。它与内部函数有关!
因为根据Crockford的说法,这是有bug的代码:
Function Foo( ) {
this.bar = 0;
var foobar=function( ) {
alert(this.bar);
}
}
所以他建议这样做:
Function Foo( ) {
this.bar = 0;
that = this;
var foobar=function( ) {
alert(that.bar);
}
}
就像我说的,我很确定Crockford对这个和这个的解释是错误的(但他的代码肯定是正确的)。或者他只是在愚弄Javascript世界,知道谁在复制他的代码?我不知道……我不是浏览器极客
EDIT
啊,这就是问题所在:'var that = this;'在JavaScript中是什么意思?
所以Crockie的解释是错误的....但他的代码是正确的,所以他还是个好人。:))
就我个人而言,我更喜欢用JavaScript创建类的以下模式:
var myClass = (function() {
// Private class properties go here
var blueprint = function() {
// Private instance properties go here
...
};
blueprint.prototype = {
// Public class properties go here
...
};
return {
// Public class properties go here
create : function() { return new blueprint(); }
...
};
})();
如您所见,它允许您定义类属性和实例属性,每个属性都可以是公共的和私有的。
Demo
var Restaurant = function() {
var totalfoodcount = 0; // Private class property
var totalrestroomcount = 0; // Private class property
var Restaurant = function(name){
var foodcount = 0; // Private instance property
var restroomcount = 0; // Private instance property
this.name = name
this.incrementFoodCount = function() {
foodcount++;
totalfoodcount++;
this.printStatus();
};
this.incrementRestroomCount = function() {
restroomcount++;
totalrestroomcount++;
this.printStatus();
};
this.getRestroomCount = function() {
return restroomcount;
},
this.getFoodCount = function() {
return foodcount;
}
};
Restaurant.prototype = {
name : '',
buy_food : function(){
this.incrementFoodCount();
},
use_restroom : function(){
this.incrementRestroomCount();
},
getTotalRestroomCount : function() {
return totalrestroomcount;
},
getTotalFoodCount : function() {
return totalfoodcount;
},
printStatus : function() {
document.body.innerHTML
+= '<h3>Buying food at '+this.name+'</h3>'
+ '<ul>'
+ '<li>Restroom count at ' + this.name + ' : '+ this.getRestroomCount() + '</li>'
+ '<li>Food count at ' + this.name + ' : ' + this.getFoodCount() + '</li>'
+ '<li>Total restroom count : '+ this.getTotalRestroomCount() + '</li>'
+ '<li>Total food count : '+ this.getTotalFoodCount() + '</li>'
+ '</ul>';
}
};
return { // Singleton public properties
create : function(name) {
return new Restaurant(name);
},
printStatus : function() {
document.body.innerHTML
+= '<hr />'
+ '<h3>Overview</h3>'
+ '<ul>'
+ '<li>Total restroom count : '+ Restaurant.prototype.getTotalRestroomCount() + '</li>'
+ '<li>Total food count : '+ Restaurant.prototype.getTotalFoodCount() + '</li>'
+ '</ul>'
+ '<hr />';
}
};
}();
var Wendys = Restaurant.create("Wendy's");
var McDonalds = Restaurant.create("McDonald's");
var KFC = Restaurant.create("KFC");
var BurgerKing = Restaurant.create("Burger King");
Restaurant.printStatus();
Wendys.buy_food();
Wendys.use_restroom();
KFC.use_restroom();
KFC.use_restroom();
Wendys.use_restroom();
McDonalds.buy_food();
BurgerKing.buy_food();
Restaurant.printStatus();
BurgerKing.buy_food();
Wendys.use_restroom();
McDonalds.buy_food();
KFC.buy_food();
Wendys.buy_food();
BurgerKing.buy_food();
McDonalds.buy_food();
Restaurant.printStatus();
看看这小提琴。