ES7 decorator 장식 자 모드

14188 단어
1. 장식 모드
디자인 모델 은 모두 가 알 고 있다. 인터넷 에는 많은 시리즈 튜 토리 얼 이 있다. 예 를 들 어 JS 디자인 모델 등등.
여기 장식 자 모드 그리고 ES7 을 어떻게 사용 하 는 지  decorator  콘 셉 트
1.1 장식 모드 v. s. 어댑터 모드
장식 모델 과 어댑터 모델 은 모두 '포장 모델' (Wrapper Pattern) 로 다른 대상 을 포장 하여 디자인 의 목적 을 달성 하지만 그들의 형 태 는 큰 차이 가 있다.
어댑터 모드 에서 우리 가 사용 하 는 장면 이 비교적 많다. 예 를 들 어 서로 다른 데이터 베 이 스 를 연결 하 는 경우 기 존의 모듈 인 터 페 이 스 를 포장 하여 데이터베이스 에 적합 하 게 해 야 한다. 예 를 들 어 핸드폰 이 인 터 페 이 스 를 사용 하여 콘센트 에 적합 하 게 하 는 것 과 같다.
장식 모델 이 다 르 기 때문에 기 존의 모듈 만 포장 하여 '더욱 화려 하 게' 하 는 것 은 기 존의 인터페이스의 기능 에 영향 을 주지 않 는 다. 예 를 들 어 핸드폰 에 케이스 를 추가 하 는 것 과 같이 핸드폰 기 존의 통화, 충전 등 기능 에 영향 을 주지 않 는 다. 
더 많은 차이 점 참조: 디자인 모델 - 장식 모델 (Decorator)
1.2 장식 모드 장면 - AOP 를 위 한 프로 그래 밍
장식 모델 의 전형 적 인 응용 은 AOP 프로 그래 밍 이다. 예 를 들 어 '로그 시스템' 이다. 로그 시스템 의 역할 은 시스템 의 행위 조작 을 기록 하 는 것 이다. 이 는 기 존의 시스템 의 기능 에 영향 을 주지 않 는 토대 에서 기록 절 차 를 추가 하 는 것 이다. 마치 스마트 팔찌 를 착용 한 것 처럼 일상생활 에 영향 을 주지 않 지만 지금 은 자신의 매일 행동 기록 을 가지 고 있다.
더욱 추상 적 인 이 해 는 데이터 흐름 을 한 층 filter 으로 이해 할 수 있 기 때문에 AOP 의 전형 적 인 응용 은 안전 검사, 캐 시, 디 버 깅, 지속 화 등 을 포함한다.Spring op 원리 및 각종 응용 장면 을 참고 할 수 있 습 니 다. 
2. ES7 의 decorator 사용
ES7 에 하나 추가 됐어 요.  decorator  속성 은 Python 에서 참고 합 니 다. 문장 Decorators in ES7 을 참고 하 십시오.
다음은 저희 가... 아 이언 맨 예 를 들 어 ES7 의 decorator 를 어떻게 사용 하 는 지 설명 합 니 다.
아 이언 맨 의 경우 아 이언 맨 은 본질 적 으로 한 사람 이다. 단지 많은 무 기 를 장식 하고 나 서 야 그렇게 NB 가 되 었 지만 아무리 장식 해도 그 는 한 사람 이다. 
우리 의 예시 장면 은 이렇다.
우선 일반 Man 클래스 를 만 듭 니 다. 저항 치 2, 공 격 력 3, 혈 액량 3;
그리고 우 리 는 그 에 게 아 이언 맨 의 갑옷 을 입 히 면 그의 저항력 이 100 증가 하여 102 가 된다.
광속 장갑 을 착용 하면 공 격 력 이 50 증가 하여 53 이 됩 니 다.
마지막 으로 그 에 게 '비행' 능력 을 증가 시 켰 다 .
2.1 、 【 데모 1 】 방법 에 대한 장식: 갑옷 착용
남자 클래스 만 들 기:
class Man{  
  constructor(def = 2,atk = 3,hp = 3){
    this.init(def,atk,hp);
  }

