Hata ayıklama için anlamlı çıktı sağlamak üzere JavaScript'in toString () işlevini geçersiz kılmak mümkün müdür?


115

Ne zaman console.log()benim JavaScript programında bir nesne, sadece çıkış görmek [object Object]nesne (hatta veya hangi nesnenin türü) onun ne endam çok yararlı değildir.

C # 'da ToString(), bir nesnenin hata ayıklayıcı temsilini özelleştirebilmek için geçersiz kılmaya alışkınım . JavaScript'te yapabileceğim benzer bir şey var mı?


2
Çıktının, bir değişkenin ne içerdiğini (veya en azından ondan daha iyi olduğunu typeof) söylemenin en güvenilir yolu olduğunu düşünüyorum .
alex

Yanıtlar:


103

toStringJavascript'te de geçersiz kılabilirsiniz . Örneğe bakın:

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]

JavaScript'te nesne türü adının nasıl belirleneceği hakkındaki bu tartışmaya bakın .


8
Bu doğru olsa da, uyarı işlevi prototip toStringözelliğini geçersiz kılan işlevin dönüş değerini Object.prototype.toString.call(f)göstermeye devam edecektir [object Object].
Frederik Krautwald

14
'Object.prototype.toString.call (f), [object Object] öğesini göstermeye devam edecek.' Evet, çünkü bu 'Foo.prototype.toString'den tamamen farklı bir işlev, lol.
Triynko

5
Benim gibi bir başkasının burada kalması durumunda, Object.prototype.toString.call davranışını özelleştirmek için ES6'da Sybmol.toStringTag'i kullanabilirsiniz. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
TLadd

32

toStringNesneniz veya prototip için ilk geçersiz kılma :

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

var foo = new Foo();

Daha sonra nesnenin dize temsilini görmek için dizeye dönüştürün:

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

Fazladan yazmayı sevmiyorsanız, bağımsız değişkenlerinin dize temsillerini konsola kaydeden bir işlev oluşturabilirsiniz:

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

Kullanımı:

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

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

Güncelleme

E2015, bu şeyler için çok daha hoş bir sözdizimi sağlar, ancak Babel gibi bir aktarıcı kullanmanız gerekecek :

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

6
console.log ('' + foo); cevabınıza ulaşana kadar herhangi bir toString uygulaması görmedim sorun buydu.
ahmadalibaloch

13

Tarayıcı JS'de hata ayıklanabilir çıktı almanın kolay bir yolu, nesneyi JSON'a serileştirmektir. Böylece bir arama yapabilirsin

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

Dolayısıyla, bir örnek olarak, alert("Blah! " + JSON.stringify({key: "value"}));metinle bir uyarı oluştururBlah! {"key":"value"}


Bu oldukça kullanışlıdır. Çıktı, tahmin ettiğim kadarıyla biraz büyük olabilir, ancak bir tutam işe yarıyor!
devios1

@dev Kullanışlı, ancak toString () geçersiz kılmaz.
Dan Dascalescu

10

Node kullanıyorsanız, dikkate almaya değer olabilir 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 );

Bu şunları verecektir:

{ #Point 1,2 }

İncelemesiz sürüm yazdırılırken:

{ x: 1, y: 2 }

6

Sadece toString()yöntemi geçersiz kıl .

Basit örnek:

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

Yeni bir tür tanımladığınızda daha da iyi olur:

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
Bu kod, OP'nin console.log sorununu çözmez, en azından node.js v0.10.*veya Chrome'da çözmez Version 32.0.1700.102. Doğrudan toString'i çağırırken (lame) veya tür zorlaması (lamer) kullanırken bununla çalışacaktır, console [/ info | log /] eski ön-mod toString için kullanır.
james_womack

1
Şimdi 2019 ve hem nodejs hem de chrome pretty-print nesneleri kendi başlarına, bu yüzden zorlama (nesneyi bir dizeye eklediğinizde) bu soruyu google'da aratacağınıza inanıyorum.
Klesun

6

Nesne kendiniz tanımlanmışsa, her zaman bir toString geçersiz kılma ekleyebilirsiniz.

//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' özelliğini özel nesneye veya sınıfa ekleyin .

Object.prototype.toString()Yöntem tarafından dahili olarak erişildiğinden, kendisine atanan dize değeri varsayılan dize açıklaması olacaktır .

Örneğin:

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

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

Haritalar ve Sözler gibi bazı Javascript türlerinde yerleşik bir toStringTagsembol tanımlanmıştır

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

Çünkü Symbol.toStringTagbir olan tanınmış sembol , biz onu ve yukarıdaki türleri Symbol.toStringTag özelliğe sahip olduklarını doğrulamak -

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

Bunu toString()başarmanın tek yolu doğrudan geçersiz kılmakla birlikte function MyObj() {} Object.prototype.toString.call(new MyObj()) // "[object MyObj]"mi?
tonix

1
@tonix - Sanırım öyle ... Başka bir yolu varsa, lütfen bana bildirin;)
Danield

0

Chrome konsol günlüğü, nesneyi incelemenizi sağlar.


Evet, sadece kullanışlı olan nesneyi çıkarırsam bu doğrudur. Ancak bazen, onu başka verileri içermek için kullanabileceğim bir dizenin parçası olarak çıkarmak istiyorum ve bu formu bir şekilde özelleştirebilseydim güzel olurdu.
devios1

6
Sadece çıkış iple satır içi nesneleri için bir console.log ek argümanlar kullanabilirsiniz keşfetti: console.log("this is my object:", obj).
devios1

0

-Bu işlemin tamamlanması çok zaman alır ve mozilla belgelerine göre kullanımı önerilmez: https://developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/proto

-Görünüşe göre, modern tarayıcılar .prototype'ı kullanımdan kaldırmış ve ECMA6 bunun yerine uygun__proto__ kullanımını belirtmiştir.

Size kendi nesne tanımlıyorsanız, Yani, örneğin, geoposition aramak gerekir __proto__ yerine özelliğini .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

Aşağıda, bir Map nesnesinin nasıl dizileneceği bir örnek verilmiştir:

  Map.prototype.toString = function() {

    let result = {};

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

    return JSON.stringify(result);
  };

-1

Herhangi bir özel nesneye kendi toString yöntemlerini verebilir veya baktığınız nesnede çağırabileceğiniz genel bir tane yazabilirsiniz.

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

JS'de genişletebilir veya geçersiz kılabilirsiniz

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


Bu, 2011 yanıtlarına aynı çözümü veren herhangi bir şeyi nasıl ekler?
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;
};
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.