Way*_*Kao 454 javascript oop private-methods
要使用公共方法创建JavaScript类,我会执行以下操作:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something here
}
Restaurant.prototype.use_restroom = function(){
// something here
}
Run Code Online (Sandbox Code Playgroud)
这样我班级的用户可以:
var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();
Run Code Online (Sandbox Code Playgroud)
如何创建一个可由buy_food和use_restroom方法调用的私有方法,但不能由类的用户创建外部方法?
换句话说,我希望我的方法实现能够:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
Run Code Online (Sandbox Code Playgroud)
但这不应该奏效:
var r = new Restaurant();
r.private_stuff();
Run Code Online (Sandbox Code Playgroud)
我如何定义private_stuff为私有方法,所以这两个都适用?
我已经阅读了Doug Crockford的几次写法,但看起来似乎不能通过公共方法调用"私有"方法,并且可以在外部调用"特权"方法.
17 *_* 26 377
你可以做到,但缺点是它不能成为原型的一部分:
function Restaurant() {
var myPrivateVar;
var private_stuff = function() { // Only visible inside Restaurant()
myPrivateVar = "I can set this here!";
}
this.use_restroom = function() { // use_restroom is visible to all
private_stuff();
}
this.buy_food = function() { // buy_food is visible to all
private_stuff();
}
}
Run Code Online (Sandbox Code Playgroud)
geo*_*ock 159
你可以像这样模拟私有方法:
function Restaurant() {
}
Restaurant.prototype = (function() {
var private_stuff = function() {
// Private code here
};
return {
constructor:Restaurant,
use_restroom:function() {
private_stuff();
}
};
})();
var r = new Restaurant();
// This will work:
r.use_restroom();
// This will cause an error:
r.private_stuff();
Run Code Online (Sandbox Code Playgroud)
有关此技术的更多信息,请访问:http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html
Yve*_* M. 153
JavaScript使用原型,并且没有像面向对象语言那样的类(或方法).JavaScript开发人员需要在JavaScript中思考.
维基百科报价:
与许多面向对象的语言不同,函数定义和方法定义之间没有区别.相反,区别发生在函数调用期间; 当一个函数作为一个对象的方法被调用时,该函数的local this关键字被绑定到该调用的该对象.
var MyObject = (function () {
// Constructor
function MyObject (foo) {
this._foo = foo;
}
function privateFun (prefix) {
return prefix + this._foo;
}
MyObject.prototype.publicFun = function () {
return privateFun.call(this, '>>');
}
return MyObject;
})();
var myObject = new MyObject('bar');
myObject.publicFun(); // Returns '>>bar'
myObject.privateFun('>>'); // ReferenceError: private is not defined
Run Code Online (Sandbox Code Playgroud)
该呼叫功能可以让我们调用私有函数与适当的上下文(this).
如果您使用的是node.js,则不需要IIFE,因为您可以利用模块加载系统:
function MyObject (foo) {
this._foo = foo;
}
function privateFun (prefix) {
return prefix + this._foo;
}
MyObject.prototype.publicFun = function () {
return privateFun.call(this, '>>');
}
exports.MyObject = MyObject;
Run Code Online (Sandbox Code Playgroud)
加载文件:
var MyObject = require('./MyObject').MyObject;
var myObject = new MyObject('bar');
myObject.publicFun(); // Returns '>>bar'
myObject.privateFun('>>'); // ReferenceError: private is not defined
Run Code Online (Sandbox Code Playgroud)
绑定运算符::是ECMAScript 提议,在Babel(阶段0)中实现.
export default class MyObject {
constructor (foo) {
this._foo = foo;
}
publicFun () {
return this::privateFun('>>');
}
}
function privateFun (prefix) {
return prefix + this._foo;
}
Run Code Online (Sandbox Code Playgroud)
加载文件:
import MyObject from './MyObject';
let myObject = new MyObject('bar');
myObject.publicFun(); // Returns '>>bar'
myObject.privateFun('>>'); // TypeError: myObject.privateFun is not a function
Run Code Online (Sandbox Code Playgroud)
小智 35
在这种情况下,如果你有一个公共API,并且你想要私有和公共方法/属性,我总是使用模块模式.这个模式在YUI库中很流行,详情可以在这里找到:
http://yuiblog.com/blog/2007/06/12/module-pattern/
这非常简单,其他开发人员也很容易理解.举个简单的例子:
var MYLIB = function() {
var aPrivateProperty = true;
var aPrivateMethod = function() {
// some code here...
};
return {
aPublicMethod : function() {
aPrivateMethod(); // okay
// some code here...
},
aPublicProperty : true
};
}();
MYLIB.aPrivateMethod() // not okay
MYLIB.aPublicMethod() // okay
Run Code Online (Sandbox Code Playgroud)
Sar*_*ath 21
这是我创建的类,用于理解Douglas Crockford在其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
}
Run Code Online (Sandbox Code Playgroud)
小智 13
我想到了这个:编辑:实际上,有人已经链接到相同的解决方案.咄!
var Car = function() {
}
Car.prototype = (function() {
var hotWire = function() {
// Private code *with* access to public properties through 'this'
alert( this.drive() ); // Alerts 'Vroom!'
}
return {
steal: function() {
hotWire.call( this ); // Call a private method
},
drive: function() {
return 'Vroom!';
}
};
})();
var getAwayVechile = new Car();
hotWire(); // Not allowed
getAwayVechile.hotWire(); // Not allowed
getAwayVechile.steal(); // Alerts 'Vroom!'
Run Code Online (Sandbox Code Playgroud)
D-M*_*arc 12
您现在可以使用es10 私有方法执行此操作。您只需要#在方法名称前添加一个。
class ClassWithPrivateMethod {
#privateMethod() {
return 'hello world';
}
getPrivateMessage() {
return #privateMethod();
}
}
Run Code Online (Sandbox Code Playgroud)
imo*_*mos 10
我认为这些问题一次又一次地出现,因为对闭包缺乏了解.Сlosures是JS中最重要的事情.每个JS程序员都必须感受到它的本质.
1.首先我们需要独立的范围(关闭).
function () {
}
Run Code Online (Sandbox Code Playgroud)
2.在这方面,我们可以做任何我们想做的.没有人会知道它.
function () {
var name,
secretSkills = {
pizza: function () { return new Pizza() },
sushi: function () { return new Sushi() }
}
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return name in secretSkills ? secretSkills[name]() : null
}
}
Run Code Online (Sandbox Code Playgroud)
3.为了让全世界了解我们的餐厅类,我们必须从封闭处归还.
var Restaurant = (function () {
// Restaurant definition
return Restaurant
})()
Run Code Online (Sandbox Code Playgroud)
4.最后,我们有:
var Restaurant = (function () {
var name,
secretSkills = {
pizza: function () { return new Pizza() },
sushi: function () { return new Sushi() }
}
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return name in secretSkills ? secretSkills[name]() : null
}
return Restaurant
})()
Run Code Online (Sandbox Code Playgroud)
5.此外,该方法对于继承和模板潜力
// Abstract class
function AbstractRestaurant(skills) {
var name
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return skills && name in skills ? skills[name]() : null
}
return Restaurant
}
// Concrete classes
SushiRestaurant = AbstractRestaurant({
sushi: function() { return new Sushi() }
})
PizzaRestaurant = AbstractRestaurant({
pizza: function() { return new Pizza() }
})
var r1 = new SushiRestaurant('Yo! Sushi'),
r2 = new PizzaRestaurant('Dominos Pizza')
r1.getFood('sushi')
r2.getFood('pizza')
Run Code Online (Sandbox Code Playgroud)
我希望这有助于人们更好地理解这个主题
Joh*_*ers 10
就个人而言,我更喜欢以下模式在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(); }
...
};
})();
Run Code Online (Sandbox Code Playgroud)
如您所见,它允许您定义类属性和实例属性,每个属性都可以是公共属性和私有属性.
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();Run Code Online (Sandbox Code Playgroud)
另见这个小提琴.
小智 8
所有这些关闭将花费你.确保测试速度影响,尤其是在IE中.您会发现最好使用命名约定.还有很多企业网站用户被迫使用IE6 ......
别这么啰嗦。它是 JavaScript。使用命名约定。
在 es6 类工作多年后,我最近开始研究一个 es5 项目(使用已经很冗长的 requireJS)。我已经一遍又一遍地提到这里提到的所有策略,基本上都归结为使用命名约定:
private. 其他使用 Javascript 的开发人员会预先知道这一点。因此,一个简单的命名约定就足够了。下划线前缀的简单命名约定解决了私有属性和私有方法的问题。我的工具提示.js
define([
'tooltip'
],
function(
tooltip
){
function MyTooltip() {
// Later, if needed, we can remove the underscore on some
// of these (make public) and allow clients of our class
// to set them.
this._selector = "#my-tooltip"
this._template = 'Hello from inside my tooltip!';
this._initTooltip();
}
MyTooltip.prototype = {
constructor: MyTooltip,
_initTooltip: function () {
new tooltip.tooltip(this._selector, {
content: this._template,
closeOnClick: true,
closeButton: true
});
}
}
return {
init: function init() {
new MyTooltip(); // <-- Our constructor adds our tooltip to the DOM so not much we need to do after instantiation.
}
// You could instead return a new instantiation,
// if later you do more with this class.
/*
create: function create() {
return new MyTooltip();
}
*/
}
});
Run Code Online (Sandbox Code Playgroud)
私有方法名称以哈希#前缀开头,并且只能在定义它的类中访问。
class Restaurant {
// private method
#private_stuff() {
console.log("private stuff");
}
// public method
buy_food() {
this.#private_stuff();
}
};
const restaurant = new Restaurant();
restaurant.buy_food(); // "private stuff";
restaurant.private_stuff(); // Uncaught TypeError: restaurant.private_stuff is not a function
Run Code Online (Sandbox Code Playgroud)