2013-02-14 85 views
14

現在,當我使用chrome開發工具調試骨幹或木偶時,我最終設置了斷點和其他東西,但是一旦代碼暫停,很難說出什麼類型的對象因爲鍍鉻將所有事情都標記爲「孩子」。
(我認爲是因爲這是構造函數)調試Javascript(Backbone and Marionette)

是否有任何簡單的方法來更改此聲明或確定我正在使用哪種類型的模型/集合。

量瘋狂這導致我要開始做這樣的事情:

MyModel = Backbone.Model.Extend({ 
    // the $$$ puts it at the top of the inspector, the NAME is just for other devs 
    $$$NAME = "MyModel", 
    ... 
}); 

我真的不喜歡它,因爲它的...醜陋的,它是一個變量...它只當我檢查並擴展變量時有幫助...更改名稱chrome用來顯示它是非常好的。

無論如何,有誰知道如何更改名稱?或者有其他一些更清潔的習慣嗎?

謝謝!

馬特

回答

33

背景

看看爲什麼瀏覽器使用「child」在控制檯/調試器中顯示Backbone對象的類型是很有趣的。

所有的JavaScript對象都有一個構造函數屬性,它是用於創建對象的函數的引用。瀏覽器使用構造函數在控制檯/調試器中顯示對象的「類型」。如果構造函數的名稱屬性不爲空,它的值將被使用。

function A() { } 
console.log(A.name); // 'A' 

匿名函數有一個空的name屬性:但是,只有功能使用命名函數表達式得到一個有用的name屬性定義

var B = function() { }; 
console.log(B.name); // '' 

所以,用匿名函數會發生什麼? Chrome會從首次分配該功能的變量或屬性的名稱推斷匿名函數的名稱。下面是一些例子:

// 1. named function expression - objects will show as 「a」 in the console 
function a() { … } 

// 2. anonymous function assigned to variable - objects will show as 「b」 in the console 
var b = function(){ … }; 

// 3. anonymous function assigned to property of object - objects will show as 「container.c」 in the debugger 
var container = { 
    c: function() { … } 
}; 

更詳細的腳本可以在這裏找到:http://jsfiddle.net/danmalcolm/Xa7ma/6/

瀏覽器似乎從源代碼中得到這個名字 - 沒有一個JavaScript功能,可以在運行時告訴你函數分配給的第一個變量的名稱。其他瀏覽器支持使用在匿名構造函數上定義的displayName屬性的約定,但目前在Chrome中不存在:http://code.google.com/p/chromium/issues/detail?id=17356

回到骨幹,你不使用自定義構造函數(見下文)假設,你的類型將最終獲得一個匿名構造函數中使用的模型,視圖,收集和路線爲Backbone's extend function創建如下:

child = function(){ return parent.apply(this, arguments); }; 

這就是爲什麼你在控制檯/調試器中看到Backbone對象旁邊的「孩子」。這是瀏覽器在對象構造函數的合適名稱下的最佳猜測。

解決方案

爲了讓你的對象更好的類型名稱,您可以通過第一個「protoProps」的說法提供了一個名爲構造函數時您可以在定義骨幹類型。只需添加一個包裝了呼叫「父」的一個構造屬性,如下所示:

var Product = Backbone.Model.extend({ 
    constructor: function Product() { 
     Backbone.Model.prototype.constructor.apply(this, arguments); 
    } 
}); 

您的產品型號實例現在看起來真的不錯在調試器。

對於您定義的每個視圖,模型,集合和路由,執行此操作有點麻煩。你可以猴子補丁骨幹的擴展功能爲你做的工作。

您首先需要建立一個用於定義類型名稱的約定。這裏,我們使用一個__name__屬性,它可以指定如下:

var Product = Backbone.Model.extend({ 
    __name__: 'Product' 
    // other props 
}); 

你再更換所使用的模型,視圖,收集和路線來讀取此屬性和一個名爲構造函數添加到您的類型擴展功能。您不需要修改backbone.js本身,只需在backbone.js之後加載的單獨腳本中包含以下內容即可。

(function() { 

    function createNamedConstructor(name, constructor) { 

     var fn = new Function('constructor', 'return function ' + name + '()\n' 
      + '{\n' 
      + ' // wrapper function created dynamically for "' + name + '" constructor to allow instances to be identified in the debugger\n' 
      + ' constructor.apply(this, arguments);\n' 
      + '};'); 
     return fn(constructor); 
    } 

    var originalExtend = Backbone.View.extend; // Model, Collection, Router and View shared the same extend function 
    var nameProp = '__name__'; 
    var newExtend = function (protoProps, classProps) { 
     if (protoProps && protoProps.hasOwnProperty(nameProp)) { 
      // TODO - check that name is a valid identifier 
      var name = protoProps[nameProp]; 
      // wrap constructor from protoProps if supplied or 'this' (the function we are extending) 
      var constructor = protoProps.hasOwnProperty('constructor') ? protoProps.constructor : this; 
      protoProps = _.extend(protoProps, { 
       constructor: createNamedConstructor(name, constructor) 
      }); 
     } 
     return originalExtend.call(this, protoProps, classProps); 
    }; 

    Backbone.Model.extend = Backbone.Collection.extend = Backbone.Router.extend = Backbone.View.extend = newExtend; 
})(); 
+3

哇,這應該只包括在骨幹默認....感謝萬丹,這是偉大的。 – MattyP 2013-02-26 16:50:10

4

是的。您可以通過使用命名函數表達式覆蓋模型/集合/視圖constructor來更改控制檯顯示名稱。這也可能是helpul覆蓋toString控制控制檯輸出時,該模型被強制字符串類型有,比方說,+操作:

var model = new Model({id:1,foo:"bar"}) 

console.log("state: " + model); 
console.log(model); 

您將獲得:

App.Model = Backbone.Model.extend({ 

    //define constructor using a named function expression 
    constructor: function Model() { 
    Backbone.Model.prototype.constructor.apply(this, arguments); 
    }, 

    //override toString to return something more meaningful 
    toString: function() { 
    return "Model(" + JSON.stringify(this.attributes) + ")"; 
    } 
}); 

所以:

state: Model({"id":1,"foo":"bar"}) 
► Model 
+0

不錯!不知道我們可以做到這一點:) ...另外,我們正在研究木偶的源代碼。我希望能有這個v1.0版本。這應該有助於調試。 – 2013-02-15 14:52:28

+0

@DerickBailey,源地圖會很棒。任何你在Marionette上工作的機會都可以爲Backbone核心做出貢獻。 https://github.com/documentcloud/backbone/issues/2143 – jevakallio 2013-02-15 14:56:53

2

也可以嘗試在你的應用程序的頂部添加

"use strict" 

。它不會像backbone.marionette.js的第1行那樣給你提供像未定義的堆棧跟蹤錯誤,它會輸出實例並且是更多的描述性信息,比如HistoryView未找到。

相關問題