JS 일부 특수 지식 점 (7) - 구조 함수 및 대상 지향 모델

구조 함수 와 new 명령
new 명령 의 원리new 명령 을 사용 할 때 그 뒤의 함 수 는 다음 절 차 를 순서대로 실행 합 니 다.
돌아 올 대상 의 인 스 턴 스 로 빈 대상 을 만 듭 니 다.
이 빈 대상 의 원형 을 구조 함수 prototype 속성 을 가리킨다.
이 빈 대상 을 함수 내부 의 this 키워드 에 할당 합 니 다.
구조 함수 내부 코드 를 실행 하기 시작 합 니 다.
new.target
함수 내부 에서 new.target 속성 을 사용 할 수 있 습 니 다.현재 함수 가 new 명령 호출 이 라면 new.target 현재 함 수 를 가리 키 고 그렇지 않 으 면 undefined 입 니 다.
function f() {
  console.log(new.target === f);
}

f() // false
new f() // true

이 속성 을 사용 하면 함수 호출 시 new 명령 을 사용 할 지 여 부 를 판단 할 수 있 습 니 다.
function f() {
  if (!new.target) {
    throw new Error('    new     !');
  }
  // ...
}

f() // Uncaught Error:     new     !

이 절 은 자 바스 크 립 트 언어의 실제 프로 그래 밍 에서 대상 을 대상 으로 프로 그래 밍 하 는 일부 모델 을 소개 한다.
구조 함수 의 계승
하나의 구조 함수 로 하여 금 다른 구조 함 수 를 계승 하 게 하 는 것 은 매우 흔히 볼 수 있 는 수요 이다.
이것 은 두 단계 로 나 누 어 실현 할 수 있다.첫 번 째 단 계 는 하위 클래스 의 구조 함수 에서 부모 클래스 의 구조 함 수 를 호출 하 는 것 이다.
function Sub(value) {
  Super.call(this);
  this.prop = value;
}

위의 코드 에서 Sub 는 하위 클래스 의 구조 함수 이 고 this 는 하위 클래스 의 인 스 턴 스 입 니 다.인 스 턴 스 에서 부모 클래스 의 구조 함수 Super 를 호출 하면 하위 클래스 인 스 턴 스 가 부모 클래스 인 스 턴 스 의 속성 을 가지 게 됩 니 다.
두 번 째 단 계 는 자 류 의 원형 이 아버지 류 의 원형 을 가리 키 게 하 는 것 이다. 이런 유형 은 아버지 류 의 원형 을 계승 할 수 있다.
Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
Sub.prototype.method = '...';

위의 코드 에서 Sub.prototype 는 하위 클래스 의 원형 으로 직접 Object.create(Super.prototype) 가 아니 라 Super.prototype 로 할당 해 야 합 니 다.그렇지 않 으 면 뒤의 두 줄 Sub.prototype 에 대한 조작 은 아버지 류 의 원형 Super.prototype 과 함께 수정 된다.
또 다른 문법 은 Sub.prototype 부계 실례 와 같다.
Sub.prototype = new Super();

위의 이런 문법 도 계승 하 는 효과 가 있 지만 자 류 는 부류 의 실례 를 가 진 방법 이 있다.때때로 이것 은 우리 가 필요 로 하 는 것 이 아 닐 수도 있 기 때문에 이런 문법 을 사용 하 는 것 을 추천 하지 않 는 다.
예 를 들 어 다음은 구조 함수 이다.
function Shape() {
  this.x = 0;
  this.y = 0;
}

Shape.prototype.move = function (x, y) {
  this.x += x;
  this.y += y;
  console.info('Shape moved.');
};

우 리 는 Shape 구조 함수 계승 Rectangle 을 필요 로 한다.
//    ,         
function Rectangle() {
  Shape.call(this); //         
}
//      
function Rectangle() {
  this.base = Shape;
  this.base();
}

//    ,         
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;

이러한 서법 을 사용 한 후에 Shape 연산 자 는 하위 클래스 와 부모 클래스 의 구조 함수 에 대해 모두 되 돌려 줍 니 다 instanceof.
var rect = new Rectangle();
rect.move(1, 1) // 'Shape moved.'

rect instanceof Rectangle  // true
rect instanceof Shape  // true

위의 코드 에서 자 류 는 전체 계승 부류 이다.때로는 하나의 방법의 계승 만 필요 할 때 아래 의 서법 을 채택 할 수 있다.
ClassB.prototype.print = function() {
  ClassA.prototype.print.call(this);
  // some code
}

