2012-11-29 34 views
5

Tôi đang tổ chức một ứng dụng doanh nghiệp nhỏ nhưng muốn sử dụng càng nhiều càng tốt. Kết quả là, tôi đã xem xét các thư viện mixin.Cách sử dụng mixin đúng cách trong Javascript

Tôi đã xem qua số library này và nghĩ rằng đó có thể là một lựa chọn tốt vì nó cho phép bạn kết hợp vào và ra khi chạy. Ngoài ra, tôi chỉ có thể có một lớp cơ sở (BaseView) ví dụ và chỉ mixin ra khỏi đó.

Câu hỏi

  1. một số ví dụ ứng dụng thực tế của mixins hữu ích là gì? (không có ví dụ trừu tượng nào khác)
  2. Tôi thậm chí có cần mở rộng các lớp học hay chỉ có thể sử dụng thư viện này để quản lý tất cả tiện ích mở rộng và mixin?

Trả lời

2

A mixin chỉ là một ý tưởng khái niệm khác về cách sắp xếp mã và kế thừa. Tất nhiên bạn có thể kết hợp nó với việc sử dụng cổ điển hoặc thừa kế nguyên mẫu, nhưng nó cũng hoạt động độc lập, để nói.

Ví dụ, thay vì tạo "ủy thác" thuộc tính đối tượng/tra cứu (như nguyên chủng thừa kế), chúng tôi sẽ thực sự "dạng" độc lập đối tượng mới, từ nhiều đối tượng khác. Điều này cũng được gọi là "nhiều thừa kế" đôi khi và điều đó không thể đạt được dễ dàng với Javascripts thừa kế nguyên mẫu một mình.

Như một ví dụ:

var pianist = { 
    play: function() {} 
}; 

var programmner: { 
    code: function() {} 
}; 

Và bây giờ chúng ta có thể tạo ra một Object, như

var Jim = Object.create(null); // create a fully self-defining object 

extend(Jim, pianist); 
extend(Jim, programmer); 

và phương pháp giả extend này có thể trông giống như (ES5):

function extend(target, source) { 
    Object.getOwnPropertyNames(source).forEach(function(key) { 
     Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)) }); 

    return target 
} 

Tôi thực sự không trả lời đúng câu hỏi của bạn, nhưng tôi cảm thấy như không có câu trả lời thực sự cho câu hỏi của bạn. Nó là thực tế như bạn sẽ sử dụng nó, không có trường hợp sử dụng "ứng dụng cụ thể" thực sự.

1

Chúng tôi sử dụng thư viện mixin có tên là Cocktail (mixins ... tải xuống?). Nó đặc biệt để sử dụng trong các ứng dụng Backbone, nhưng khá tốt.

Chúng tôi đã written up details on our usage patterns làm một công việc tốt hơn tôi có thể mô tả nó ở đây.

3

xin vui lòng xem thêm:

Nếu nói đến JavaScript và phương pháp tiếp cận thành phần dựa trên vai trò như Mixins và Traits, tôi cũng rất có ý kiến. Tôi sẽ chỉ đến một hỗn hợp bất khả tri trong thư viện của 2 mẫu dựa trên chức năng thuần túy - trước tiên là mô hình mô-đun và thứ hai là mẫu "Chuyến bay Mixin" vì nó đã được khám phá lại, đặt tên và mô tả bởi Angus Croll vào tháng 5 năm 2011. Nhưng tôi cũng khuyên bạn nên đọc một bài báo của tôi từ tháng Tư năm 2014.

Câu hỏi

    01.
  • 1) Một số ví dụ ứng dụng thực sự của Mixins hữu ích là gì? (xin không có ví dụ trừu tượng nào hơn)
  • 2) Tôi thậm chí có cần mở rộng các lớp học hay chỉ có thể sử dụng thư viện này để quản lý tất cả tiện ích mở rộng và mixin?

Trả lời 2 câu hỏi của bạn ...

1) [Observable] lẽ là một trong những ví dụ thế giới thực phổ biến nhất cho mixins. Nhưng đây không phải là nơi thích hợp để cung cấp toàn bộ cơ sở mã của nó. Các ví dụ ngày càng phát triển từ Smart Talents chapter không cung cấp các triển khai hoạt động của nhà máy [Queue] khi bắt đầu chỉ sử dụng Mixins như [Enumerable][Allocable] nhưng cuối cùng cũng áp dụng số đã được đề cập [Observable].

