Можно ли переопределить функцию JavaScript toString() для обеспечения значимого вывода для отладки?

Когда я console.log() объект в моей программе JavaScript, я просто вижу вывод [object Object], что не очень полезно при определении того, какой объект (или даже какой тип объекта) он имеет.

В С# я использую переопределение ToString(), чтобы иметь возможность настраивать представление отладчика объекта. Есть ли что-то подобное в JavaScript?

Ответ 1

Вы можете переопределить toString в Javascript. Пример:

function Foo() 
{
}

// toString override added to prototype of Foo class
Foo.prototype.toString = function()
{
    return "[object Foo]";
}

var f = new Foo();
alert(f);  // popup displays [object Foo]

См. эту дискуссию о том, как определить имя типа объекта в JavaScript.

Ответ 2

Сначала переопределите toString для вашего объекта или прототипа:

var Foo = function(){};
Foo.prototype.toString = function(){return 'Pity the Foo';};

var foo = new Foo();

Затем преобразуйте в строку, чтобы увидеть строковое представление объекта:

//using JS implicit type conversion
console.log('' + foo);

Если вам не нравится дополнительная набрав, вы можете создать функцию, которая записывает строковые представления своих аргументов на консоль:

var puts = function(){
    var strings = Array.prototype.map.call(arguments, function(obj){
        return '' + obj;
    });
    console.log.apply(console, strings);
};

Использование:

puts(foo)  //logs 'Pity the Foo'

puts(foo, [1,2,3], {a: 2}) //logs 'Pity the Foo 1,2,3 [object Object]'

Update

E2015 обеспечивает гораздо более хороший синтаксис для этого материала, но вам придется использовать транспилер, например Babel:

// override `toString`
class Foo {
  toString(){
    return 'Pity the Foo';
  }
}

const foo = new Foo();

// utility function for printing objects using their `toString` methods
const puts = (...any) => console.log(...any.map(String));

puts(foo); // logs 'Pity the Foo'

Ответ 3

Легкий способ получить отлаживаемый вывод в браузере JS - это просто сериализовать объект в JSON. Таким образом, вы можете позвонить, например

console.log ("Blah: " + JSON.stringify(object));

Итак, для примера alert("Blah! " + JSON.stringify({key: "value"})); выдает предупреждение с текстом Blah! {"key":"value"}

Ответ 4

Просто переопределите метод toString().

Простой пример:

var x = {foo: 1, bar: true, baz: 'quux'};
x.toString(); // returns "[object Object]"
x.toString = function () {
    var s = [];
    for (var k in this) {
        if (this.hasOwnProperty(k)) s.push(k + ':' + this[k]);
    }
    return '{' + s.join() + '}';
};
x.toString(); // returns something more useful

Это еще лучше, если вы определяете новый тип:

function X()
{
    this.foo = 1;
    this.bar = true;
    this.baz = 'quux';
}

X.prototype.toString = /* same function as before */

new X().toString(); // returns "{foo:1,bar:true,baz:quux}"

Ответ 5

Если вы используете Node, стоит рассмотреть util.inspect.

var util = require('util')

const Point = {
  x: 1,
  y: 2,
  [util.inspect.custom]: function(depth) { return `{ #Point ${this.x},${this.y} }` }

}

console.log( Point );

Это даст:

