var functionName=function(){…}
로 선언 가능하다.) 그리고 (생성자를 포함하여) privileged 메소드에 의해서만 호출이 가능하다.this.methodName=function(){...}
객체 바깥의 코드에 의해 호출이 가능하다.
this.variableName
객체 바깥에서 읽기와 쓰기가 가능하다.
Classname.prototype.methodName = function(){...}
그리고 객체의 바깥에서 호출될수 있다.
Classname.prototype.propertyName = someValue
Classname.propertyName = someValue
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.
function Person(n,race){ this.constructor.population++; // ************************************************************************ // PRIVATE 변수와 함수 // PRIVELEGED 메소드만 보기,수정,호출이 가능하다. // *********************************************************************** var alive=true, age=1; var maxAge=70+Math.round(Math.random()*15)+Math.round(Math.random()*15); function makeOlder(){ return alive = (++age <= maxAge) } var myName=n?n:"John Doe"; var weight=1; // ************************************************************************ // PRIVILEGED 메소드 // 어디서든 호출할수 있고 PRIVATE ITEMS에 접근이 가능하다 // PUBLIC FLAVORS와 함께 변경될수 있다 // ************************************************************************ this.toString=this.getName=function(){ return myName } this.eat=function(){ if (makeOlder()){ this.dirtFactor++; return weight*=3; } else alert(myName+" 는 먹을수 없습니다, 그는 죽었습니다!"); } this.exercise=function(){ if (makeOlder()){ this.dirtFactor++; return weight/=2; } else alert(myName+" 는 운동할수 없습니다, 그는 죽었습니다!"); } this.weigh=function(){ return weight } this.getRace=function(){ return race } this.getAge=function(){ return age } this.muchTimePasses=function(){ age+=50; this.dirtFactor=10; } // ************************************************************************ // PUBLIC 속성 -- 누구든 읽고 쓸수 있다 // ************************************************************************ this.clothing="아무것도입지않음"; this.dirtFactor=0; } // ************************************************************************ // PUBLIC 메소드 -- 누구든 읽고 쓸수 있다 // ************************************************************************ Person.prototype.beCool = function(){ this.clothing="검은 셔츠" } Person.prototype.shower = function(){ this.dirtFactor=2 } Person.prototype.showLegs = function(){ alert(this+" 는 다리가 "+this.legs+" 개 입니다") } Person.prototype.amputate = function(){ this.legs-- } // ************************************************************************ // PROTOTYOPE 속성 -- 누구든 읽고 쓸수 있다 (overridden 할수 없습니다) // ************************************************************************ Person.prototype.legs=2; // ************************************************************************ // STATIC 속성 -- 누구든 읽고 쓸수 있다 // ************************************************************************ Person.population = 0; // Person 클래스를 사용한 코드 function RunGavinsLife(){ var gk=new Person("Gavin","caucasian"); // Person 객체의 인스턴스를 생성 var lk=new Person("Lisa","caucasian"); // Person 객체의 인스턴스를 생성 alert("현재 "+Person.population+" 명의 사람이 있습니다"); gk.showLegs(); lk.showLegs(); // 'this.legs'를 참조할때 모두 'Person.prototype.legs' 변수를 공유한다 gk.race = "hispanic"; // 값을 변경하려고 해도 private 'race' 변수는 overwrite 되지 않는다. alert(gk+"'의 인종은 "+gk.getRace()+" 입니다"); // 인스턴스 생성시에 지정된 private 'race' 변수로부터 'caucasian'을 리턴한다 gk.eat(); gk.eat(); gk.eat(); // 몸무게는 3... 9... 27 alert(gk+" 는 "+gk.weigh()+" 파운드의 무게가 나가며 dirt factor 는 "+gk.dirtFactor + "입니다"); gk.exercise(); // 몸무게 13.5 gk.beCool(); // 옷이 새로운 것으로 변경됩니다. gk.clothing="Pimp Outfit"; // clothing 은 public 변수고 다른 값으로 변경이 가능합니다. gk.shower(); alert("현재의 샤워기술로 "+gk+" 의 dirt factor가 "+gk.dirtFactor + " 이 되었습니다"); gk.muchTimePasses(); //50년이 지남 Person.prototype.shower=function(){ //모두에게 샤워 기술이 향상됨 this.dirtFactor=0; } gk.beCool=function(){ //Gavin 은 혼자서 새로운 패션 아이디어를 얻었다. this.clothing="꽃남방"; }; gk.beCool(); gk.shower(); alert("패셔너블한 "+gk+" 는 " +gk.getAge()+" 살이고 지금 " +gk.clothing+" 를 입고있으며 dirt factor 는 " +gk.dirtFactor+"이다"); gk.amputate(); //prototype 메소드를 사용하여 public 속성을 만듭니다 gk.showLegs(); lk.showLegs(); //Lisa는 여전히 prototype 속성을 가지고 있다 gk.muchTimePasses(); //50년이 지나고... Gavin 은 현재 100살이 넘었다. gk.eat(); // 나이가 수명을 초과하였고 죽었기 때문에 먹을수 없다. }
alert(gk+' is so cool.')
to put the word 'Gavin' in there, and is equivalent to alert(gk.toString()+' is so cool.')
. Every object of every type in JS has a .toString() method, but you can override it with your own.gk.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 calling gk.amputate() only removed a leg from Gavin, but not Lisa.) To modify a prototype property, you must use Person.prototype.legs=1
or something like this.constructor.prototype.legs=1
. (I say 'something like' because I discovered that this.constructor is not available inside private functions of the object, since this refers to the window object in that scope.)foo = function(p1,p2){ some code }
new Function() 생성자와는 다르다. 예를 들어,
foo = new Function('p1','p2','code');
후자의 코드는 (생성자 함수의 scope을 상속받지 않고) 전역 scope에서 실행된다. 전자의 코드는 private 변수의 접근을 막아준다.
function StupidClass(){ var foo = "internal"; this.foo = "external"; this.yell=function(){ alert("Internal foo is "+foo+"\nExternal foo is "+this.foo) } }
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.