2011-12-20 37 views
5

Câu hỏi này đã xuất hiện từ another, có liên quan đến hành vi của console.dir bằng chuỗi ký tự. Đặc biệt, xem các ý kiến ​​trên my answer.Tại sao các phương thức của String.prototype có sẵn cho các chuỗi ký tự?

Như chúng ta đã biết, String đối tượng trong JavaScript có một số phương pháp. Các phương thức đó được xác định trên đối tượng String.prototype. Ví dụ: String.prototype.toUpperCase. Do đó chúng tôi có thể làm những việc như thế này:

var s = new String("hello"), 
    s2 = s.toUpperCase();  //toUpperCase is a method on String.prototype 

Tuy nhiên, chúng tôi cũng có thể làm điều này:

var s = "hello",    //s is a string literal, not an instance of String 
    s2 = s.toUpperCase(); 

Rõ ràng, người phiên dịch JavaScript đang làm một số hình thức chuyển đổi/cast khi bạn gọi một phương pháp String.prototype trên một chuỗi chữ. Tuy nhiên, tôi không thể tìm thấy bất kỳ tham chiếu nào về điều này trong số spec. Nó có ý nghĩa, bởi vì nếu không bạn sẽ phải explicity đúc mỗi chuỗi chữ cho một đối tượng String trước khi bạn có thể sử dụng bất kỳ phương pháp nào, và điều đó sẽ khá khó chịu.

Vì vậy, câu hỏi của tôi là, chức năng này được mô tả ở đâu và tôi có đúng là giả sử giá trị bằng chữ được tạm thời truyền tới một phiên bản String không? Tôi có đang suy nghĩ quá mức và thiếu cái gì đó hiển nhiên không?

+1

Btw ký hiệu 'chuỗi mới (giá trị)' là 100% vô dụng ... không sử dụng nó. –

+0

Tôi biết. Câu hỏi đặt ra là tại sao. Điều này được mô tả trong spec ở đâu? –

+1

Chuỗi ký tự là một đối tượng chuỗi: 'typeof" hello "===" string "' trả về true. Điều đó có xảy ra ở vấn đề này không? – bbg

Trả lời

7

Nó định nghĩa ở đây:

The following [[Nhận]] phương pháp nội bộ được sử dụng bởi GetValue khi V là một tài liệu tham khảo tài sản với giá trị cơ sở nguyên thủy. Nó được gọi là sử dụng cơ số làm giá trị của nó và với thuộc tính P làm đối số của nó. Các các bước sau đây được thực hiện:

  1. Cho O là ToObject (cơ sở).
  2. Cho phép desc là kết quả của việc gọi phương thức bên trong [[GetProperty]] của O với tên thuộc tính P.
  3. Nếu desc không xác định, trả về không xác định.
  4. Nếu IsDataDescriptor (desc) là true, trả về desc. [[Value]].
  5. Nếu không, IsAccessorDescriptor (desc) phải đúng như vậy, hãy để getter là desc. [[Get]].
  6. Nếu getter không được xác định, hãy trả lại không xác định.
  7. Trả về kết quả gọi phương thức getter nội bộ [[Call]] cung cấp cơ sở làm giá trị này và không cung cấp đối số.

CHÚ THÍCH Không thể truy cập đối tượng được tạo ở bước 1 ngoài phương pháp trên. Triển khai có thể chọn để tránh việc tạo đối tượng thực tế. Tình huống duy nhất mà việc truy cập thuộc tính thực tế sử dụng phương thức nội bộ này có thể có hiệu lực là khi nó gọi hàm truy nhập.

Nguồn:http://es5.github.com/#x8.7.1

Giá trị chuỗi nguyên thủy được ép buộc đến một đối tượng trong bước 1.


Ví dụ 1

var str = 'some string'; 
str = str.toUpperCase(); 