2nd) Chỉ cần sử dụng hệ thống mô-đun bạn chọn hoặc cần - CommonJS or AMD. Các mô-đun nhà máy của bạn hoặc thậm chí cả các cá thể/đối tượng sau đó thực hiện các hành vi bổ sung bằng cách ủy nhiệm; do đó họ chủ động làm call/apply các mô hình Mixin hoặc Trait.

cuối cùng - rút ngắn mã ví dụ:

var Observable_SignalsAndSlots = (function() { 
 

 
    var 
 
    Event = function (target, type) { 
 

 
     this.target = target; 
 
     this.type = type; 
 
    }, 
 

 
    EventListener = function (target, type, handler) { 
 

 
     var defaultEvent = new Event(target, type); 
 

 
     this.handleEvent = function (evt) { 
 
     /* ... */ 
 
     }; 
 
     this.getType = function() { 
 
     return type; 
 
     }; 
 
     this.getHandler = function() { 
 
     return handler; 
 
     }; 
 
    }, 
 

 
    EventTargetMixin = function() { 
 

 
     var eventMap = {}; 
 

 
     this.addEventListener = function (type, handler) { 
 
     /* ... */ 
 
     }; 
 
     this.dispatchEvent = function (evt) { 
 
     /* ... */ 
 
     }; 
 
    } 
 
    ; 
 

 
    return EventTargetMixin; 
 

 
}).call(null); 
 

 

 
var Queue = (function() { 
 

 
    var 
 
    global = this, 
 

 
    Observable = global.Observable_SignalsAndSlots, 
 
    //Allocable = global.Allocable, 
 

 
    Queue, 
 

 
    onEnqueue = function (queue, type) { 
 
     queue.dispatchEvent({type: "enqueue", item: type}); 
 
    }, 
 
    onDequeue = function (queue, type) { 
 
     queue.dispatchEvent({type: "dequeue", item: type}); 
 
    }, 
 
    onEmpty = function (queue) { 
 
     queue.dispatchEvent("empty"); 
 
    } 
 
    ; 
 

 
    Queue = function() { // implementing the [Queue] Constructor. 
 
    var 
 
     queue = this, 
 
     list = [] 
 
    ; 
 
    queue.enqueue = function (type) { 
 

 
     list.push(type); 
 
     onEnqueue(queue, type); 
 

 
     return type; 
 
    }; 
 
    queue.dequeue = function() { 
 

 
     var type = list.shift(); 
 
     onDequeue(queue, type); 
 

 
     (list.length || onEmpty(queue)); 
 

 
     return type; 
 
    }; 
 
    Observable.call(queue); 
 
    //Allocable.call(queue, list); 
 
    }; 
 

 
    return Queue; 
 

 
}).call(null); 
 

 

 
var q = new Queue; 
 

 
q.addEventListener("enqueue", function (evt) {console.log("enqueue", evt);}); 
 
q.addEventListener("dequeue", function (evt) {console.log("dequeue", evt);}); 
 
q.addEventListener("empty", function (evt) {console.log("empty", evt);}); 
 

 
console.log("q.addEventListener : ", q.addEventListener); 
 
console.log("q.dispatchEvent : ", q.dispatchEvent); 
 

 
console.log("q.enqueue('the') ... ", q.enqueue('the'));  // "enqueue" Object {type: "enqueue", item: "the", target: Queue} 
 
console.log("q.enqueue('quick') ... ", q.enqueue('quick')); // "enqueue" Object {type: "enqueue", item: "quick", target: Queue} 
 
console.log("q.enqueue('brown') ... ", q.enqueue('brown')); // "enqueue" Object {type: "enqueue", item: "brown", target: Queue} 
 
console.log("q.enqueue('fox') ... ", q.enqueue('fox'));  // "enqueue" Object {type: "enqueue", item: "fox", target: Queue} 
 

 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: "the", target: Queue} 
 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: "quick", target: Queue} 
 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: "brown", target: Queue} 
 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: "fox", target: Queue} 
 
               // "empty" Object {target: Queue, type: "empty"} 
 
console.log("q.dequeue() ... ", q.dequeue()); // "dequeue" Object {type: "dequeue", item: undefined, target: Queue} 
 
               // "empty" Object {target: Queue, type: "empty"}
.as-console-wrapper { max-height: 100%!important; top: 0; }