Отладка Javascript (Магистраль и марионетка) - программирование
Подтвердить что ты не робот

Отладка Javascript (Магистраль и марионетка)

Прямо сейчас, когда я отлаживаю магистраль или марионетку с помощью инструментов chrome dev, я в конечном итоге устанавливаю точки останова и многое другое, но как только код приостанавливается, трудно определить, с каким типом объектов я работаю, потому что хром-метки все "ребенок".
(Я думаю, потому что функция-конструктор)

Есть ли простой способ изменить это объявление или определить, какой тип модели/коллекции я использую.

Количество безумия, которое это вызывает во мне, хочет начать делать что-то вроде этого:

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

Мне это не очень нравится, потому что его... уродливый, его переменная... и это помогает только при проверке и расширении переменной... было бы здорово изменить имя, которое использует хром для отображения Это.

В любом случае, кто-нибудь знает, как изменить имя? или использовать какое-либо другое соглашение о экологически чистом виде?

Спасибо!

Matt

4b9b3361

Ответ 1

Фон

Интересно посмотреть, почему браузер использует "child" для отображения типа объектов Backbone в консоли/отладчике.

Все объекты JavaScript имеют свойство constructor, ссылку на функцию, используемую для создания объекта. Конструктор используется браузером для отображения объектов "type" в консоли/отладчике. Значение свойства имени функции конструктора будет использоваться, если оно не пустое. Однако только функции, определенные с помощью названных функциональных выражений, получают полезное свойство имени:

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() { … }
};

Более подробный script доступен здесь: http://jsfiddle.net/danmalcolm/Xa7ma/6/

Браузер, как представляется, получает это имя из исходного кода - не существует функции JavaScript, которая может указывать во время выполнения имя первой переменной, которой была назначена функция. Другие браузеры поддерживают соглашение, в котором используется свойство displayName, определенное в функциях анонимного конструктора, но в настоящее время это не происходит в Chrome: http://code.google.com/p/chromium/issues/detail?id=17356.

Возвращаясь к Магине, предполагая, что вы не используете собственный конструктор (см. ниже), ваш тип будет иметь анонимную конструкторскую функцию, созданную в функции продления базы используется Model, View, Collection и Route следующим образом:

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

Вот почему вы видите "child" рядом с вашими объектами Backbone в консоли/отладчике. Это браузеры лучше всего угадывают подходящее имя для вашего конструктора объектов.

Решения

Чтобы дать вашим объектам лучшее имя типа, вы можете предоставить именованный конструктор через первый аргумент "protoProps" при определении типов Backbone. Просто добавьте свойство конструктора, которое обертывает вызов конструктору "parent" следующим образом:

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

В отладчике теперь будут выглядеть действительно хорошие экземпляры модели продукта.

Это немного громоздко сделать для каждого вида, модели, коллекции и маршрута, которые вы определяете. Вы можете использовать обезьянную патч Backbones, чтобы выполнять работу за вас.

Сначала вам нужно установить соглашение для определения имен ваших типов. Здесь мы используем свойство __name__, которое вы указываете следующим образом:

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

Затем вы заменяете функцию расширения, используемую Model, View, Collection и Route, чтобы прочитать это свойство и добавить именованный конструктор к вашему типу. Вам не нужно изменять сам backbone.js, просто включите следующее в отдельный script, который загружается после 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;
})();

Ответ 2

Да. Вы можете изменить отображаемое имя консоли, переопределив модель/коллекцию/представление constructor с помощью именованного функционального выражения. Также может быть helpl переопределить 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

Ответ 4

Также попробуйте добавить

"use strict"

в верхней части приложения. Вместо того чтобы давать вам ошибки трассировки стека, такие как undefined в строке 1 backbone.marionette.js, он выведет экземпляр и будет более описательной информацией, такой как HistoryView, не найден.