กำลังส่งไปยังสตริงใน JavaScript


184

ฉันพบสามวิธีในการแปลงตัวแปรเป็นStringJavaScript
ฉันค้นหาสามตัวเลือกเหล่านี้ในซอร์สโค้ด jQuery และพวกมันใช้งานอยู่
ฉันต้องการทราบว่ามีความแตกต่างระหว่างพวกเขาหรือไม่:

value.toString()
String(value)
value + ""

การสาธิต

พวกเขาทั้งหมดผลิตผลลัพธ์เดียวกัน แต่หนึ่งในนั้นดีกว่าคนอื่น ๆ ?
ฉันจะบอกว่า+ ""มีข้อได้เปรียบที่ช่วยประหยัดตัวละครบางตัว แต่นั่นไม่ใช่ข้อได้เปรียบที่ยิ่งใหญ่อีกแล้ว


1
ดูเหมือนว่าถ้าทุกสิ่งเท่ากันมาตรฐานtoString()จะเป็นหนทางไป
asawyer

1
@asawyer และทำไมเป็นเช่นนั้น? หากพวกเขาทั้งหมดผลิตผลลัพธ์เดียวกันและทำเช่นเดียวกันเลือกหนึ่งและไปกับมัน นี่คือความคิดเห็นของฉันหากเป็นกรณีนี้จริง
gdoron ให้การสนับสนุนโมนิก้า

1
สองวิธีแรกควรเท่ากัน (คุณควรตรวจสอบมาตรฐาน แต่ Constructor จะเรียก toString) หนึ่งในสามมักสร้างผลลัพธ์เดียวกัน แต่เกี่ยวข้องกับกลไกที่แตกต่างกันมาก (นอกเหนือจากความเร็วมันเกี่ยวข้องกับการเรียกที่แตกต่างกันดังนั้นมันอาจไม่ใช่สิ่งที่คุณคาดหวังสำหรับวัตถุทุกชนิด)
Adriano Repetti

6
ในความคิดของฉันtoStringเป็นวิธีที่ชัดเจนที่สุดในการทำเอกสารด้วยตนเองเกี่ยวกับความจริงที่ว่าคุณกำลังพยายามที่จะได้สตริงเทียบเท่ากับวัตถุ String(...)ค่อนข้างป้านและvalue + ""แฮกเล็กน้อย นอกจากนี้ยังช่วยให้คุณสามารถแทนที่ค่าเริ่มต้นtoStringด้วยการใช้งานที่กำหนดเองหากคุณจำเป็นต้องสมมติว่าเป็นประโยชน์เล็กน้อย
asawyer

2
@Adriano แต่+ ""มันเป็นวิธีที่เร็วที่สุดตาม jsperf ดังนั้น ... มันทำได้อีกวิธีหนึ่งที่ฉันเดา
gdoron สนับสนุน Monica

คำตอบ:


213

พวกเขาจะทำงานแตกต่างกันเมื่อเป็นvaluenull

  • null.toString()เกิดข้อผิดพลาด - ไม่สามารถเรียกเมธอด 'toString' เป็นโมฆะ
  • String(null)ผลตอบแทน - "null"
  • null + ""ผลตอบแทนก็ - "null"

พฤติกรรมที่คล้ายกันมากเกิดขึ้นถ้าvalueเป็นundefined(ดูคำตอบของ jbabey )

นอกจากนั้นยังมีความแตกต่างของประสิทธิภาพการทำงานเล็กน้อยซึ่งหากคุณไม่ได้ใช้งานในลูปขนาดใหญ่คุณก็ไม่ควรกังวล


นี่คือความแตกต่างที่น่าสนใจ ดังนั้นคุณควรละเว้นจากการใช้toString()เมื่อคุณไม่ได้ตรวจสอบnullเลย
Sammy S.

@SammyS ไม่ทราบว่าการพิมพ์nullหรือundefinedไปที่หน้าจอเป็นพฤติกรรมที่พึงประสงค์มากกว่าข้อผิดพลาดของ javascript หรือไม่
Justus Romijn

@JustusRomijn: จริงแน่นอน ในระหว่างนี้ฉันเริ่มใช้ประเภทตัวเลือกเพื่อจัดการข้อผิดพลาดดังกล่าว
Sammy S.

คุณสามารถตรวจสอบตัวแปรหล่อเหล่านี้ด้วย typeof เพื่อตรวจสอบสตริง typeof (null + '') == 'string'
Bruce Lim

4
มีอีกกรณีหนึ่งเมื่อพวกเขาทำงานแตกต่างกัน v + ''ส่งคืนผลลัพธ์ที่ไม่ถูกต้องหาก v มีเมธอด toString () และ valueOf () การต่อข้อมูลจะละเว้น toString () และจะใช้ valueOf () ตัวอย่างคลาสที่การต่อข้อมูลล้มเหลว: github.com/processing-js/processing-js/blob/
......

26

มีความแตกต่าง แต่อาจไม่เกี่ยวข้องกับคำถามของคุณ ตัวอย่างเช่นต้นแบบ toString ไม่มีอยู่ในตัวแปรที่ไม่ได้กำหนด แต่คุณสามารถส่งแบบไม่กำหนดไปยังสตริงโดยใช้อีกสองวิธี:

var foo;

var myString1 = String(foo); // "undefined" as a string

var myString2 = foo + ''; // "undefined" as a string

var myString3 = foo.toString(); // throws an exception

http://jsfiddle.net/f8YwA/


3
String()ถ้าตัวแปรไม่ได้เลยที่กำหนดไว้คุณจะยังคงได้รับข้อผิดพลาดสำหรับ ตัวอย่าง: String(test);พ่นUncaught ReferenceError: test is not definedในขณะที่จะมีผลในvar test; String(test); "undefined"
แอนโธนี

17

พวกเขาทำงานเหมือนกัน แต่toStringยังให้วิธีการแปลงสตริงเลขฐานสองฐานแปดหรือเลขฐานสิบหก:

ตัวอย่าง:

var a = (50274).toString(16)  // "c462"
var b = (76).toString(8)      // "114"
var c = (7623).toString(36)   // "5vr"
var d = (100).toString(2)     // "1100100"

9

จากการทดสอบ JSPerfพวกเขาต่างความเร็ว แต่ถ้าคุณไม่ได้ใช้มันในปริมาณมาก ๆ พวกมันควรจะทำงานได้ดี

เพื่อความสมบูรณ์: ตามที่asawyerพูดถึงแล้วคุณยังสามารถใช้.toString()วิธีนี้ได้


2
jsperf นั้นมีการทดสอบเดียวกันสองครั้งฉันแก้ไขและnew String()ส่งคืนวัตถุที่ไม่ใช่String
gdoron สนับสนุน Monica

new String()ส่งคืนวัตถุใช่ String()อย่างไรก็ตามส่งคืนสตริงซึ่งเป็นหนึ่งในคำถาม
Connell

2
สิ่งนี้ไม่เป็นความจริงทั้งหมด อย่างที่คุณเห็นจากผลลัพธ์การเชื่อมสตริงว่างและวัตถุไม่ให้ผลลัพธ์เดียวกันกับการเชื่อมวัตถุและสตริงว่าง นอกจากนี้ยังnew String(blarg)ให้Stringวัตถุที่คุณสามารถโทรหาtoString()ได้ ในดีบักเกอร์ Chrome ของฉันพวกมันให้ผลลัพธ์วัตถุชนิดเดียวกันได้อย่างมีประสิทธิภาพยกเว้นความแตกต่างที่กล่าวไว้
Sammy S.

@SammyS คุณช่วยเพิ่มตัวอย่างผลการปฏิบัติงานให้กับคำตอบของคุณได้ไหม? ปัจจุบันลิงก์ jsperf หยุดทำงานและจะกลับมาอีกครั้งในอีก 5 ปีข้างหน้า
mxmlnkn

9

นอกเหนือจากข้างต้นทั้งหมดแล้วเราควรทราบว่าสำหรับค่าที่กำหนดv:

  • String(v) โทร v.toString()
  • '' + vการโทรv.valueOf()ก่อนส่งนักแสดงประเภทอื่น ๆ

ดังนั้นเราสามารถทำสิ่งที่ชอบ:

var mixin = {
  valueOf:  function () { return false },
  toString: function () { return 'true' }
};
mixin === false;  // false
mixin == false;    // true
'' + mixin;       // "false"
String(mixin)     // "true"

ทดสอบใน FF 34.0 และโหนด 0.10


8

หากคุณตกลงกับค่า null, ไม่ได้กำหนด, NaN, 0 และ false ทั้งหมดที่ส่งไปยัง '' (s ? s+'' : '')จะเร็วขึ้น

ดูhttp://jsperf.com/cast-to-string/8

หมายเหตุ - ในขณะนี้มีความแตกต่างที่สำคัญในเบราว์เซอร์


4

ตัวอย่างโลกจริง: log("foo is {} and bar is {}", param1, param2)ฉันมีฟังก์ชั่นบันทึกที่สามารถเรียกว่ามีจำนวนข้อของพารามิเตอร์: หากมีการDEBUGตั้งธงที่จะวงเล็บได้รับการแทนที่ด้วยพารามิเตอร์ที่กำหนดและสตริงถูกส่งไปยังtrue console.log(msg)พารามิเตอร์สามารถและจะเป็น Strings, Numbers และอะไรก็ได้ที่อาจถูกส่งคืนโดยการโทร JSON / AJAX หรืออาจเป็นแบบnullนั้นก็ได้

  • arguments[i].toString()ไม่ใช่ตัวเลือกเนื่องจากnullค่าที่เป็นไปได้(ดูคำตอบของ Connell Watkins)
  • JSLint arguments[i] + ""จะบ่นเกี่ยวกับ สิ่งนี้อาจมีหรือไม่มีอิทธิพลต่อการตัดสินใจว่าจะใช้อย่างไร บางคนปฏิบัติตามอย่างเคร่งครัดกับ JSLint
  • ในบางเบราว์เซอร์การเชื่อมสตริงว่างเปล่านั้นเร็วกว่าการใช้ฟังก์ชั่นสตริงหรือตัวสร้างสตริง (ดูการทดสอบ JSPerf ใน Sammys S. answer เล็กน้อย) ใน Opera 12 และ Firefox 19 การต่อสตริงว่างจะเร็วขึ้น rediculously (95% ใน Firefox 19) - หรืออย่างน้อยJSPerfก็บอกเช่นนั้น

1

ในหน้านี้คุณสามารถทดสอบประสิทธิภาพของแต่ละวิธีด้วยตนเอง :)

http://jsperf.com/cast-to-string/2

ที่นี่ในทุกเครื่องและเบราว์เซอร์ '' "+ str 'เป็นหนึ่งที่เร็วที่สุด str (สตริง) ช้าที่สุด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.