Ở đây, khái niệm str.toUpperCase được đánh giá theo ngữ nghĩa được định nghĩa trong 11.2.1 Property Accessors:

  1. Từ định danh str được đánh giá theo độ phân giải định danh (xem 10.2.2.1 GetIdentifierReference). Kết quả là một tham chiếu có giá trị cơ bản là bản ghi môi trường của môi trường từ vựng hiện tại và có tên tham chiếu là "str". Tham chiếu này là baseReference.
  2. baseValue được xác định bằng cách thực hiện GetValue(baseReference). Kể từ baseReference không phải là tham chiếu thuộc tính (giá trị cơ sở của nó không phải là đối tượng hoặc giá trị nguyên thủy, nhưng bản ghi môi trường), phương thức GetBindingValue() được gọi để truy lục giá trị của tham chiếu. Phương thức này trả về giá trị của biến cục bộ str, tức là giá trị Chuỗi gốc 'some string'. Giá trị này là baseValue.
  3. Tài sản NameValue đánh giá thành giá trị Chuỗi gốc 'toUpperCase'. (Tôi đã rút ngắn quá trình này một chút vì lợi ích của sự đơn giản.)
  4. Một tham chiếu mới được tạo ra có cơ sở giá trị là baseValue và có tên tham chiếu là propertyNameValue.

Vì vậy, có hai tài liệu tham khảo liên quan đến quá trình này:

  • str (cơ sở giá trị: kỷ lục môi trường, tên tham chiếu: 'str')
  • str.toUpperCase (giá trị cơ sở: 'some string', tên tham chiếu: 'toUpperCase')

Cuối cùng, toán tử yêu cầu () được thực hiện trên tham chiếu sau. Giá trị của tham chiếu đó được xác định theo các ngữ nghĩa được xác định ở đầu câu trả lời này.

Ví dụ 2

var str = 'some string'.toUpperCase(); 

Ở đây, khái niệm 'some string'.toUpperCase được đánh giá theo cùng một "tài sản accessor" ngữ nghĩa như trong ví dụ 1:

  1. Chuỗi đen 'some string' rõ ràng là đánh giá với nguyên thủy Chuỗi giá trị 'some string'. Đây là số baseReference. (Đừng để tên gây nhầm lẫn cho bạn - đây là một giá trị chuỗi, không phải là tham chiếu.)
  2. baseValue được xác định bằng cách thực hiện GetValue(baseReference). Vì baseReference không phải là tham chiếu, phương thức chỉ trả về giá trị đối số, tức là baseValue = baseReference.

Như bạn thấy, giống như trong ví dụ 1, baseValue là nguyên thủy String value 'some string'. Các bước 3 và 4 tương đương với các bước 3 và 4, ví dụ 1.

Vì vậy, cả tham chiếu số nhận dạng str và chuỗi ký tự 'some string' đều được đánh giá bằng cùng giá trị - giá trị chuỗi nguyên thủy 'some string' - và giá trị đó được sử dụng là baseValue cho tham chiếu mới, sau đó được gọi với (). Và vì tham chiếu này có giá trị cơ sở nguyên thủy, nên các ngữ nghĩa được định nghĩa ở đầu câu trả lời của tôi sẽ được áp dụng.

+0

Ah-ha! Cảm ơn bạn rất nhiều :) –

+0

Tôi đọc đó là tốt, nhưng làm thế nào là một chuỗi chữ liên quan đến một tài liệu tham khảo? Tham chiếu là gì, hoặc chính xác hơn, ràng buộc tên được giải quyết là gì? –

+0

'+ 1' - Tôi đang tìm kiếm điều đó! –

1

mỗi the reference literals được chuyển đổi thành các đối tượng:

literals String (ký hiệu bằng dấu ngoặc kép hoặc đơn) và chuỗi trở về từ chuỗi các cuộc gọi trong ngữ cảnh không phải là hàm tạo (tức là, không có sử dụng từ khóa mới) là các chuỗi gốc. JavaScript tự động chuyển đổi các đối tượng nguyên thủy và chuỗi, để có thể sử dụng phương thức đối tượng String cho các chuỗi nguyên thủy.

+0

Đó là như tôi giả định, nhưng tôi vẫn không thể tìm thấy nó trong spec ECMAScript. Bạn có biết nếu/nơi hành vi này được mô tả trong đó? –

Các vấn đề liên quan