Apakah mungkin untuk mengganti fungsi toString () JavaScript untuk memberikan keluaran yang berarti untuk debugging?

115

Ketika saya console.log()sebuah objek dalam program JavaScript saya, saya hanya melihat hasilnya [object Object], yang tidak terlalu membantu dalam mencari tahu objek apa (atau bahkan tipe objek apa) itu.

Di C # saya terbiasa menimpa ToString()agar dapat menyesuaikan representasi debugger dari suatu objek. Apakah ada hal serupa yang dapat saya lakukan di JavaScript?

devios1
sumber
2
Saya menemukan bahwa output adalah cara paling andal untuk memberi tahu Anda apa yang dimiliki variabel (atau setidaknya lebih baik dari typeof).
alex

Jawaban:

103

Anda juga dapat mengganti toStringdalam Javascript. Lihat contoh:

function Foo() {}

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

var f = new Foo();
console.log("" + f); // console displays [object Foo]

Lihat diskusi ini tentang cara menentukan nama tipe objek di JavaScript.

Michael Spector
sumber
8
Meskipun benar, fungsi peringatan akan menampilkan nilai kembali dari fungsi yang menggantikan toStringproperti prototipe , Object.prototype.toString.call(f)akan tetap ditampilkan [object Object].
Frederik Krautwald
14
'Object.prototype.toString.call (f) masih akan menampilkan [Object Object].' Ya, karena itu adalah fungsi yang sangat berbeda dari 'Foo.prototype.toString', lol.
Triynko
5
Jika orang lain seperti saya berakhir di sini, Anda dapat menggunakan Sybmol.toStringTag di ES6 untuk menyesuaikan perilaku Object.prototype.toString.call. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
TLadd
32

Timpa pertama toStringuntuk objek atau prototipe Anda:

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

var foo = new Foo();

Kemudian konversikan ke string untuk melihat representasi string dari objek:

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

Jika Anda tidak menyukai pengetikan tambahan, Anda dapat membuat fungsi yang mencatat representasi string dari argumennya ke konsol:

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

Pemakaian:

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

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

Memperbarui

E2015 menyediakan sintaks yang jauh lebih baik untuk hal ini, tetapi Anda harus menggunakan transpiler seperti 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'
Max Heiber
sumber
6
console.log ('' + foo); ini adalah masalah yang saya tidak melihat implementasi toString sampai saya mencapai jawaban Anda.
ahmadalibaloch
13

Cara mudah untuk mendapatkan keluaran yang dapat di-debug di JS browser adalah dengan membuat serialisasi objek ke JSON. Jadi Anda bisa menelepon seperti

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

Jadi misalnya, alert("Blah! " + JSON.stringify({key: "value"}));menghasilkan peringatan dengan teksBlah! {"key":"value"}

Paul V.
sumber
Itu sangat berguna. Outputnya bisa sedikit besar, saya bayangkan, tetapi berfungsi dalam keadaan darurat!
devios1
@dev Berguna, tetapi tidak menimpa toString ().
Dan Dascalescu
10

Jika Anda menggunakan Node, mungkin perlu dipertimbangkan 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 );

Ini akan menghasilkan:

{ #Point 1,2 }

Sedangkan versi tanpa pemeriksaan cetakan:

{ x: 1, y: 2 }
SystematicFrank
sumber
6

Ganti saja toString()metode ini.

Contoh sederhana:

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

Ini bahkan lebih baik ketika Anda mendefinisikan tipe baru:

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}"
Matt Ball
sumber
9
Kode ini tidak menyelesaikan masalah console.log OP, setidaknya tidak di node.js v0.10.*atau Chrome Version 32.0.1700.102. Saat memanggil toString secara langsung (lame) atau menggunakan pemaksaan tipe (lamer) akan bekerja dengan ini, konsol [/ info | log /] menggunakan toString pra-mod lama.
james_womack
1
Sekarang tahun 2019 dan nodejs dan chrome cukup mencetak objek dengan sendirinya, jadi paksaan (saat Anda menambahkan objek ke string) adalah satu-satunya kasus penggunaan Anda akan mencari pertanyaan ini di Google.
Klesun
6