  init(def,atk,hp){
    this.def = def; //    
    this.atk = atk;  //    
    this.hp = hp;  //   
  }
  toString(){
    return `   :${this.def},   :${this.atk},  :${this.hp}`;
  }
}

var tony = new Man();

console.log(`     ===> ${tony}`); 

//   :     ===>    :2,   :3,  :3

코드 http://babeljs.io/repl/ 보기 결 과 를 실행 할 때 체크 Experimental 옵션 과 Evaluate 옵션 을 기억 하 십시오.
창설 decorateArmour 방법, 아 이언 맨 을 위 한 갑옷 조립 - 주의  decorateArmour  방법 init 에 장 식 된 것 입 니 다.
function decorateArmour(target, key, descriptor) {  
  const method = descriptor.value;
  let moreDef = 100;
  let ret;
  descriptor.value = (...args)=>{
    args[0] += moreDef;
    ret = method.apply(target, args);
    return ret;
  }
  return descriptor;
}

class Man{  
  constructor(def = 2,atk = 3,hp = 3){
    this.init(def,atk,hp);
  }

  @decorateArmour
  init(def,atk,hp){
    this.def = def; //    
    this.atk = atk;  //    
    this.hp = hp;  //   
  }
  toString(){
    return `   :${this.def},   :${this.atk},  :${this.hp}`;
  }
}

var tony = new Man();

console.log(`     ===> ${tony}`);  
//   :     ===>    :102,   :3,  :3

우리 가 먼저 수출 결 과 를 보 니 방 어 력 이 확실히 증가 했다. 100.. 갑옷 이 효과 가 있 나 봐 요.
초보 자 에 게 는 두 가지 의문 이 있다. - 1.  decorateArmour 방법의 매개 변 수 는 왜 이 세 개 입 니까?교체 가능 한 가요? -2. decorateArmour 방법 이 왜 돌아 오 는 지 descriptor여기에 개인의 해답 을 참고 로 한다.
Decorators 본질 적 으로 ES5 를 이 용 했 습 니 다. Object.defineProperty 속성, 이 세 개의 매개 변 수 는 사실 Object. defineProperty 매개 변수 와 일치 하기 때문에 변경 할 수 없습니다. 상세 한 분석 은 참조 하 십시오. 상세 설명 ES7 JavaScript Decorators 볼 수 있다 bable 변환 후 의 코드, 그 중 하 나 는 descriptor = decorator(target, key, descriptor) || descriptor; 입 니 다. 점 까지 상세 하 게 전개 되 지 않 았 습 니 다. 이 코드 의 문맥 (참고 문헌 에서 도 이 코드 의 해석 과 관련된다) 을 직접 볼 수 있 습 니 다.
2.2 、 【 데모 2 】 장식 기 중첩: 광속 장갑 증가
위의 예 에서 우 리 는 일반인 에 게 '갑옷' 이라는 장식 을 추가 하 는 데 성공 했다.지금 나 는 그 에 게 '광속 장갑' 을 더 해 주 고 싶 으 니, 추가 로 증가 하 기 를 바란다. 50 방어 치 를 찍다.
Step 1: 1 부 decorateArmour 방법 을 복사 하여 decorateLight 로 이름 을 바 꾸 고 방어 치 의 속성 을 수정 합 니 다.
function decorateLight(target, key, descriptor) {  
  const method = descriptor.value;
  let moreAtk = 50;
  let ret;
  descriptor.value = (...args)=>{
    args[1] += moreAtk;
    ret = method.apply(target, args);
    return ret;
  }
  return descriptor;
}

Step 2: init 방법 에 장식 문법 을 직접 추가 합 니 다.
....
  @decorateArmour
  @decorateLight
  init(def,atk,hp){
    this.def = def; //    
    this.atk = atk;  //    
    this.hp = hp;  //   
  }
 ...

마지막 코드 는 다음 과 같 습 니 다.
...
function decorateLight(target, key, descriptor) {  
  const method = descriptor.value;
  let moreAtk = 50;
  let ret;
  descriptor.value = (...args)=>{
    args[1] += moreAtk;
    ret = method.apply(target, args);
    return ret;
  }
  return descriptor;
}

