Debugging Javascript (Backbone and Marionette)
Debugging Javascript (Backbone and Marionette)
现在,当我使用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用来显示它的名称,那就太好了。
无论如何,有人知道如何更改名称吗?或者你用其他更清洁的约定?
谢谢!
Matt
背景
有趣的是,浏览器为什么使用"子"来显示控制台/调试器中的主干对象类型。
所有JavaScript对象都有一个构造函数属性,即对用于创建对象的函数的引用。浏览器使用构造函数在控制台/调试器中显示对象的"类型"。如果构造函数的name属性的值不为空,则将使用该值。但是,只有使用命名函数表达式定义的函数才能获得有用的名称属性:
function A() { }
console.log(A.name); // 'A'
匿名函数的名称属性为空:
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,假设您没有使用自定义构造函数(见下文),您的类型将以匿名构造函数结束,该函数是在Model、View、Collection和Route使用的Backbone扩展函数中创建的,如下所示:
child = function(){ return parent.apply(this, arguments); };
这就是为什么您在控制台/调试器中的主干对象旁边会看到"子"。这是浏览器对对象构造函数的合适名称的最佳猜测。
解决方案
为了给对象一个更好的类型名称,可以在定义主干类型时通过第一个"protoProps"参数提供一个命名构造函数。只需添加一个构造函数属性,该属性封装对"父"构造函数的调用,如下所示:
var Product = Backbone.Model.extend({
constructor: function Product() {
Backbone.Model.prototype.constructor.apply(this, arguments);
}
});
您的产品模型实例现在在调试器中看起来非常好。
对您定义的每个视图、模型、集合和路线执行此操作有点麻烦。您可以使用猴子补丁Backbone的扩展功能为您完成工作。
您首先需要建立一个定义类型名称的约定。这里我们使用的是__name__
属性,指定如下:
var Product = Backbone.Model.extend({
__name__: 'Product'
// other props
});
然后替换Model、View、Collection和Route用来读取此属性的扩展函数,并将命名构造函数添加到类型中。您不需要修改backline.js本身,只需在backline.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;
})();
是。您可以通过使用命名函数表达式覆盖模型/集合/视图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
请考虑使用此扩展的库进行调试。
同时尝试添加
"use strict"
位于应用程序顶部。它不会像backbone.marionette.js的第1行上的undefined那样向您提供堆栈跟踪错误,而是会输出实例,并提供更具描述性的信息,比如找不到HistoryView。
- Selenium WebDriver and JavaScript change
- PHP and Javascript functions
- Javascript Return and if/else
- SetTimeout and clearTimeout in Javascript
- lightbox in html 5 and javascript
- TimelineJS and AngularJS
- timeago.js with datatable and PHP
- javascript button ajax and php
- Ajax and Json with Rails
- Combine onload, onresize and onclick
- php布尔值's小写AND大写和数字布尔值'可以接受
- setTimeout and V8
- Jquery post and onclick
- Moment js and IOS
- Rails 3.2 and Paloma gem
- Backbone, TypeScript, and super
- iframe and JavaScript on different pages
- JSON and jQuery Search
- Marionette JS and Wreqr
- Debugging Javascript (Backbone and Marionette)