Sự khác biệt giữa String (value) so với value.toString ()


104

Javascript có rất nhiều "thủ thuật" xung quanh các loại và chuyển đổi loại, vì vậy tôi đang tự hỏi liệu 2 phương pháp này có giống nhau không hoặc có một số trường hợp góc khiến chúng khác nhau?

Câu trả lời:


121

Chúng không hoàn toàn giống nhau và trên thực tế, phương thức khởi tạo Chuỗi được gọi là một hàm (ví dụ đầu tiên của bạn), ở cuối sẽ gọi toStringphương thức của đối tượng được truyền vào, ví dụ:

var o = { toString: function () { return "foo"; } };
String(o); // "foo"

Mặt khác, nếu một số nhận dạng đề cập đến nullhoặc undefined, bạn không thể sử dụng toStringphương thức này, nó sẽ cung cấp cho bạn một TypeErrorngoại lệ :

var value = null;
String(null);     // "null"
value.toString(); // TypeError

Hàm Stringtạo được gọi là một hàm sẽ gần tương đương với:

value + '';

Các quy tắc chuyển đổi kiểu từ Object -to- Primitive được mô tả chi tiết trên đặc tả, [[DefaultValue]]hoạt động bên trong.

Tóm tắt ngắn gọn, khi chuyển đổi từ Object -to- String , các bước sau được thực hiện:

  1. Nếu có sẵn, hãy thực thi toStringphương thức.
    • Nếu resultnguyên thủy , hãy trả về result, nếu không, hãy chuyển sang Bước 2.
  2. Nếu có sẵn, hãy thực thi valueOfphương thức.
    • Nếu resultnguyên thủy , hãy trả về result, nếu không, hãy chuyển sang Bước 3.
  3. Ném TypeError.

Với các quy tắc trên, chúng ta có thể tạo một ví dụ về ngữ nghĩa có liên quan:

var o = {
  toString: function () { return "foo"; },
  valueOf:  function () { return "bar"; }
};

String(o); // "foo"

// Make the toString method unavailable:
o.toString = null;

String(o); // "bar"

// Also make the valueOf method unavailable:
o.valueOf = null;

try { 
  String(o); 
} catch (e) {
  alert(e); // TypeError
}

Nếu bạn muốn biết thêm về cơ chế này, tôi khuyên bạn nên xem xét ToPrimitivecác ToStringhoạt động bên trong.

Tôi cũng khuyên bạn nên đọc bài viết này:


1
Có một "cách" thứ ba, nếu bạn gọi điều này: new String(value)trên bất kỳ giá trị nào, nó sẽ luôn trả về một đối tượng chuỗi.
Herbertusz

@Herbertusz new String({toString: null})ném a TypeError.
Константин Ван

Với việc bổ sung các Biểu tượng String()+ ''bây giờ có một sự khác biệt khá đáng kể. String(Symbol())sẽ chạy, nhưng Symbol() + ''sẽ ném ra một lỗi (và Symbol () sẽ vượt qua một bảo vệ sai, không giống như null và không xác định, vì vậy x && (x + '')bây giờ có thể ném).
yeerk

24

value.toString()sẽ gây ra lỗi nếu valuelà null. String(value)không nên.

Ví dụ:

var value = null;
alert(value.toString());

sẽ thất bại bởi vì value == null.

var value = null;
alert(String(value));

sẽ hiển thị thông báo có nội dung "null" (hoặc tương tự), nhưng nó sẽ không bị lỗi.


3
Tôi chưa bao giờ thấy ngoại lệ con trỏ null trong javascript ... bạn thấy điều đó ở đâu?
Dagg Nabbit

đẹp. điều đó chưa phải đẹp hơn với một ví dụ
mykhal

@no, @casablanca Đã sửa. Tôi đã quen với Java. @mykhal Nó trông như thế nào?
Jonathan

Nó trả về một chuỗi "null" :)
moefinley

1

String(value)nên có cùng kết quả như value.toString()trong mọi trường hợp, ngoại trừ các giá trị không có thuộc tính như nullhoặc undefined. ''+valuesẽ tạo ra kết quả tương tự.


1

String () [lệnh gọi hàm tạo ] về cơ bản đang gọi .toString ()

.toString ()String () có thể được gọi trên các giá trị nguyên thủy (number, boolean, string) và về cơ bản sẽ không có gì đặc biệt:

true => 'true'

false => 'false'

17 => '17'

'xin chào' => 'xin chào'

Nhưng việc gọi các hàm này trên các đối tượng là nơi mọi thứ trở nên thú vị:

nếu đối tượng có hàm .toString () của riêng nó, nó sẽ được gọi bất cứ khi nào bạn cần đối tượng này được coi như một chuỗi (rõ ràng / ngầm định)

let obj = {
           myName:"some object",
           toString:function(){ return this.myName; } 
          }

//implicitly treating this obj as a string
"hello " + obj; //"hello some object"

//OR (explicitly)
"hello " + String(obj) //calling the existent toString function

//OR
"hello " + obj.toString(); //calling toString directly

Nhân tiện, nếu bạn muốn coi đối tượng này là một số, nó phải có một hàm .valueOf () được định nghĩa trong đó.

điều gì sẽ xảy ra nếu chúng ta có cả hai trong một đối tượng?

nếu chúng ta muốn coi đối tượng này là một chuỗi => sử dụng .toString ()

nếu chúng ta muốn coi đối tượng này là một số => sử dụng .valueOf ()

điều gì sẽ xảy ra nếu chúng ta chỉ có .valueOf () được định nghĩa?

.valueOf () được định nghĩa bên trong đối tượng sẽ được gọi cho dù chúng ta muốn xử lý đối tượng dưới dạng chuỗi hay dưới dạng số

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.