위의 코드 에서 하위 클래스 trueB 방법 은 먼저 부모 클래스 printA 방법 을 호출 한 다음 에 자신의 코드 를 배치 합 니 다.부계 printA 방법 을 물 려 받 은 셈 이다.
다 중 상속
자 바스 크 립 트 는 한 대상 이 여러 대상 을 동시에 계승 할 수 없 도록 다 중 계승 기능 을 제공 하지 않 습 니 다.하지만 변 칙 적 인 방법 을 통 해 이 기능 을 실현 할 수 있다.
function M1() {
  this.hello = 'hello';
}

function M2() {
  this.world = 'world';
}

function S() {
  M1.call(this);
  M2.call(this);
}

//    M1
S.prototype = Object.create(M1.prototype);
//        M2
Object.assign(S.prototype, M2.prototype);

//       
S.prototype.constructor = S;

var s = new S();
s.hello // 'hello:'
s.world // 'world'

상기 코드 에서 하위 클래스 print 는 부모 클래스 SM1 를 동시에 계승 했다.이런 모델 을 Mixin (혼합) 이 라 고도 부른다.
모듈
사이트 가 점차 '인터넷 응용 프로그램' 으로 변 함 에 따라 웹 페이지 에 삽 입 된 자 바스 크 립 트 코드 는 갈수 록 방대 해 지고 복잡 해진 다.웹 페이지 는 점점 데스크 톱 프로그램 과 같 아 지고 있 습 니 다. 팀 분업 협력, 진도 관리, 유닛 테스트 등 이 필요 합 니 다. 개발 자 는 소프트웨어 공학 의 방법 을 사용 하여 웹 페이지 의 업무 논 리 를 관리 해 야 합 니 다.
JavaScript 모듈 화 프로 그래 밍 은 이미 절실 한 수요 가 되 었 다.이상 적 인 상황 에서 개발 자 는 핵심 적 인 업무 논리 만 실현 하고 다른 사람들 이 이미 작성 한 모듈 을 불 러 올 수 있 습 니 다.
그러나 자 바스 크 립 트 는 모듈 화 프로 그래 밍 언어 가 아니 라 ES5 는 '클래스' (class) 를 지원 하지 않 으 며 '모듈' (module) 을 논 할 필요 가 없다.ES6 는 '클래스' 와 '모듈' 을 공식 적 으로 지원 하지만 아직 주류 가 되 지 는 않 았 다.자 바스 크 립 트 커 뮤 니 티 는 기 존의 운영 환경 에서 모듈 의 효 과 를 실현 하기 위해 많은 노력 을 기 울 였 다.
기본 적 실현 방법
모듈 은 특정 기능 을 실현 하 는 속성 과 방법의 패키지 이다.
서로 다른 함수 (그리고 상 태 를 기록 하 는 변수) 를 간단하게 함께 놓 으 면 하나의 모듈 이 라 고 할 수 있다.
function m1() {
  //...
}

function m2() {
  //...
}

위의 함수 m1 () 과 m2 () 는 하나의 모듈 을 구성한다.사용 할 때 직접 호출 하면 됩 니 다.
이런 방법의 단점 은 매우 뚜렷 하 다. '전체 변 수 를 오염 시 켰 기 때문에 다른 모듈 과 변수 명 충돌 이 발생 하지 않 고 모듈 구성원 간 에 직접적인 관 계 를 볼 수 없다.
위의 단점 을 해결 하기 위해 모듈 을 하나의 대상 으로 쓸 수 있 고 모든 모듈 구성원 이 이 대상 에 넣 을 수 있다.
var module1 = new Object({
 _count : 0,
 m1 : function (){
  //...
 },
 m2 : function (){
   //...
 }
});

위의 함수 M2m1 는 모두 m2 대상 에 밀봉 되 어 있다.사용 할 때 이 대상 의 속성 을 호출 합 니 다.
module1.m1();

그러나 이런 표기 법 은 모든 모듈 구성원 을 폭로 하고 내부 상 태 는 외부 에서 고 칠 수 있다.예 를 들 어 외부 코드 는 내부 카운터 의 값 을 직접 바 꿀 수 있다.
module1._count = 5;

패키지 개인 변수: 구조 함수 의 쓰기
우 리 는 구조 함 수 를 이용 하여 사유 변 수 를 봉인 할 수 있다.
function StringBuilder() {
  var buffer = [];

  this.add = function (str) {
     buffer.push(str);
  };

  this.toString = function () {
    return buffer.join('');
  };

}

