윤제니

JavaScript - 생성자 함수, this, Object 객체, 클로저(closure) 본문

JavaScript/JavaScript

JavaScript - 생성자 함수, this, Object 객체, 클로저(closure)

꿈다루 2020. 5. 4. 02:42

생성자 함수(constructor)

  • '생성자함수'를 통해 생성된 객체  =>  '인스턴스'
  • '생성자함수'를 이용하여 객체를 복사('인스턴스')하여 사용하는 방법
  • 프로토타입을 만들 때 사용하는 함수 (new로 객체가 생성될 때 호출되는 함수이기 때문)

 1) 형식과 인스턴스 생성법

  • 객체의 '인스턴스'는 new 연산자와 '생성자함수'를 통하여 생성 가능 
  • '생성자함수' : 일반적인 함수의 형식과 동일하지만 사용 용도가 다르므로 일반 함수와 차이를 두기 위해 함수명이나 변수명첫글자는  대문자로 사용 
선언적함수 형식으로 정의하는 방법 익명함수 형식으로 정의하는 방법

function Circle(c, d) {

   this.color = c;

   this.diameter = d;

   this.radius = function (n) {

   var r = n / 2;

   return n;

  }

}

 

var red_circle = new Circle("red", 100);

 

var Circle=function() {

   this.color = c;

   this.diameter = d;

   this.radius = function (n) {

   var r = n / 2;

   return n;

  }

 

var red_circle = new Circle("red",100);

 설명) Circle() 함수와 new연산자를 통해 생성된 'red_circle 객체'와 'blue_circle 객체'는 생성자함수 Circle() 안의 

          모든 속성과 메서드들을 상속받는다. 따라서 객체가 생성될 때마다 '생성자함수' 안의 모든 속성과 메서드들은 

          새로 생성된 객체의 것으로 인식해야 한다. 그렇기 때문에 'this'라는 키워드를 사용 

          '생성자함수' 안의 this는 '생성자함수'에 의해 만들어지는 객체(인스턴스) 자신을 의미

 

 2) this 키워드

var a=10;
function obj() {
   var a=20;
   console.log(this.a);
}

obj();  // 10

 => 여기서 this의 의미 : window 객체 (객체를 만든 것도 아니고, '생성자함수'로 인스턴스를 생성하지도 않는다.)

 

var circle = { color: "red" };
var r = function () {
  console.log(this.color);
}
r();

 => circle을 객체로 만들고 속성으로 color을 정의  

      r함수 안의 this가 'window 객체'를 의미 

      첫번째 줄에 정의되어 있는 color는 circle 객체의 속성 , window 객체의 속성이 아니다. 

      현재 window 객체에 대한 color 속성이 정의되지 않은 상태이므로 'undefined'를 출력 

     

* this가 window 객체가 아닌 circle 객체가 되도록 변경 * 

var circle = { color: "red" };
var r = function () {
  console.log(this.color);
}

circle.w = r;
circle.w();

 => circle객체에 w 속성을 추가하고 r함수를 저장하게 되면 circle.w()는 아래와 같은 메서드가 된다. 

      this는 'window 객체'가 아닌 circle 객체'를 출력. 

circle.w = function () {
  console.log(this.color);
}

 

 

 3) 인스턴스의 속성, 메서드 추가

  • 새로 생성된 객체(인스턴스)는 필요에 따라 속성과 메서드를 추가, 삭제 가능
  • '인스턴스'에 속성이나 메서드를 추가, 삭제하는 방법객체에 동적으로 속성이나 메서드를 추가 삭제하는 방법과 동일 

 => 단, red_circle 객체에 추가된 속성과 메서드는 red_circle 객체에서만 사용할 수 있고 다른 인스턴스에 사용 불가능 

 

 4) 객체의 프로토타입 속성

      : 동일한 메서드를 '생성자함수'에 포함시키지 않고 외부에 만들어 놓은 뒤 '인스턴스'에서 필요할 때만 호출해서 사용     

         => 메서드 하나로 처리  => 메서드들을 '생성자함수'에 포함시키지 않고 외부에서 만들 수 있는 방법  =>  '프로토타입'

      : ex) 붕어빵 => 객체 / 붕어빵을 찍어내는 틀 => 프로토타입 

              new 연산자프로토타입으로부터 객체를 찍어내도록 하는 명령 