Jika objek ditentukan sendiri, Anda selalu dapat menambahkan toString override.

//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);

Anak yang Diretas
sumber
5

Dengan literal template :

class Foo {
  toString() {
     return 'I am foo';
  }
}

const foo = new Foo();
console.log(`${foo}`); // 'I am foo'
sami
sumber
3

Tambahkan properti 'Symbol.toStringTag' ke objek atau kelas kustom.

Nilai string yang ditugaskan padanya akan menjadi deskripsi string default karena diakses secara internal oleh Object.prototype.toString()metode tersebut.

Sebagai contoh:

class Person {
  constructor(name) {
    this.name = name
  }
  get [Symbol.toStringTag]() {
    return 'Person';
  }
}

let p = new Person('Dan');
Object.prototype.toString.call(p); // [object Person]

Beberapa jenis Javascript seperti Maps dan Promises memiliki toStringTagsimbol bawaan yang ditentukan

Object.prototype.toString.call(new Map());       // "[object Map]"
Object.prototype.toString.call(Promise.resolve()); // "[object Promise]"

Karena Symbol.toStringTagmerupakan simbol yang terkenal , kita dapat mereferensikannya dan memverifikasi bahwa tipe di atas memiliki properti Symbol.toStringTag -

new Map()[Symbol.toStringTag] // 'Map'
Promise.resolve()[Symbol.toStringTag] // 'Promise'
Danield
sumber
Apakah ini bersama-sama dengan menimpa toString()secara langsung satu-satunya cara untuk mencapainya function MyObj() {} Object.prototype.toString.call(new MyObj()) // "[object MyObj]"?
tonix
1
@tonix - Saya rasa begitu ... Jika ada cara lain, beri tahu saya;)
Danield
0

Log konsol Chrome memungkinkan Anda memeriksa objek.

tomconte.dll
sumber
Ya, itu benar jika saya hanya mengeluarkan objek, yang berguna. Namun terkadang saya hanya ingin mengeluarkannya sebagai bagian dari string yang mungkin saya gunakan untuk memuat data lain dan alangkah baiknya jika saya dapat menyesuaikan formulir itu dengan beberapa cara.
devios1
6
Saya baru saja menemukan bahwa Anda dapat menggunakan argumen tambahan dalam console.log untuk keluaran objek inline dengan string: console.log("this is my object:", obj).
devios1
0

-Operasi ini membutuhkan banyak waktu untuk diselesaikan, dan penggunaannya tidak disarankan menurut dokumen mozilla: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/proto

-Tampaknya, browser modern tidak lagi menggunakan .prototype dan ECMA6 menetapkan penggunaan proper__proto__ sebagai gantinya.

Jadi misalnya, jika Anda mendefinisikan geoposisi objek Anda sendiri, Anda harus memanggil properti __proto__ daripada .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());
jmojico.dll
sumber
0

Berikut adalah contoh cara merangkai objek Map:

  Map.prototype.toString = function() {

    let result = {};

    this.forEach((key, value) => { result[key] = value;});

    return JSON.stringify(result);
  };
Agustí Sánchez
sumber
-1

Anda dapat memberi objek kustom apa pun metode toStringnya sendiri, atau menulis metode umum yang dapat Anda panggil pada objek yang Anda lihat-

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);
}
kennebec
sumber
-1

Daripada menimpa toString(), jika Anda menyertakan Prototipe JavaScript Library , Anda dapat menggunakanObject.inspect() untuk mendapatkan representasi yang jauh lebih berguna.

Kerangka kerja paling populer menyertakan sesuatu yang serupa.

codelahoma
sumber
-1

Anda dapat memperpanjang atau mengganti di JS

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

ch2o
sumber
Bagaimana ini menambahkan sesuatu pada jawaban 2011 yang memberikan solusi yang sama?
Dan Dascalescu
-3
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;
};
aricca
sumber