이런 방법 은 사유 변 수 를 구조 함수 에 봉 하여 구조 함수 와 실례 대상 이 분리 되 는 원칙 을 위반 했다.그리고 메모 리 를 많이 쓴다.
function StringBuilder() {
  this._buffer = [];
}

StringBuilder.prototype = {
  constructor: StringBuilder,
  add: function (str) {
    this._buffer.push(str);
  },
  toString: function () {
    return this._buffer.join('');
  }
};

이러한 방법 은 개인 변 수 를 인 스 턴 스 대상 에 넣 으 면 더욱 자 연 스 러 워 보이 지만 개인 변 수 는 외부 에서 읽 고 쓸 수 있어 안전 하지 않다.
패키지 개인 변수: 함수 쓰기 즉시 실행
"즉시 실행 함수" (Immediately - Invoked Function Expression, IIFE) 를 사용 하여 관련 속성 과 방법 을 함수 역할 영역 에 밀봉 하면 개인 구성원 이 노출 되 지 않 는 목적 을 달성 할 수 있 습 니 다.
var module1 = (function () {
 var _count = 0;
 var m1 = function () {
   //...
 };
 var m2 = function () {
  //...
 };
 return {
  m1 : m1,
  m2 : m2
 };
})();

위의 쓰기 방법 을 사용 하면 외부 코드 는 내부 의 module1 변 수 를 읽 을 수 없습니다.
console.info(module1._count); //undefined

위의 _count 는 자바 스 크 립 트 모듈 의 기본 적 인 쓰기 입 니 다.다음은 이런 표기 법 을 가공 하 겠 습 니 다.
모듈 의 증폭 모드
만약 에 하나의 모듈 이 매우 크다 면 반드시 몇 부분 으로 나 누 어야 하거나 하나의 모듈 이 다른 모듈 을 계승 해 야 한다. 이때 '확대 모드' (augmentation) 를 사용 할 필요 가 있다.
var module1 = (function (mod){
 mod.m3 = function () {
  //...
 };
 return mod;
})(module1);

위의 코드 는 module1 모듈 에 새로운 방법 module1 을 추가 한 다음 에 새로운 m3() 모듈 로 돌아 갑 니 다.
브 라 우 저 환경 에서 모듈 의 각 부분 은 보통 인터넷 에서 가 져 오 는데 어떤 부분 이 먼저 불 러 올 지 알 수 없습니다.위의 쓰기 방법 을 사용 하면 첫 번 째 로 실 행 된 부분 에 빈 대상 이 없 는 것 을 불 러 올 수 있 습 니 다. 이 때 는 '넓 은 확대 모드' (Loose augmentation) 를 사용 해 야 합 니 다.
var module1 = ( function (mod){
 //...
 return mod;
})(window.module1 || {});

'확대 모드' 에 비해 '넓 은 확대 모드' 는 '즉시 실행 함수' 의 매개 변 수 는 빈 대상 일 수 있 습 니 다.
전역 변수 입력
독립 성 은 모듈 의 중요 한 특징 으로 모듈 내 부 는 프로그램의 다른 부분 과 직접 상호작용 하지 않 는 것 이 가장 좋다.
모듈 내부 에서 전역 변 수 를 호출 하기 위해 서 는 다른 변 수 를 모듈 에 명시 적 으로 입력 해 야 합 니 다.
var module1 = (function ($, YAHOO) {
 //...
})(jQuery, YAHOO);

위의 module1 모듈 은 jQuery 라 이브 러 리 와 YUI 라 이브 러 리 를 사용 해 야 합 니 다. 이 두 라 이브 러 리 (사실은 두 모듈) 를 매개 변수 로 입력 하 십시오 module1.이렇게 하면 모듈 의 독립 성 을 확보 하 는 동시에 모듈 간 의 의존 관 계 를 뚜렷하게 한다.
함 수 를 즉시 실행 하면 네 임 스페이스 의 역할 도 할 수 있다.
(function($, window, document) {

  function go(num) {
  }

  function handleEvents() {
  }

  function initialize() {
  }

  function dieCarouselDie() {
  }

  //attach to the global scope
  window.finalCarousel = {
    init : initialize,
    destroy : dieCouraselDie
  }

})( jQuery, window, document );

상기 코드 에서 module1 대상 이 전체 로 수출 되 고 대외 노출 finalCarouselinit 인터페이스, 내부 방법 destroy, go, handleEvents, initialize 은 모두 외부 에서 호출 할 수 없다.
참조 링크
JavaScript Modules: A Beginner’s Guide, by Preethi Kasireddy

좋은 웹페이지 즐겨찾기