class Man{  
  constructor(def = 2,atk = 3,hp = 3){
    this.init(def,atk,hp);
  }

  @decorateArmour
  @decorateLight
  init(def,atk,hp){
    this.def = def; //    
    this.atk = atk;  //    
    this.hp = hp;  //   
  }
...
}
var tony = new Man();  
console.log(`     ===> ${tony}`);  
//  :     ===>    :102,   :53,  :3

여기 서 장식 모델 의 장점 을 알 수 있다. 이 는 특정한 방법 을 중첩 하여 사용 할 수 있 고 원래 의 침입 성 이 매우 작 으 며 한 줄 @decorateLight 만 증가 할 뿐 편리 하 게 삭제 할 수 있다.(동시에 재 활용 가능)
2.3 、 【 데모 3 】 유형 별 장식: 비행 능력 증가
문장 에 따르다 장식 모델 에서 말 한 것 처럼 장식 모델 은 두 가지 가 있다. 순수한 장식 모델 이다. 화해시키다 반투명 장식 패턴.
상기 두 데모 에서 사용 한 것 은 순수한 장식 모드 는 기 존의 인 터 페 이 스 를 증가 시 키 지 않 습 니 다.다음은 demo 는 일반인 에 게 '비행' 능력 을 증가 시 키 는 것 으로 클래스 에 새로운 방법 을 추가 하 는 것 과 같다. 반투명 장식 모드 로 어댑터 모드 같 아 요.
Step 1: 방법 추가:
function addFly(canFly){  
  return function(target){
    target.canFly = canFly;
    let extra = canFly ? '(    :    )' : '';
    let method = target.prototype.toString;
    target.prototype.toString = (...args)=>{
      return method.apply(target.prototype,args) + extra;
    }
    return target;
  }
}

Step 2: 이 방법 은 직접 장식 류 를 제거 합 니 다.
...

// 3
function addFly(canFly){  
  return function(target){
    target.canFly = canFly;
    let extra = canFly ? '(    :    )' : '';
    let method = target.prototype.toString;
    target.prototype.toString = (...args)=>{
      return method.apply(target.prototype,args) + extra;
    }
    return target;
  }
}

@addFly(true)
class Man{  
  constructor(def = 2,atk = 3,hp = 3){
    this.init(def,atk,hp);
  }

  @decorateArmour
  @decorateLight
  init(def,atk,hp){
    this.def = def; //    
    this.atk = atk;  //    
    this.hp = hp;  //   
  }
  ...
}
...

console.log(`     ===> ${tony}`);  
//   :     ===>    :102,   :53,  :3(    :    )

방법 적  decorator  받 은 첫 번 째 인자 (target )클래스  prototype; 하 나 를 decorator 클래스 에 작용 하면 첫 번 째 매개 변 수 는 target 입 니 다. 클래스 자체. Decorators in ES7 )
3. 원생 JS 를 사용 하여 장식 기 모드 구현
기 존 기준의 원생 JS 로 어떻게 장식 하 는 지 에 대해 서 는 번역문 을 참고 할 수 있다. JavaScript 디자인 모델: 장식 자 모델, 이것 은 읽 을 만 한 글 입 니 다.
여기 서 ES5 로 위의 데모 1 장면 을 다시 쓰 고 중요 한 점 을 간략하게 말씀 드 리 겠 습 니 다.
남자 겨냥 하 다 Man 의 인 테 리 어 기본 클래스 구체 적 인 장식 류 DecorateArmour 전형 적 으로 사용 하 다 prototype 계승 방식 잇다 Decorator 기본 클래스; 기초 하 다 IOC 사상 ,Decorator 받다 Man 클래스, 자신 이 만 든 것 이 아 닙 니 다. Man 클래스; 마지막 코드 는:
//            
function Man(){

  this.def = 2;
  this.atk = 3; 
  this.hp = 3;
}

//             ,  Man   
Man.prototype={  
  toString:function(){
    return `   :${this.def},   :${this.atk},  :${this.hp}`;
  }
}
//      ,  Man      。
var Decorator = function(man){  
  this.man = man;
}

