背景
ブラウザが「子」を使用してコンソール/デバッガに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;
})();
うわー、これはデフォルトでバックボーンに含まれるべきです....百万ダンに感謝、これは素晴らしいです。 – MattyP