{ #Point 1,2 }

Пока версия не проверяет печать:

{ x: 1, y: 2 }

Ответ 6

Если объект определяется самим собой, вы всегда можете добавить переопределение toString.

//Defined car Object
var car = {
  type: "Fiat",
  model: 500,
  color: "white",
  //.toString() Override
  toString: function() {
    return this.type;
  }
};

//Various ways to test .toString() Override
console.log(car.toString());
console.log(car);
alert(car.toString());
alert(car);

//Defined carPlus Object
var carPlus = {
  type: "Fiat",
  model: 500,
  color: "white",
  //.toString() Override
  toString: function() {
    return 'type: ' + this.type + ', model: ' + this.model + ', color:  ' + this.color;
  }
};

//Various ways to test .toString() Override
console.log(carPlus.toString());
console.log(carPlus);
alert(carPlus.toString());
alert(carPlus);

Ответ 8

Журнал консоли Chrome позволяет вам проверять объект.

Ответ 9

Вы можете предоставить любым настраиваемым объектам свои собственные методы toString или написать общий, который вы можете вызвать на объект, который вы ищете -

Function.prototype.named= function(ns){
    var Rx=  /function\s+([^(\s]+)\s*\(/, tem= this.toString().match(Rx) || "";
    if(tem) return tem[1];
    return 'unnamed constructor'
}

function whatsit(what){
    if(what===undefined)return 'undefined';
    if(what=== null) return 'null object';
    if(what== window) return 'Window object';
    if(what.nodeName){
        return 'html '+what.nodeName;
    }
    try{
        if(typeof what== 'object'){
            return what.constructor.named();
        }
    }
    catch(er){
        return 'Error reading Object constructor';
    }
    var w=typeof what;
    return w.charAt(0).toUpperCase()+w.substring(1);
}

Ответ 10

Вместо того, чтобы переопределять toString(), если вы включили Prototype JavaScript Library, вы можете использовать Object.inspect(), чтобы получить гораздо более полезное представление.

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

Ответ 11

Вы можете расширить или переопределить в JS

String.prototype.toString = function() {
    return this + "..."
}
document.write("Sergio".toString());

Ответ 12

Для выполнения операции -This требуется много времени, и ее использование не рекомендуется в соответствии с документами mozilla: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/proto

-Apparently, современные браузеры, устаревшие.prototype и ECMA6, вместо этого используют use__proto__.

Например, если вы определяете свое собственное геопозиционирование объектов, вы должны вызывать свойство __proto__, а не .prototype:

var  geoposition = {

        lat: window.pos.lat,
        lng: window.pos.lng
    };

geoposition.__proto__.toString = function(){ return "lat: "+this.lat+", lng: "+this.lng }
console.log("Searching nearby donations to: "+geoposition.toString());

Ответ 13

A simple format Date function using Javascript prototype, it can be used for your purpose

https://gist.github.com/cstipkovic/3983879 :

Date.prototype.formatDate = function (format) {
    var date = this,
        day = date.getDate(),
        month = date.getMonth() + 1,
        year = date.getFullYear(),
        hours = date.getHours(),
        minutes = date.getMinutes(),
        seconds = date.getSeconds();

    if (!format) {
        format = "MM/dd/yyyy";
    }

    format = format.replace("MM", month.toString().replace(/^(\d)$/, '0$1'));

    if (format.indexOf("yyyy") > -1) {
        format = format.replace("yyyy", year.toString());
    } else if (format.indexOf("yy") > -1) {
        format = format.replace("yy", year.toString().substr(2, 2));
    }

    format = format.replace("dd", day.toString().replace(/^(\d)$/, '0$1'));

    if (format.indexOf("t") > -1) {
        if (hours > 11) {
            format = format.replace("t", "pm");
        } else {
            format = format.replace("t", "am");
        }
    }

    if (format.indexOf("HH") > -1) {
        format = format.replace("HH", hours.toString().replace(/^(\d)$/, '0$1'));
    }

    if (format.indexOf("hh") > -1) {
        if (hours > 12) {
            hours -= 12;
        }

        if (hours === 0) {
            hours = 12;
        }
        format = format.replace("hh", hours.toString().replace(/^(\d)$/, '0$1'));
    }

    if (format.indexOf("mm") > -1) {
        format = format.replace("mm", minutes.toString().replace(/^(\d)$/, '0$1'));
    }

    if (format.indexOf("ss") > -1) {
        format = format.replace("ss", seconds.toString().replace(/^(\d)$/, '0$1'));
    }

    return format;
};