JavaScriptのtoString()関数をオーバーライドして、デバッグに意味のある出力を提供することは可能ですか?


115

console.log()私がJavaScriptプログラムでオブジェクトを実行すると、出力が表示されるだけです[object Object]。これは、それがどのオブジェクト(またはどのタイプのオブジェクト)であるかを理解するのにあまり役立ちません。

C#ではToString()、オブジェクトのデバッガー表現をカスタマイズできるようにオーバーライドすることに慣れています。JavaScriptで私ができる類似のものはありますか?


2
出力は、変数が何を保持しているかを伝える最も信頼できる方法であることがわかります(または少なくともより優れていますtypeof)。
アレックス

回答:


102

toStringJavaScriptでもオーバーライドできます。例を参照してください:

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でオブジェクトタイプ名を決定する方法については、この説明を参照してください。


8
trueの場合、アラート関数はプロトタイプtoStringプロパティをオーバーライドする関数の戻り値を表示しますが、Object.prototype.toString.call(f)引き続き表示します[object Object]
フレデリククラウトヴァルト

14
'Object.prototype.toString.call(f)は引き続き[オブジェクトオブジェクト]を表示します。' ええ、それは「Foo.prototype.toString」とは完全に異なる関数なので、笑
Triynko

5
私のような他の人がここにいる場合、ES6でSybmol.toStringTagを使用して、Object.prototype.toString.callの動作をカスタマイズできます。developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…–
TLadd

32

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]'

更新

E2015は、このようなもののために非常に良く構文を提供していますが、次のようなtranspiler使用する必要がありますバベル

// 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'

5
console.log( '' + foo); これは私があなたの答えに到達するまでtoString実装を見なかった問題でした。
ahmadalibaloch 2015

13

ブラウザJSでデバッグ可能な出力を取得する簡単な方法は、オブジェクトをJSONにシリアル化することです。だからあなたはのような電話をかけることができます

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

したがって、例として、alert("Blah! " + JSON.stringify({key: "value"}));テキストでアラートを生成しますBlah! {"key":"value"}


それはかなり便利です。出力は私が想像する少し巨大かもしれませんが、ピンチで動作します!
devios1

@dev便利ですが、toString()をオーバーライドしません。
Dan Dascalescu

10

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()メソッドをオーバーライドするだけです。

簡単な例:

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}"

9
このコードはOPのconsole.logの問題を解決しません。少なくともnode.js v0.10.*やChrome では問題は解決しませんVersion 32.0.1700.102。toStringを直接呼び出す(lame)または型強制(lamer)を使用するとこれが機能しますが、console [/ info | log /]は古いpre-mod toStringを使用します。
james_womack 14年

1
それは2019年になり、nodejsとchrome pretty-printオブジェクトの両方が単独で使用されるため、(オブジェクトを文字列に追加するときの)強制は、この質問をググる唯一のユースケースです。
Klesun

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



3

'Symbol.toStringTag'プロパティをカスタムオブジェクトまたはクラスに追加します。

に割り当てられている文字列値は、デフォルトで文字列の説明になります。 Object.prototype.toString()メソッド。

例えば:

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

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

マップやプロミスなどの一部のJavaScriptタイプには、組み込みのtoStringTagシンボルが定義されています

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

のでSymbol.toStringTagあり、よく知られているシンボルが、我々はそれを参照し、上記のタイプはSymbol.toStringTagプロパティを持っていることを確認することができます-

new Map()[Symbol.toStringTag] // 'Map'
Promise.resolve()[Symbol.toStringTag] // 'Promise'

これをtoString()直接オーバーライドすることと一緒に、達成する唯一の方法はありfunction MyObj() {} Object.prototype.toString.call(new MyObj()) // "[object MyObj]"ますか?
tonix

1
@tonix-そう思います...別の方法がある場合はお知らせください;)
Danield

0

Chromeコンソールログを使用すると、オブジェクトを検査できます。


はい、オブジェクトのみを出力する場合はそうです。これは便利です。ただし、他のデータを含めるために使用する可能性がある文字列の一部として出力したい場合もあり、そのフォームをなんらかの方法でカスタマイズできると便利です。
devios1

6
console.logで追加の引数を使用して、オブジェクトを文字列にインラインで出力できることを発見しましたconsole.log("this is my object:", obj)
devios1

0

-この操作は完了するまでに時間がかかります。また、Mozillaのドキュメントによれば、使用は推奨されていません:https : //developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/proto

-どうやら、最近のブラウザは.prototypeを非推奨にしており、ECMA6は代わりにproper__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());

0

次に、Mapオブジェクトを文字列化する方法の例を示します。

  Map.prototype.toString = function() {

    let result = {};

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

    return JSON.stringify(result);
  };

-1

カスタムオブジェクトに独自の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);
}

-1

を上書きするのtoString()ではなく、Prototype JavaScript Libraryを含めると、を使用Object.inspect()して、はるかに有用な表現を取得できます。

最も人気のあるフレームワークには、同様のものが含まれています。


-1

JSで拡張またはオーバーライドできます

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


これは、2011年の回答に同じ解決策を与えるものをどのように追加しますか?
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;
};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.