14

現在、chrome devツールを使用してバックボーンまたはマリオネットをデバッグしているときに、ブレークポイントなどを設定することになりますが、コードが一時停止すると、chromeがすべてに「子"。
(コンストラクター関数だからだと思います)

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

これが私に引き起こす狂気の量は、次のようなことを始めたいと思っています:

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

私はそれが本当に好きではありません。なぜなら、その...醜い、その変数...そしてそれは私が変数を調べて展開するときにのみ役立ちます...chromeがそれを表示するために使用する名前を変更するのは素晴らしいことです。

いずれにせよ、名前を変更する方法を知っている人はいますか?またはあなたが使用する他のよりクリーンな慣習がありますか?

ありがとう!

マット

4

4 に答える 4

33

バックグラウンド

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

すべての JavaScript オブジェクトには、オブジェクトの作成に使用される関数への参照であるコンストラクター プロパティがあります。コンストラクターは、コンソール/デバッガーにオブジェクトの「タイプ」を表示するためにブラウザーによって使用されます。空でない場合は、コンストラクター関数の name プロパティの値が使用されます。ただし、名前付き関数式を使用して定義された関数のみが、有用な名前プロパティを取得します。

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

無名関数には空の 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 に戻ると、カスタム コンストラクター (以下を参照) を使用していないと仮定すると、モデル、ビュー、コレクション、およびルートで次のように使用されるBackbone の extends 関数で作成された匿名コンストラクター関数で型が終了します。

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

これが、コンソール/デバッガーでバックボーン オブジェクトの横に「子」が表示される理由です。これは、オブジェクトのコンストラクターに適した名前をブラウザーが推測する最善の方法です。

ソリューション

オブジェクトに適切な型名を付けるには、バックボーン型を定義するときに、最初の「protoProps」引数を介して名前付きコンストラクターを指定できます。次のように、「親」コンストラクターへの呼び出しをラップするコンストラクター プロパティを追加するだけです。

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

Product モデルのインスタンスがデバッガーで見栄えよくなります。

定義するすべてのビュー、モデル、コレクション、およびルートに対してこれを行うのは少し面倒です。Backbone の拡張機能にモンキー パッチを適用して、作業を行うことができます。

まず、型の名前を定義するための規則を確立する必要があります。ここでは__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;
})();
于 2013-02-22T22:07:58.577 に答える
4

はい。constructor名前付き関数式を使用してモデル/コレクション/ビューをオーバーライドすることにより、コンソールの表示名を変更できます。toStringモデルが文字列型に強制されている場合、コンソール出力を制御するためにオーバーライドすることも役立つ場合があります。たとえば、次の+演算子を使用します。

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

だから:

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

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

あなたは得るでしょう:

state: Model({"id":1,"foo":"bar"})
► Model
于 2013-02-14T06:45:31.807 に答える