OOP in JS Public/Private Variables and Methods
Summary
- private variables are declared with the 'var' keyword inside the object, and can only be accessed by private functions and privileged methods.
- private functions are declared inline inside the object's constructor (or alternatively may be defined via
var functionName=function(){...}
) and may only be called by privileged methods (including the object's constructor).
- privileged methods are declared with
this.methodName=function(){...}
and may invoked by code external to the object.
- public properties are declared with
this.variableName
and may be read/written from outside the object.
- public methods are defined by
Classname.prototype.methodName = function(){...}
and may be called from outside the object.
- prototype properties are defined by
Classname.prototype.propertyName = someValue
- static properties are defined by
Classname.propertyName = someValue
(different between static and prototype properties)
Example
In this example, a person's name and race are set at birth and may never be changed. When created, a person starts out at year 1 and a hidden maximum age is determined for that person. The person has a weight which is modified by eating (tripling their weight) or exercising (halfing it). Every time the person eats or exercises, they grow a year older. The person object has a publicly accessible 'clothing' property which anyone can modify, as well as a dirtFactor which can be modified manually (throwing dirt on or scrubbing it off), but which increases every time the person eats or exercises, and is reduced by the use of the shower() method.
The Example Code
function Person(n,race){
this.constructor.population++; // this.constructor equal Person // ************************************************************************
// PRIVATE VARIABLES AND FUNCTIONS
// ONLY PRIVELEGED METHODS MAY VIEW/EDIT/INVOKE
// ***********************************************************************
var alive=true, age=1;
var maxAge=70+Math.round(Math.random()*15)+Math.round(Math.random()*15); // Math.random() return an random 0-1
function makeOlder(){ return alive = (++age <= maxAge) } // makeOlder cann't direct access outside Person var myName=n?n:"John Doe";
var weight=1; // ************************************************************************
// PRIVILEGED METHODS
// MAY BE INVOKED PUBLICLY AND MAY ACCESS PRIVATE ITEMS
// MAY NOT BE CHANGED; MAY BE REPLACED WITH PUBLIC FLAVORS
// ************************************************************************
this.toString=this.getName=function(){ return myName } this.eat=function(){
if (makeOlder()){
this.dirtFactor++;
return weight*=3;
} else alert(myName+" can't eat, he's dead!");
}
this.exercise=function(){
if (makeOlder()){
this.dirtFactor++;
return weight/=2;
} else alert(myName+" can't exercise, he's dead!");
}
this.weigh=function(){ return weight }
this.getRace=function(){ return race }
this.getAge=function(){ return age }
this.muchTimePasses=function(){ age+=50; this.dirtFactor=10; } // ************************************************************************
// PUBLIC PROPERTIES -- ANYONE MAY READ/WRITE
// ************************************************************************
this.clothing="nothing/naked";
this.dirtFactor=0;
} // ************************************************************************
// PUBLIC METHODS -- ANYONE MAY READ/WRITE
// ************************************************************************
Person.prototype.beCool = function(){ this.clothing="khakis and black shirt" }
Person.prototype.shower = function(){ this.dirtFactor=2 }
Person.prototype.showLegs = function(){ alert(this+" has "+this.legs+" legs") }
Person.prototype.amputate = function(){ this.legs-- } // ************************************************************************
// PROTOTYOPE PROERTIES -- ANYONE MAY READ/WRITE (but may be overridden)
// ************************************************************************
Person.prototype.legs=2; // ************************************************************************
// STATIC PROPERTIES -- ANYONE MAY READ/WRITE
// ************************************************************************
Person.population = 0;
// Here is the code that uses the Person class
function RunGavinsLife(){
var gk=new Person("Gavin","caucasian"); //New instance of the Person object created.
var lk=new Person("Lisa","caucasian"); //New instance of the Person object created.
alert("There are now "+Person.population+" people"); gk.showLegs(); lk.showLegs(); //Both share the common 'Person.prototype.legs' variable when looking at 'this.legs' gk.race = "hispanic"; //Sets a public variable, but does not overwrite private 'race' variable.
alert(gk+"'s real race is "+gk.getRace()); //Returns 'caucasian' from private 'race' variable set at create time.
gk.eat(); gk.eat(); gk.eat(); //weight is 3...then 9...then 27
alert(gk+" weighs "+gk.weigh()+" pounds and has a dirt factor of "+gk.dirtFactor); gk.exercise(); //weight is now 13.5
gk.beCool(); //clothing has been update to current fashionable levels
gk.clothing="Pimp Outfit"; //clothing is a public variable that can be updated to any funky value
gk.shower();
alert("Existing shower technology has gotten "+gk+" to a dirt factor of "+gk.dirtFactor); gk.muchTimePasses(); //50 Years Pass
Person.prototype.shower=function(){ //Shower technology improves for everyone
this.dirtFactor=0;
}
gk.beCool=function(){ //Gavin alone gets new fashion ideas
this.clothing="tinfoil";
}; gk.beCool(); gk.shower();
alert("Fashionable "+gk+" at "
+gk.getAge()+" years old is now wearing "
+gk.clothing+" with dirt factor "
+gk.dirtFactor); gk.amputate(); //Uses the prototype property and makes a public property
gk.showLegs(); lk.showLegs(); //Lisa still has the prototype property gk.muchTimePasses(); //50 Years Pass...Gavin is now over 100 years old.
gk.eat(); //Complains about extreme age, death, and inability to eat.
}
Notes
maxAge
is a private variable with no privileged accessor method; as such, there is no way to publicly get or set it.
race
is a private variable defined only as an argument to the contructor. Variables passed into the constructor are available to the object as private variables.
- The 'tinfoil'
beCool()
fashion method was applied only to thegk
object, not the entirePerson
class. Other people created and set tobeCool()
would still use the original 'khakis and black shirt' clothing that Gavin eschewed later in life.
- Note the implicit call to the
gk.toString()
method when using string concatenation. It is this which allows the codealert(gk+' is so cool.')
to put the word 'Gavin' in there, and is equivalent toalert(gk.toString()+' is so cool.')
. Every object of every type in JS has a.toString()
method, but you can override it with your own.
- You cannot (to my knowledge) assign public methods of a class inside the main object constructor...you must use the
prototype
property externally, as above with thebeCool()
andshower()
methods.
- As I attempted to show with the
Person.prototype.legs
property and theamputate()
function, prototype properties are shared by all object instances. Asking forlk.legs
yields '2' by looking at the single prototype property. However, attempting to change this value using eithergk.legs=1
or (in the Person object)this.legs=1
ends up making a new public property of the object specific to that instance. (This is why callinggk.amputate()
only removed a leg from Gavin, but not Lisa.) To modify a prototype property, you must usePerson.prototype.legs=1
or something likethis.constructor.prototype.legs=1
. (I say 'something like' because I discovered thatthis.constructor
is not available inside private functions of the object, sincethis
refers to the window object in that scope.)
- Wherever an anonymous function is declared inline with
foo = function(p1,p2){ some code }
thenew Function()
constructor is NOT equivalent, e.g.foo = new Function('p1','p2','code');
since the latter runs in the global scope--instead of inheriting the scope of the constructor function--thus preventing it from accessing the private variables. - As noted above in the code comments, the act of setting
gk.race
to some value did NOT overwrite the privaterace
variable. Although it would be a dumb idea, you can have both private and public variables with the same name. For example, theyell()
method in the following class will yield different values forfoo
andthis.foo
:function StupidClass(){
var foo = "internal";
this.foo = "external";
this.yell=function(){ alert("Internal foo is "+foo+"\nExternal foo is "+this.foo) }
} - Private functions and privileged methods, like private variables and public properties, are instantiated with each new object created. So each time
new Person()
is called, new copies ofmakeOlder()
,toString()
,getName()
,eat()
,exercise()
,weigh()
,getRace()
,getAge()
, andmuchTimePasses()
are created. For every Person, each time. Contrast this with public methods (only one copy ofbeCool()
andshower()
exist no matter how many Person objects are created) and you can see that for memory/performance reasons it can be preferable to give up some degree of object protection and instead use only public methods.
Note that doing so requires making private variables public (since without privileged accessor methods there would be no way to use them) so the public methods can get at them...and which also allows external code to see/destroy these variables. The memory/performance optimization of using only public properties and methods has consequences which may make your code less robust.
For example, in the above age
and maxAge
are private variables; age
can only be accessed externally through getAge()
(it cannot be set) and maxAge
cannot be read or set externally. Changing those to be public properties would allow any code to do something like gk.maxAge=1; gk.age=200;
which not only does it not make sense (you shouldn't be able to manipulate someone's age or lifespan directly), but by setting those values directly the alive
variable wouldn't properly be updated, leaving your Person object in a broken state.
Quote From:
OOP in JS, Part 1 : Public/Private Variables and Methods
See Also:
Object-Oriented JavaScript Tip: Creating Static Methods, Instance Methods
How To Get Private, Privileged, Public And Static Members (Properties And Methods)
OOP in JS Public/Private Variables and Methods的更多相关文章
- 深入浅出OOP(五): C#访问修饰符(Public/Private/Protected/Internal/Sealed/Constants)
访问修饰符(或者叫访问控制符)是面向对象语言的特性之一,用于对类.类成员函数.类成员变量进行访问控制.同时,访问控制符也是语法保留关键字,用于封装组件. Public, Private, Protec ...
- [Java] public, private, final and basic rules for naming.
1. Access: public, private, protected public: Any other class can access a public field or method. ( ...
- JavaScript Patterns 5.3 Private Properties and Methods
All object members are public in JavaScript. var myobj = { myprop : 1, getProp : function() { return ...
- php class中public,private,protected的区别,以及实例
一,public,private,protected的区别 public:权限是最大的,可以内部调用,实例调用等. protected: 受保护类型,用于本类和继承类调用. private: 私有类型 ...
- OOP in JS - Inheritance
Summary You cause a class to inherit using ChildClassName.prototype = new ParentClass();. You need t ...
- PHP中public,private,protected,abstract等关键字用法详解
PHP中常用的关键字 在PHP中包含了很多对函数和类进行限制的关键字,常用的通常有abstract,final,interface,public,protected,private,static等等, ...
- python之private variables
[python之private variables] “Private” instance variables that cannot be accessed except from inside a ...
- Public Private Protect Inheritance and access specifiers
In the previous lessons on inheritance, we've been making all of our data members public in order to ...
- 訪问控制 protected, public, private 对照
OOP 3大特性:数据抽象,继承,动态绑定 3中訪问标号 protected, public, private 对照 用类进行数据抽象:用继承类继承基类的成员,实现继承.通过将基类对应函数声明为vir ...
随机推荐
- PRD学习笔记:一些需要注意的说明
控件说明 1)输入框 若输入框有默认提示,点击输入框,弹出软键盘. 当输入框内不为空(空格除外)时,默认显示消失. 2)软键盘的弹出及退去机制 当输入框内必须输入的为数字时,弹出数字软键盘.其余时候, ...
- 用Canvas,画中国国旗(Canvas基本知识点)
.getContext("2d")=======>获取绘图接口 //2d .beginPath()========>创建绘图路径开始点 .moveTo(x,y)==== ...
- 不要错过 DevOps 之父出席的2017 DevOpsDays 北京站!
通过 DevOpsDays 活动,Patrick 将 DevOps 这项伟大的运动带到了地球的东方,带到了北京.同时,他将亲自参加2017年3月18日的 DevOpsDays 北京站,并作精彩演讲. ...
- ListView的局部刷新
有的列表可能notifyDataSetChanged()代价有点高,最好能局部刷新. 局部刷新的重点是,找到要更新的那项的View,然后再根据业务逻辑更新数据即可. private void upda ...
- 【LeetCode】25. Reverse Nodes in k-Group
Given a linked list, reverse the nodes of a linked list k at a time and return its modified list. k ...
- python爬虫框架scrapy初识(一)
Scrapy介绍 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中.所谓网络爬虫,就是一个在网上到处或定向抓取数据的 ...
- java学习笔记:反射
1.什么是反射? Reflection(反射)是被视为动态语言的关键,反射机制允许程序做执行期间借助于ReflectionAPI取得任何类的内部信息,并能直接操作任意对象内部属性及方法 2.反射相关的 ...
- php 内置函数 ( 随手能写出100个才算高级工程师 )
string 类型 去掉左右空格, trim()字符串的长度 strlen() float类型数组类型 count() 数组个数 资源类型 fopen() 大写转小写 strtolower()小写转大 ...
- JSTL标签库--核心标签库
->JSTL的使用和EL表达式是分不开的 ->JSTL标签库分为5类 1.核心标签库(这里只介绍该标签库) 2.I18N格式化标签库 3.SQL标签库 4.XML标签库 5.函数标签库 - ...
- java四种xml解析区别
1.DOM解析 dom解析是根据树形结构解析,将整个文档加载到内存中,因此对内存的要求较高,所以可以对该文档数据进行多次操作(增,删,改,查). 2.SAX解析 SAX解析是根据事件模型解析,边读取文 ...