2012-03-13 43 views
26

Cho một ví dụ về mô hình Backbone, làm thế nào tôi có thể biết "lớp" (để nói) của cá thể này?Lấy mô hình/tên lớp của mô hình Backbone

Ví dụ:

class Car extends Backbone.Model 

mycar = new Car() 

Và những gì tôi cần là:

mycar.modelName # => 'Car' 
+1

Bạn cần cụ thể hơn. Mô hình có thể có nhiều chế độ xem. Khung nhìn có tham chiếu .el mà AFAIK là đủ, * nếu bạn đang xem xét các khung nhìn *. Nhưng đó có thể không phải là những gì bạn đang yêu cầu. – JayC

+0

Ah, nevermind. Bạn đang nói theo chương trình. – JayC

+0

Tại sao bạn cần tên lớp? Để tạo ra một mô hình mới cùng loại hoặc để truy cập một chức năng cấp lớp hoặc một cái gì đó khác? Câu hỏi thú vị của nó. – websymphony

Trả lời

10

Đó là vấn đề nói chung, tôi nghĩ vậy. Tôi sẽ đề xuất một số tùy chọn được đề cập ở đây (How do I get the name of an object's type in JavaScript?) nhưng tôi đã gặp sự cố với tùy chọn đầu tiên. Bạn luôn có thể mở rộng tất cả các mô hình của bạn để có một hàm trả về một "tên" cho mô hình, nhưng tôi có thể hiểu tại sao bạn có thể thấy rằng ít hơn thỏa đáng.

+1

Tôi đồng ý, hoặc bạn giải quyết thủ công như @JayC đề xuất hoặc bạn đang nói về một mối quan tâm chung JS rất cũ vẫn chưa được giải quyết. – fguillen

14

Tính đến văn bản bạn có thể nhận tên lớp của mô hình bằng cách làm như sau:

model.constructor.name 

này làm việc cho tôi trong trình duyệt Chrome.

+15

Lưu ý rằng điều này sẽ không hoạt động nếu bạn có một bộ khai thác như Jammit, hàm tạo sẽ thay đổi sau khi đóng gói. –

23

Tôi đã thử đề xuất của Mitch nhưng trong Chrome, model.constructor.name luôn là "" đối với tôi.

Tôi đã chọn thay vì sử dụng quy ước. bây giờ tôi tạo ra một tài sản lớp bằng cách sử dụng param thứ hai của mở rộng mà làm việc như sau:

directory.models.SomeModel = Backbone.Model.extend({ 
    // usual model instance stuff 
}, { 
    modelType: "SomeModel" // class property 
}); 

tôi thấy rằng tôi luôn có thể có được những gì tôi muốn như thế này:

var mt = model.constructor.modelType; 
0

này đã được giải quyết trong tất cả các trình duyệt ngoại trừ IE, nhưng một polyfill dễ thực hiện. Câu trả lời là Function.name:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name

Chắc chắn tận dụng điều này! Trong các lớp ES6, Function.name của hàm dựng là tên lớp, vì vậy trong ES6:

class Car { /*...*/ } 
var c = new Car(); 
console.log(c.constructor.name); // "Car" 

Trong ES5 hiện tại, không phải tất cả thư viện đều tận dụng điều này. Xương sống, ví dụ, không. :(constructors Backbone là chức năng ẩn danh, vì vậy

var m = new Backbone.Model(); 
console.log(m.constructor.name); // "undefined" :(

không may. Giống như người kia đã nói, nếu bạn đang sử dụng Backbone, bạn sẽ phải làm cho hệ thống đặt tên của riêng bạn.

Dưới đây là một polyfill cho Function .name:

// Polyfill for Function.name on browsers that do not support it (IE): 
// See: http://stackoverflow.com/questions/6903762/function-name-not-supported-in-ie 
if (!(function f() {}).name) { 
    Object.defineProperty(Function.prototype, 'name', { 
     get: function() { 
      var name = this.toString().match(/^\s*function\s*(\S*)\s*\(/)[1]; 

      // For better performance only parse once, and then cache the 
      // result through a new accessor for repeated access. 
      Object.defineProperty(this, 'name', { value: name }); 

      return name; 
     } 
    }); 
} 
0

bạn có thể truy vấn các cây thừa kế (hay còn gọi là chuỗi nguyên mẫu) ví dụ đối tượng của bạn như thế này:

đối tượng .__ proto __.__ proto __.__ proto__

Bạn có thể xem những gì có sẵn. Bất kỳ thuộc tính tên loại nào sẽ được bạn thêm vào mỗi chế độ xem và/hoặc mô hình theo cách thủ công. Đây là con đường sạch sẽ nhất. Tôi đề nghị điều này. Chỉ cần thêm 'className: "MyCompany.MyProject.MyArea.MyView"' vào mỗi chế độ xem và/hoặc mô hình của bạn.

Nếu bạn không thêm một tài sản className để đối tượng của bạn, có một cách nhẹ hacky để vẫn có được nó (ví dụ cho các mục đích kết xuất debug):

Giả sử bạn làm điều gì đó như: "MyCompany.MyProject. MyArea.MyView = Backbone.View.extend ({"tên khung nhìn/mô hình nằm trong một tên miền toàn cục var name. Từ cá thể đối tượng, chúng ta không thể tiếp cận tên var toàn cục đó. Vì vậy, trong khi không thực sự lý tưởng, tốt nhất chúng ta có thể làm là đi qua không gian tên tìm kiếm var:

function findBackboneClassName(ns, object, prefix, depth) { 
    prefix = typeof prefix !== 'undefined' ? prefix : ""; 
    depth = typeof depth !== 'undefined' ? depth : 0; 
    if (depth > 5) return null; 

    for (i in ns) { 
     try { ns[i]; } catch (e) { continue; } 
     if (/top|window|document|parent|frames|self|chrome|form|theForm/.test(i)) continue; 
     //console.log(">" + prefix + "." + i + " " + typeof(ns[i])); 

     if (ns[i] == object.constructor) { 
      //console.log("Found:", prefix + "." + i); 
      return prefix + "." + i; 
     } 

     if (typeof (ns[i]) == "object") { 
      var r = findBackboneClassName(ns[i], object, prefix + (prefix != "" ? "." : "") + i, depth + 1); 
      if (r != null) return r; 
     } 
    } 
    return null; 
} 
findBackboneClassName(window, myBackboneViewInstance); 

Lý tưởng nhất là bạn đang sử dụng không gian tên cho các loại khác ngoài "cửa sổ". dễ dàng hơn để đi qua. Bạn chỉ cần thay thế "cửa sổ" bằng cơ sở không gian tên của bạn và chuyển vào tiền tố mong muốn nếu bạn muốn tiền tố được đặt đúng. Bạn cũng có thể xóa một vài dòng như try..catch và if..continue.

findBackboneClassName(MyCompany.MyProject, myBackboneViewInstance, "MyCompany.MyProject"); 

Bí quyết nhận tên lớp từ objectInstance.constructor không hoạt động vì xương đòn thừa kế. Tất cả các ctors nhìn giống nhau đối với tôi: "function() {return parent.apply (this, arguments);}".

Các vấn đề liên quan