>  기사  >  웹 프론트엔드  >  JavaScript 디자인 패턴 배우기 - 데코레이터 패턴_javascript 기술

JavaScript 디자인 패턴 배우기 - 데코레이터 패턴_javascript 기술

WBOY
WBOY원래의
2016-05-16 15:19:191273검색

때때로 우리는 클래스가 본질적으로 규모가 크고 동시에 많은 책임을 포함하는 것을 원하지 않습니다. 그런 다음 장식된 패턴을 사용할 수 있습니다.
데코레이터 패턴은 이 클래스에서 파생된 다른 개체에 영향을 주지 않고 개체에 일부 추가 책임을 동적으로 추가할 수 있습니다.
장식된 패턴은 하나의 물체를 다른 물체에 삽입하는데, 이는 실제로 이 물체가 다른 물체에 의해 포장되어 포장 체인을 형성하는 것과 같습니다.

1. 원래 기능을 변경하지 않고 기능에 몇 가지 추가 기능을 추가합니다

1. 원본 인용문을 저장합니다

window.onload = function() {
  console.log(1);
};

var _onload = window.onload || function() {};

window.onload = function() {
  _onload();
  console.log(2);
}

질문:
(1) 중간변수
는 반드시 유지되어야 한다 (2) 이것이 납치되는 문제가 발생할 수 있습니다
window.onload의 예에서는 일반 함수 _onload를 호출할 때도 window.onload를 호출할 때와 마찬가지로 window를 가리키기 때문에 이러한 문제가 없습니다.

2. 탈취당했습니다:

var _getElementById = document.getElementById;
document.getElementById = function(id) {
  console.log(1);
  return _getElementById(id);
}

return _getElementById(id); // 报错“Uncaught TypeError: Illegal invocation”

_getElementById는 전역 함수이므로 전역 함수가 호출되면 이는 창을 가리키고 document.getElementById의 this는 문서를 가리킬 것으로 예상됩니다.

3. 납치당하는 문제 해결:

var _getElementById = document.getElementById;
document.getElementById = function(id) {
  console.log(1);
  return _getElementById.call(document, id);
}

2. AOP를 활용해 함수 꾸미기

/* 让新添加的函数在原函数之前执行(前置装饰)*/
Function.prototype.before = function(beforefn) {
  var _self = this;
  return function() {
    beforefn.apply(this, arguments);  // 新函数接收的参数会被原封不动的传入原函数
    return _self.apply(this, arguments);
  };
};

/* 让新添加的函数在原函数之后执行(后置装饰)*/
Function.prototype.after = function(afterfn) {
  var _self = this;
  return function() {
    var ret = _self.apply(this, arguments);
    afterfn.apply(this, arguments);
    return ret;
  };
};

document.getElementById = document.getElementById.before(function() {
  console.log(1);
});

3. 프로토타입 오염 방지

var before = function(fn, beforefn) {
  return function() {
    beforefn.apply(this, arguments);
    return fn.apply(this, arguments);
  };
};

var after = function(fn, afterfn) {
  return function() {
    var ret = fn.apply(this, arguments);
    afterfn.apply(this, arguments);
    return ret;
  };
};

document.getElementById = before(document.getElementById, function(){
  console.log(1);
});

4. 예 – 플러그인 양식 유효성 검사

"JavaScript 디자인 패턴 학습 - 전략 패턴" 의 [Form Validation]과 결합하고, ajax를 적용하여 데이터 검증을 제출하면 효과가 짱이에요!

위의 before 방법을 수정

var before = function(fn, beforefn) {
  return function() {
    if(beforefn.apply(this, arguments) === false) {
      // beforefn返回false,直接return,不执行后面的原函数
      return;
    }
    return fn.apply(this, arguments);
  };
};
/* 模拟数据验证*/
var validate = function() {
  if(username === "") {
    console.log("验证失败!");
    return false;
  }
  return true;
}
/* 模拟ajax提交*/
var formSubmit = function() {
  console.log("提交!!!");
}
username = 1;
formSubmit = before(formSubmit, validate); // 提交!!!
formSubmit();

username = "";
formSubmit = before(formSubmit, validate); // 验证失败!
formSubmit();

5. 데코레이터 모드와 프록시 모드

유사점: 두 패턴 모두 객체에 대해 어느 정도의 간접 참조를 제공하는 방법을 설명합니다. 해당 구현 부분은 다른 객체에 대한 참조를 유지하고 해당 객체에 요청을 보냅니다.
차이점:
(1) 프록시 모드: 직접 로컬 접속이 불편하거나 요구사항을 충족하지 못하는 경우 이 온톨로지를 대체할 수 있는 모드를 제공합니다. 주요 기능을 로컬로 정의하면 에이전트는 이에 대한 액세스를 제공 또는 거부하거나 온톨로지에 액세스하기 전에 몇 가지 추가 작업을 수행합니다. (아직도 본체와 같은 역할을 합니다)
(2) 데코레이터 모드: 객체에 동작을 동적으로 추가합니다. (처음부터 객체의 모든 기능을 결정하고 실제로 객체에 새로운 책임과 행동을 추가할 수는 없습니다)

이 기사가 자바스크립트 프로그래밍을 배우는 모든 사람에게 도움이 되기를 바랍니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.