//              
Decorator.prototype.toString = function(){  
    return this.man.toString();
}

//         
//         ,    Man    
var DecorateArmour = function(man){

  var moreDef = 100;
  man.def += moreDef;
  Decorator.call(this,man);

}
DecorateArmour.prototype = new Decorator();

//                      ,      ,         。
DecorateArmour.prototype.toString = function(){  
  return this.man.toString();
} 

//          
//       “   ”,     
var tony = new Man();  
tony = new DecorateArmour(tony);  
console.log(`     ===> ${tony}`);  
//   :     ===>    :102,   :3,  :3

4. 고전 실현: Logger
AOP 의 대표 적 인 앱 은 바로... 로그 시스템 자, 그럼 우리 도 ES7 문법 으로 아 이언 맨 에 게 로그 시스템 을 만들어 주자.
다음은 최종 코드 입 니 다.
/**
 * Created by jscon on 15/10/16.
 */
let log = (type) => {

  return (target, name, descriptor) => {
    const method = descriptor.value;
    descriptor.value =  (...args) => {
      console.info(`(${type})     : ${name}(${args}) = ?`);
      let ret;
      try {
        ret = method.apply(target, args);
        console.info(`(${type})    : ${name}(${args}) => ${ret}`);
      } catch (error) {
        console.error(`(${type})   : ${name}(${args}) => ${error}`);
      }
      return ret;
    }
  }
}
class IronMan {  
  @log('IronMan     ')
  check(){
    return '    ';
  }
  @log('IronMan     ')
  attack(){
    return '    ';
  }
  @log('IronMan     ')
  error(){
    throw 'Something is wrong!';
  }
}

var tony = new IronMan();  
tony.check();  
tony.attack();  
tony.error();

//   :
// (IronMan     )     : check() = ?
// (IronMan     )    : check() =>     
// (IronMan     )     : attack() = ?
// (IronMan     )    : attack() =>     
// (IronMan     )     : error() = ?
// (IronMan     )   : error() => Something is wrong!

Logger 방법의 관건 은: - 우선 사용  const method = descriptor.value;  기 존 방법 을 추출 하여 기 존 방법의 청정 을 보장 합 니 다. - 네. try..catch 호출  ret = method.apply(target, args); 호출 전에 각각 로그 보고 하기; - 마지막 으로 되 돌려 주기  return ret;  원본 호출 결과
이 사고방식 이 후속 적 으로 AOP 모델 을 실현 하 는 데 좋 은 참고 가 될 것 이 라 고 믿는다.
5. 확장
5.1 공장 모델 기반
세 가지 기능 을 가 진 아 이언 맨 을 원한 다 면 사용 해 야 한다. new 연산 자 4 개의 대상 을 만 듭 니 다. 이렇게 하면 단 조 롭 고 지루 하기 때문에 우 리 는 한 가지 방법 만 사용 하면 모든 기능 을 가 진 아 이언 맨 을 만 들 수 있 습 니 다.
그게 필요 해. 공장 모드 공장 모델 의 공식 정 의 는 하위 클래스 에서 하나의 구성원 대상 을 예화 하 는 것 이다. 예 를 들 어 정의 하 는 것 이다. decorateIronMan(person,feature) 방법 Person 대상 (자신 이 초기 화 하 는 것 이 아니 라) 은 유수 선 생산 에 해당 한다.
어떻게 장식 모델 과 공장 모델 을 결합 하 다. 코드 효능 향상, 이 우수한 번역문 JavaScript 디자인 모델: 공장 모델 은 상세 한 방법 을 제 시 했 습 니 다. 여 기 는 더 이상 군말 하지 않 고 이 글 을 읽 는 것 을 강력 히 추천 합 니 다.
5.2、pure-render-decorator
React 성능 최적화 시 중복 렌 더 링 을 피 하 는 큰 방법 이 있 습 니 다. 바로 사용 하 는 것 입 니 다.  shouldComponentUpdate() 불필요 한 재 렌 더 링 을 피 할 수 있 습 니 다. 차용 Immutable 은 성능 을 크게 향상 시 킬 수 있 습 니 다. 공식 React.addons.PureRenderMixin 을 직접 사용 하거나 Pure - render - decorator 를 사용 할 수 있 습 니 다. 바로 ES7 Decorator 을 사용 한 것 입 니 다.
import {Component} from 'react';  
import pureRender from 'pure-render-decorator';

