JavaScript изменить имя конструктора в консоли

1

Используя фабрику конструкторов, я хотел бы, чтобы эти конструкторы имели разные имена в консоли, а также при регистрации их экземпляров.

Вот упрощенный пример моей проблемы:

// Constructor factory //
function type(name, prototype) {
    function Constructor() {}
    Constructor.name ; // "Constructor"
    // Constructor.name = name  won't work properly.
    Object.defineProperty(Constructor, 'name', { value:name }) ;
    Constructor.prototype = prototype ;

    window[name] = Constructor ;
    return Constructor ;
}

// Creating constructor and instance //
type('Cat', { name:"", paws:4 }) ;
var chat = new Cat ;

// Tests //
Cat.name ; // "Cat"    -> Correct name
Cat ; // Constructor() { ... }     -> Incorrect name
chat ; // Constructor {name:"", paws:4}     -> Incorrect name

Есть ли способ отобразить правильное имя в этом случае?

Протестировано с последней версией Chrome (67). В этом случае я не хочу использовать функцию class.

  • 1
    class Cat { /*...*/ } . И я не думаю, что вы можете повлиять на вывод консоли без какого-либо очень странного кода with(){} или eval .
  • 0
    Я бы порекомендовал не делать все ваши функции конструктора глобальными. Глобальное пространство имен уже очень, очень тесно.
Показать ещё 2 комментария
Теги:
debugging
constructor

1 ответ

1
Лучший ответ

Вы бы подумали, что объект с решением для обхода вычисленного свойства может ответить на этот вопрос, но он не работает для сценария конструктора, который вы описываете (по крайней мере, на данный момент в Chrome или Firefox он работает, сейчас, в по крайней мере, Firefox v66; он работает в Edge и, что удивительно для меня, в Node.js, несмотря на то, что Node.js и Chrome оба используют V8 [см. этот комментарий ]):

const dynamicName = "foo" + Math.floor(Math.random() * 1000);
const obj = {
  [dynamicName]: function() {
  }
};
const f = obj[dynamicName];
const inst = new f();
console.log(f.name);	// works
console.log(f);				// nope (on Chrome)
console.log(inst);		// nope (on Chrome)
Look in the real console.

К сожалению, даже несмотря на то, что Function#name теперь является определенной функцией функций, как вы обнаружили, это name не всегда то, что внутренности движков JavaScript используют при трассировке стека и тому подобное (пока, надеюсь, это изменится по мере того, как name созревает; он был добавлен только в ES2015).

Если вам действительно нужно это сделать, это одно из немногих мест, где вы могли бы достичь для генерации и выполнения динамического кода, такого как new Function:

var Constructor = new Function("return function " + name + "() { };")();

Это делает следующее, но динамически используя name вместо nameGoesHere:

var Constructor = (function() {
    return function nameGoesHere() { };
})();

new Function - это то, что создает внешнюю функцию, которую мы немедленно выполняем.

Живой пример (посмотрите в реальной консоли для вывода):

// Constructor factory //
function type(name, prototype) {
    var Constructor = new Function("return function " + name + "() { };")();

    window[name] = Constructor ;
    return Constructor ;
}

// Creating constructor and instance //
type('Cat', { name:"", paws:4 }) ;
var chat = new Cat ;

// Tests //
console.log(Cat.name) ;
console.log(Cat) ;
console.log(chat) ;

Очевидно, это предполагает, что вы не получаете name из ненадежного источника.

  • 0
    Следует отметить, что это определенно не должно использоваться в производстве.
  • 1
    @JonasW. - Это абсолютно нормально использовать в производстве, если name не из ненадежного источника.
Показать ещё 15 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню