2010-03-21 25 views
100

Javascript'te her nesnenin bir valueOf() ve toString() yöntemi vardır. Bir dize dönüşümü çağrıldığında toString() yönteminin çağrıldığını düşünürdüm, ama görünüşe göre valueOf() tarafından kondu. ÖrneğinvalueOf() vs. toString() Javascript'te

x karmaşık bir sayı, örneğin, ben valueOf isteyeyim olsaydı

var x = {toString: function() {return "foo"; }, 
     valueOf: function() {return 42; }}; 
window.console.log ("x="+x); 
window.console.log ("x="+x.toString()); 

.. Bu kadar geriye beni çarptığı

x=42 
x=foo 

yazdırır kodu() vermek üzere bana onun büyüklüğü, ama ne zaman bir dizeye dönüştürmek istediğimde "a + bi" gibi bir şey isterdim. Ve bir dizgeyi ima eden bağlamlarda toString() 'i açıkça çağırmak istemem.

Bu şekilde mi oluyor?

+5

window.console.log (x); 'veya' alert (x); 'denediniz mi? – Li0liQ

+4

Sırasıyla "Nesne" ve "foo" verir. Eğlenceli şeyler. – brainjam

+0

Aslında, uyarı (x); "foo" ve window.console.log (x) verir; Firebug’a ve Chrome konsolundaki tüm Nesneye "foo {}" verir. – brainjam

cevap

95

("x =" + x) neden "x = value" değerini verir ve "x = tostring" olmasın " takip ediliyor. "+" Değerini değerlendirirken, javascript önce işlenenlerin ilkel değerlerini toplar ve sonra her ilkel türüne göre ekleme veya birleştirme uygulanıp uygulanmayacağına karar verir.

Yani, bu onu

a + b: 
    pa = ToPrimitive(a) 
    if(pa is string) 
     return concat(pa, ToString(b)) 
    else 
     return add(pa, ToNumber(b)) 

çalıştığını nasıl düşündüğünü ve bu aslında orijinal nesneye,

olduğunu
a + b: 
    pa = ToPrimitive(a) 
    pb = ToPrimitive(b)* 
    if(pa is string || pb is string) 
     return concat(ToString(pa), ToString(pb)) 
    else 
     return add(ToNumber(pa), ToNumber(pb)) 

, toString valueOf sonucu uygulanan ne olduğudur .

Daha fazla bilgi için, ECMAScript Dil Belirtimi bölümünde 11.6.1 The Addition operator (+) bölümüne bakın. dize bağlamında denilen *


, ToPrimitive çağırmak toString, ama '+' her tür içeriği zorlamaz çünkü bu, burada durum böyle değil.

+2

"aslında" bloğunda şartlı değil "if (pa dizedir && pb dizedir)" okuma mıdır? I.e "||" yerine "&&" ? – brainjam

+3

Standart kesinlikle "veya" yazıyor (bağlantıya bakın). – user187291

+0

Evet, haklısın. – brainjam

64

İşte cevap ulaşmadan, biraz daha ayrıntı verilmiştir:

var x = { 
    toString: function() { return "foo"; }, 
    valueOf: function() { return 42; } 
}; 

alert(x); // foo 
"x=" + x; // "x=42" 
x + "=x"; // "42=x" 
x + "1"; // 421 
x + 1; // 43 
["x=", x].join(""); // "x=foo" 

toString fonksiyonu genel olarak valueOf tarafından "uydurma" değilolduğunu. ECMAScript standardı aslında bu soruyu oldukça iyi cevaplıyor. Her nesnenin isteğe bağlı olarak hesaplanan [[DefaultValue]] özelliği vardır. Bu mülk için sorulduğunda, tercüman da ne tür bir değer beklediği için bir "ipucu" sağlar. İpucu String ise, valueOf'dan önce kullanılır. Ancak, ipucu Number ise, önce valueOf kullanılacaktır. Yalnızca bir tane varsa veya ilkel olmayan bir öğe döndürdüğünde, genellikle diğerini ikinci seçenek olarak çağırır.

+ işleci, ilk işlenen bir dize değeri olsa bile her zaman ipucunu Number sağlar. Number gösterimi için x soran olsa bile, ilk işlenen [[DefaultValue]] bir dize döndürdüğünden, bu dizge birleştirme yapar.

Dize birleştirme için toString çağrıldığından emin olmak istiyorsanız, bir dizi ve .join("") yöntemini kullanın.

(ActionScript 3.0 hafifçe ancak + davranışını değiştirir. Her iki işlenen bir String ise, bir dizge birleştirme işlemi olarak kabul ederiz ve onu [[DefaultValue]] çağırdığında ipucu String kullanın. Yani, AS3'te, bu örneği "foo, x = foo, foo = x, foo1, 43, x = foo" verir.

+0

Ayrıca 'valueOf' veya' olmayan ilkeller iade toString', onlar göz ardı unutmayın. Hiçbiri yoksa veya bir ilkel döndürmezse, bir 'TypeError' atılır. – bcherry

+1

Teşekkürler bcherry, bu umduğum cevapların kalibresi. Ancak x + "x =" olmamalıdır; verim "42x ="? Ve x + "1"; Verim 421? Ayrıca , sen ECMAScript standardının ilgili kısmı için bir URL var mı? – brainjam

+0

Oops, evet. Sırasıyla "1" + 1 'testinden bir yazım hatası ve bir hata. Orijinal gönderiyi düzenledim. Teşekkürler :) ECMAScript 3 belirtimi (pdf): http://www.mozilla.org/js/language/E262-3.pdf "8.6.2.6 [[DefaultValue]] aradınız (ipucu) ', sayfa 35. – bcherry