2011-09-21 3 views
16

다양한 라이브러리를 살펴보고 extend() 팝업이 많이 표시되는 것을보고 있지만 mixin()이 표시되는 것을 볼 수 있습니다. YUI에는 mixin과 확장 기능이 모두 있습니다.자바 스크립트 라이브러리에서 mixin()과 extend()의 차이점

이 두 개념의 차이점은 무엇입니까? 믹스 인과 오브젝트를 확장 할 때 언제 결정해야합니까?

감사합니다, 매트 명확성을 위해

답변

16

믹스는 instanceof와 함께 작동하지 않지만 확장됩니다. Mixins는 다중 상속을 허락하지만 프로토 타입을 적절히 연결하는 것이 아니라 위조함으로써 가능합니다.

Ext-JS 예제를 보여 드리지만 개념은 믹스를 제공하는 모든 클래스 라이브러리에 적용됩니다. 프로토 타입을 연결하는 대신 개체에 속성을 복사합니다.

믹스는 상속에 의지하지 않고 개체에 기능을 추가하는 좋은 방법입니다. 일부 기능을 사용하기 위해 상속해야하는 경우 클래스의 기능을 사용할 수 없습니다. Many people believe it's evil.

Labelable 기능을 FieldSet에 추가하려고 할 때 Ext-JS가 문제를 경험했으며 필드처럼 입력되지 않은 문제도있었습니다. Field 안에있는 Labelable 동작의 이점을 누릴 수있는 방법이 없었습니다. Field을 확장 할 수 없기 때문에 모든 입력 동작이 있었기 때문입니다.

+1

이 답변은 Ext.js에만 한정되어 있으며 다른 많은 JavaScript 라이브러리에는 적용 할 수 없습니다 (jQuery와 Underscore는 두 가지 예입니다). – natlee75

+0

@ natlee75 제 대답은 믹스 인이 프로토 타입 체인을 사용하지 않는다는 것입니다. 그리고 그것은 'instanceof' 테스트에 실패합니다. Ext-JS는 그것들의 구현 중 하나입니다. (뭔가 다른 것이 믹스 인 경우 체크 할 수 있습니다). 내가 아는 한 jquery 또는 밑줄은 프로토 타입 체인에서 설정하여 혼합을 구현하지 않습니다 (속성 만 복사합니다). 귀하의 의견은 jquery와 밑줄은 instanceof와 올바르게 작동하는 mixins을 가질 수 있다는 것을 의미합니까?/ –

+2

아니요, 그러나'extend' 함수는 아무 것도하지 않습니다. "클래스 라이브러리"(예 :'Ext.define')만이 prototypical 상속을위한 "extend"용어를 사용합니다. – Bergi

0

편집 :이 때로는 때로는 같은 일을하고 있지 않으며, mixin은 여러 객체 사이에서 함수를 재사용하는 데 사용되는 패턴의 이름이며 확장은 알고리즘/메소드를 사용하는 방식입니다. 동일한 경우 (예 : 밑줄 _.extend)와 다른 경우 (backbone.js가 확장 됨)가 있습니다.

확장이 다른 경우 확장은 일반적으로 프로토 타입을 확장되는 개체에 연결하지만 mixin은 메서드 목록을 대상에 복사합니다.

+0

두 클래스가 제공하는 동작을 원하는 경우를 제외하고. 자체 상속 문제가있는 다중 상속이 아닌 이상 상속을 사용할 수 없습니다. –

+0

extend와 mixin이 상속 등과 직접적으로 관련이 없기 때문에 그것이 어떻게 관련이 있는지 잘 모르겠습니다. 그 동작을 모방하는 방법 일뿐입니다. – taxilian

+0

나는 같은 행동을하지 않는 경우에 대해서 설명 할 뿐이다. –

2

여러분은 확실히 extends를 사용하여 믹스 인을 만들 수 있습니다.

믹스는 계층 구조없이 다중 상속의 모든 이점을 제공합니다 (JavaScript의 프로토 타입 상속). 둘 다 여러 객체에서 인터페이스 (또는 함수 집합)를 다시 사용할 수 있습니다. 믹스 인이 부모 - 자식 관계를 가지고 만날 수있는 "다이아몬드 문제"에 직면하지 않습니다.