@pureRender
class Test extends Component {  
  render() {
    return 
; } }

等效于:

var React = require('react');  
var PureRenderMixin = require('react-addons-pure-render-mixin');

var Test = React.createClass({  
  mixins: [
    PureRenderMixin
  ],

  render: function() {
    return 
; } });

6、现在就想用?

decorator 目前还只是一个提议,但是感谢 Babel ,我们现在就可以体验它了。首先,安装babel

npm install babel -g  

그리고 decorator:
babel --optional es7.decorators foo.js > foo.es5.js  

babel 도 온라인 REPL 을 제공 합 니 다. ,뽑다 experimental 옵션 을 선택 하면 됩 니 다.
웹 storm 에 babel 설정
Step 1: 우선 전역 설치 babel 구성 요소 모듈
npm install -g babel  

Step 2: scope 설정 (이 단 계 는 생략 할 수 있 습 니 다)
이름 scope:
현재 scope 에 파일 추가: 
단계 3: ES 버 전 설정
단계 4: watcher 추가
arguments 에 기입 할 수 있 습 니 다: $FilePathRelativeToProjectRoot$ --stage --out-file $FileNameWithoutExtension$-es5.js $FilePath$.
source - map 가 필요 하 다 면 --source-map 옵션 을 추가 하고 Output paths to refresh 에 작성 해 야 합 니 다 $FileNameWithoutExtension$-es5.js:$FileNameWithoutExtension$-es5.js.map더 많은 설정 참조 babel cli
7. 총화
ES7 의 특성 이지 만 Babel 대세 가 유행 하 는 오늘날 우 리 는 Babel 을 이용 하여 사용 할 수 있 습 니 다. Babel 명령 행 도구 나 grunt, gulp, webpack 의 babel 플러그 인 을 이용 하여 Decorators 를 사용 할 수 있 습 니 다.
상술 한 코드 는 모두 직접 놓 을 수 있다. http://babeljs.io/repl/ 결과 보기 실행 하기;
ES7 Decorators 의 더 재 미 있 는 게임 방법 에 대해 서 는 소 가 자주 사용 하 는 것 을 참조 할 수 있 습 니 다. Decorators: core - decorators. 어떻게 Decorators 로 Mixin 을 실현 합 니까?
참고 문헌
Decorators in ES7: 장식 자 모드 는 기 존의 방법 을 포장 하여 기 존 함 수 를 확장 합 니 다. JavaScript 디자인 모델: 장식 자 모델: 심각 한 추천 입 니 다. 이 시 리 즈 는 디자인 모델 이 JS 에서 의 응용 을 잘 알 게 해 줍 니 다. ES7 의 Decorators 는 AOP 예 시 를 실현 합 니 다. 간단 한 AOP 를 어떻게 실현 합 니까? ES7 JavaScript Decorators: ES7 Decorator 의 배후 원 리 를 설명 하 는 것 은 Object. defineProperty 방법 을 사용 한 것 이다. WebStorm 에서 Babel 플러그 인 을 설정 하 는 방법: 그림 과 글 이 모두 훌륭 합 니 다. babel 을 설정 하 는 방법 을 알려 드 립 니 다. Rest 매개 변수 와 매개 변수 기본 값: ES6 는 가 변 매개 변수 함수, Rest 매개 변수 와 매개 변수 기본 값 을 만 드 는 새로운 방식 을 제공 합 니 다.
Exploring ES 2016 Decorators: 아주 완전한 튜 토리 얼 입 니 다. 그 안에 전면적 인 내용 이 포함 되 어 있 습 니 다. Traits with ES7 Decorators: 소개  traits-decorator  모듈;

좋은 웹페이지 즐겨찾기