2013-02-14 12 views
14

現在、私はChrome Devツールを使用してバックボーンやマリオネットをデバッグしていますが、ブレークポイントやその他の設定は終了しますが、一旦コードが一時停止すると、クロムのラベルはすべて「子供」というラベルが付いているからです。
(これはコンストラクタ関数だと思います)JavaScriptをデバッグする(バックボーンとマリオネット)

この宣言を変更するか、使用しているモデル/コレクションの種類を簡単に判別する方法はありますか。

これは私の中で原因狂気はこのような何かやって起動したい金額:その...醜い、その変数ので、私は、本当に好きではない

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

に...それだけ変数を調べて展開するときに役立ちます... chromeが表示するために使用する名前を変更することは素晴らしいことでしょう。

いずれにしても、名前を変更する方法を知っている人はいますか?あなたが使っている清潔なコンベンションをいくつか持っていますか?

ありがとうございます!

マット

答えて

33

背景

ブラウザが「子」を使用してコンソール/デバッガにBackboneオブジェクトのタイプを表示する理由を調べることは興味深いです。

すべてのJavaScriptオブジェクトには、オブジェクトを作成するために使用された関数への参照であるコンストラクタプロパティがあります。コンストラクタは、ブラウザがオブジェクトの「型」をコンソール/デバッガに表示するために使用されます。空でない場合は、コンストラクタ関数のnameプロパティの値が使用されます。

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); 
    } 
}); 

:ちょうど次のように「親」コンストラクタへの呼び出しをラップconstructorプロパティを追加します。

定義したすべてのビュー、モデル、コレクション、ルートでこれを行うのは少し面倒です。あなたはあなたのために仕事をするためにバックボーンの拡張機能をサルパッチすることができます。

まず、タイプの名前を定義するための規約を確立する必要があります。ここでは、次のように指定した__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

4

はい。名前付き関数式を使用して、モデル/コレクション/ビューconstructorをオーバーライドすることによって、コンソール表示名を変更できます。

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) + ")"; 
    } 
}); 

:モデルは言う、と文字列型に強制されたとき、また、+オペレータコンソール出力を制御するためにtoStringを上書きするhelpulかもしれ:

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

nice!私たちがそれを行うことができるかどうかはわかりませんでした:) ...また、私たちはMarionetteのソースシンボルに取り組んでいます。私はこれをv1.0のリリースに備えることを望んでいます。これはデバッグに大いに役立つはずです。 –

+0

@DerickBailey、ソースマップはすばらしいでしょう。 Marionetteの作業がBackboneコアに何か貢献する可能性もあります。 https://github.com/documentcloud/backbone/issues/2143 – jevakallio

2

デバッグのために、このextensionのこのlibraryを使用することを検討してください。

2

また、アプリケーションの上部にある

"use strict" 

を追加してみてください。 backbone.marionette.jsの1行目に定義されていないようなスタックトレースエラーを出すのではなく、インスタンスを出力し、HistoryViewが見つからないような説明的な情報になります。

関連する問題