다이아몬드 문제는 한 개체가 두 개체에서 동일한 함수 (또는 함수 이름)를 상속 할 때 발생합니다. 왜? 이 두 객체 중 하나가 기능을 추가하고 (예 : "super"라는 자바에서) 기능을 수정하면 JavaScript는 더 이상 두 가지 방법을 해석/결합하는 방법을 알지 못합니다. 믹스 인은이 계층을 피하는 방법입니다. 그들은 어디서든 붙잡을 수있는 기능을 정의합니다. Mixins에는 일반적으로 자체 데이터가 포함되어 있지 않습니다.

그래서 예를 들어 $.extend() 인 믹스 인을 jQuery에 쓸 수 있습니다. var newmixin = $.extend({}, mixin1, mixin2)은 두 개의 인터페이스를 결합하고 플랫 화 (이름 충돌을 덮어 씁니다)합니다.

  1. 이 두 인터페이스의 조합이 "계층"즉이 있습니까 :

    다음은 고려해야 할 3 가지입니다. 부모/자식 관계입니다. JavaScript에서는 프로토 타입 상속을 의미합니다.

  2. 함수가 복사되거나 참조됩니까? 원래 메소드가 변경되면 상속 된 메소드도 변경됩니까?
  3. 같은 이름의 두 메서드를 결합하면 어떻게됩니까? 그리고 이러한 갈등은 어떻게 처리됩니까?
5

확장 메서드는 JavaScript 라이브러리에서 매우 일반적이며 일반적으로 소비 코드가 하나 이상의 개체에 대한 모든 "자체"속성과 메서드를 대상 개체에 추가 할 수있는 메서드입니다. 코드는 대개 매우 간단합니다. 첫 번째 인수를 넘어서 각 인수의 모든 자체 키를 반복하고 거기에 저장된 값을 첫 번째 인수에 복사합니다.

"Mixin"은 하나의 개체를 시스템의 여러 개체에서 공유하려는 특정 속성 및 메서드 집합에 대한 컨테이너 종류로 사용하는 디자인 패턴을 나타냅니다. 예를 들어 응용 프로그램의 모든 UI 구성 요소에 적용 할 수있는 너비 및 높이 getter 및 setter가있을 수 있으므로 JavaScript의 경우 "new"로 인스턴스화 할 수있는 함수 나 이러한 메소드를 보유합니다. 그런 다음 "확장"유형 함수를 사용하여이 메소드를 시스템의 여러 객체에 복사 할 수 있습니다.

Underscore에는 전달 된 모든 객체 메소드가 체인에 사용할 기본 밑줄 객체에 추가되는 확장 인 본질적으로 확장 인 mixin 메소드가 있습니다. jQuery는 jQuery.fn의 확장 메소드와 비슷한 기능을 수행한다.

개인적으로 나는 하나의 원본 개체 만 받아들이는 대신 별도의 mixin 메서드를 사용하는 동안 "이 모든 개체를이 개체에서이 개체로 복사"동작을 그대로 유지하고 속성의 이름으로 모든 추가 인수를 처리합니다. 복사 할 메소드 (대상과 소스 만 더 이상 인수없이 전달되는 경우 단일 소스 확장과 같이 작동합니다).

function mixin(target, source) { 
    function copyProperty(key) { 
     target[key] = source[key]; 
    } 

    if (arguments.length > 2) { 
     // If there are arguments beyond target and source then treat them as 
     // keys of the specific properties/methods that should be copied over. 
     Array.prototype.slice.call(arguments, 2).forEach(copyProperty); 
    } else { 
     // Otherwise copy all properties/methods from the source to the target. 
     Object.keys(source).forEach(copyProperty); 
    } 
} 
+1

왜 Array.prototype.slice.call (arguments , 2)'arguments.slice (2)'를 통해. 더 유용한시기를 알고 싶을뿐입니다. 미리 감사드립니다 – cantfindaname88

+3

@ cantfindaname88 :'arguments','Array'와 같은 것은'Array' 인스턴스가 아니므로'.slice()'메소드가 없습니다. –

관련 문제