要创建一个带有公共方法的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(cb) {
const self = {};
const constructor = (fn) => {
func = fn;
};
const addPrivate = (fnName, obj) => {
self[fnName] = obj;
}
const addPublic = (fnName, obj) => {
this[fnName] = obj;
self[fnName] = obj;
func.prototype[fnName] = obj;
}
cb(constructor, addPrivate, addPublic, self);
return func;
}
const test = new Class((constructor, private, public, self) => {
constructor(function (test) {
console.log(test)
});
public('test', 'yay');
private('qwe', 'nay');
private('no', () => {
return 'hello'
})
public('asd', () => {
return 'this is public'
})
public('hello', () => {
return self.qwe + self.no() + self.asd()
})
})
const asd = new test('qweqwe');
console.log(asd.hello());
就我个人而言,我更喜欢用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();
看看这小提琴。
下面是我创建的类,用来理解Douglas Crockford在他的网站Private Members in JavaScript中的建议
function Employee(id, name) { //Constructor
//Public member variables
this.id = id;
this.name = name;
//Private member variables
var fName;
var lName;
var that = this;
//By convention, we create a private variable 'that'. This is used to
//make the object available to the private methods.
//Private function
function setFName(pfname) {
fName = pfname;
alert('setFName called');
}
//Privileged function
this.setLName = function (plName, pfname) {
lName = plName; //Has access to private variables
setFName(pfname); //Has access to private function
alert('setLName called ' + this.id); //Has access to member variables
}
//Another privileged member has access to both member variables and private variables
//Note access of this.dataOfBirth created by public member setDateOfBirth
this.toString = function () {
return 'toString called ' + this.id + ' ' + this.name + ' ' + fName + ' ' + lName + ' ' + this.dataOfBirth;
}
}
//Public function has access to member variable and can create on too but does not have access to private variable
Employee.prototype.setDateOfBirth = function (dob) {
alert('setDateOfBirth called ' + this.id);
this.dataOfBirth = dob; //Creates new public member note this is accessed by toString
//alert(fName); //Does not have access to private member
}
$(document).ready()
{
var employee = new Employee(5, 'Shyam'); //Create a new object and initialize it with constructor
employee.setLName('Bhaskar', 'Ram'); //Call privileged function
employee.setDateOfBirth('1/1/2000'); //Call public function
employee.id = 9; //Set up member value
//employee.setFName('Ram'); //can not call Private Privileged method
alert(employee.toString()); //See the changed object
}
以下是迄今为止我最喜欢的关于javascript中的私有/公共方法/成员和实例化:
这是文章:http://www.sefol.com/?p=1090
下面是一个例子:
var Person = (function () {
//Immediately returns an anonymous function which builds our modules
return function (name, location) {
alert("createPerson called with " + name);
var localPrivateVar = name;
var localPublicVar = "A public variable";
var localPublicFunction = function () {
alert("PUBLIC Func called, private var is :" + localPrivateVar)
};
var localPrivateFunction = function () {
alert("PRIVATE Func called ")
};
var setName = function (name) {
localPrivateVar = name;
}
return {
publicVar: localPublicVar,
location: location,
publicFunction: localPublicFunction,
setName: setName
}
}
})();
//Request a Person instance - should print "createPerson called with ben"
var x = Person("ben", "germany");
//Request a Person instance - should print "createPerson called with candide"
var y = Person("candide", "belgium");
//Prints "ben"
x.publicFunction();
//Prints "candide"
y.publicFunction();
//Now call a public function which sets the value of a private variable in the x instance
x.setName("Ben 2");
//Shouldn't have changed this : prints "candide"
y.publicFunction();
//Should have changed this : prints "Ben 2"
x.publicFunction();
JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/