객체명.propertype.메서드 = function() {
   실행문;
}

 

 ' 프로토타입'을 여러 개 만들어야 할 경우 객체 리터럴로 정의 가능 

객체명.propertype=function() {
  메서드:function(){실행문;},
  메서드:function(){실행문;},
}

 

 

5) Object 객체

    : Object 객체는 '내장객체'와 '사용자 정의 객체'의 기본 객체 

      Object 객체의 메서드들모든 객체에서 공통으로 사용 가능 

 

  • Object 객체 프로퍼티(속성)
속성 설명
constructor

* 인스턴스를 생성하는 '생성자함수'를 반환

* var str="string"  ->  str은 String 객체의 '인스턴스' str.constructor

   ->  인스턴스 str 객체의 생성자 함수를 반환 

   function String() {[native code]}

 

* var num=10  ->  num은 Number 객체의 '인스턴스' num.constructor

   ->  인스턴스 num 객체의 생성자 함수를 반환

   function Number() {[native code]}

 

메서드 설명
hasOwnProperty()

* hasOwnProperty("length")일 때 length 속성이 객체에 존재하는지 검사하여 

   존재하면 true, 존재하지 않으면 false 반환

 

*  var str="string"

    str.hasOwnProperty("length")  ->  true

propertyIsEnumerable()

*  propertyIsEnumerable("sub")일 때 sub 속성을 반복문으로 열거할 수 있는지를  

   검사하여 열거할 수 있으면 true, 없으면 false 반환

 

*  var subject={sub:"Javascript"}

    subject.propertyIsEnumerable("sub")  ->  true

isPropertypeOf()

*  isPrototypeOf(obj)일 때 obj 객체가 지정한 객체의 프로토타입이면 true, 아니면 false 반환

*  var subject=["Javascript","jQuery"]

    Array.propertype.isPrototypeOf(subject)  ->  true

★  toString()

*  객체의 값을 문자열로 반환

*  var subject = ["Javascript","jQuery"]

   subject.toString()  ->  "Javascript,jQuery"

★  valueOf()

*  객체의 값을 반환

*  var num=10

    num.valueOf()  ->  10 

 

 

 6) 클로저(Closure)

     : '지역 변수'는 함수 안에서만 한정적으로 사용되는 변수이기 때문에 함수의 실행이 끝나면 지역변수도 사라진다.

        but, 함수의 실행이 끝난 뒤에도 지역변수를 계속 유지시킬 수 있는 방법, 지역변수의 값을 계속 유지하면서 사용 가능  =>  '클로저'

 

* 클로저를 사용하지 않은 방법 *

  => a, b 변수에 각각 closure 함수를 저장하여 a, b 변수를 함수로 작성 

       closure 함수 안의 n 변수는 '지역변수'이기 때문에 함수의 실행이 끝나면 변수는 사라진다. (함수 실행할 때마다 변수 초기화)

 해결 ) closure 함수 안에 익명함수를 만들어 리턴해 주면 n 변수가 초기화 되지 않고 현재의 변수값을 계속 저장하여 연산 가능 

function closure(n) {
  return ++n;
}

var a = closure;
console.log(a(10));  // 11

var b = closure;
console.log(b(20));  // 21

console.log(a(10));  // 11

 
 *  클로저를 사용하는 방법 *

  => '생성자함수' 처럼 여러 개의 속성과 메서드를 처리할 수 없고 단순히 변수 하나만을 처리하는 객체 

        익명함수를 리턴하는 명령이 없다면 'var a=closure(10)' 과 'var b=closure(20)'은 함수 호출 형태가 되므로 사용 불가 

function closure(n) {
  return function () {
    return ++n;
  };
}

var a = closure(10);
console.log(a());    // 11
console.log(a());    // 12

var b = closure(20);
console.log(b());    // 21
console.log(b());    // 22