2012-09-27 24 views
13

Tôi đã nhầm lẫn bản thân mình một chút với một thử nghiệm suy nghĩ và bây giờ tôi đang tìm một số lời khuyên. Giới thiệu về các tham chiếu ECMAscript và phương pháp Array.prototype.indexOf().Làm thế nào để indexOf của Javascript() giải quyết tham chiếu

Cho phép bắt đầu dễ dàng:

var container = [ ]; 
// more code 
container.push(5); 
container.push(7); 
container.push(10); 

Vì vậy, bây giờ chúng tôi đã đẩy một số "giá trị nguyên thủy" vào mảng ECMAScript của chúng tôi (đã hoặc chưa tuyên bố đó là sự thật, tôi sẽ trở lại cho), tại ít nhất tôi tưởng tượng nó như thế này cho đến nay. Một cuộc gọi đến

container.indexOf(7); 

sẽ trả lại 1 như mong đợi. Câu hỏi lớn tôi đang có là, nếu .indexOf() thực sự so sánh giá trị nguyên thủy hoặc nếu trong thực tế, đối tượng Number() được tạo + được lưu trữ và tham chiếu của nó được so sánh. Điều này trở nên một chút rõ ràng hơn nếu chúng ta lại viết rằng như vậy:

var a = 5, 
    b = 7, 
    c = 10; 

var container = [ ]; 

container.push(a); 
container.push(b); 
container.push(c); 

container.indexOf(b); 

Cho đến thời điểm này, người ta có thể vẫn dễ dàng cho rằng tất cả .indexOf() cần phải làm là để so sánh giá trị, nhưng bây giờ cho phép xem xét một cái gì đó như thế này:

var a = { name: 'a', value: 5 }, 
    b = { name: 'b', value: 10 }, 
    c = { name: 'c', value: 15 }; 

var container = [ ]; 
// more code 
container.push(a); 
container.push(b); 
container.push(c); 

Ở đây, chúng ta điền rằng mảng container với đối tượng tài liệu tham khảo và vẫn còn, .indexOf() công trình như mong đợi

container.indexOf(b) // === 1 

trong khi một cuộc gọi như thế này

container.indexOf({ name: 'b', value: 10 }); 

rõ ràng trả -1 vì chúng ta đang tạo ra một đối tượng mới và có được một tham chiếu mới. Vì vậy, ở đây nó phải so sánh nội bộ tài liệu tham khảo với nhau, phải không?

Có thể một số thiên tài spec ECMAscript xác nhận rằng hoặc thậm chí tốt hơn liên kết tôi một số tài liệu về điều đó?

Một câu hỏi bên về vấn đề này sẽ là nếu có bất kỳ có thể cách để truy cập vào một lưu trữ nội bộ đối tượng tham chiếu trong một lexicalEnvironment tương ứng Hoạt Object.

+0

Nếu đây làm việc bất cứ nơi nào tương tự như các ngôn ngữ khác, sau đó 'indexOf' hoạt động trên băm đối tượng mà đối tượng thường có giá trị khác nhau và các đối tượng nguyên thủy thường có một băm liên tục dựa trên giá trị của chúng (đối với các số nguyên, điều này thường chỉ là giá trị số nguyên). Vì vậy, hai đối tượng int '5' và' 5' đều có hàm băm '5' và như vậy là“ giống nhau ”. – poke

+1

Tôi bắt đầu viết một câu trả lời, nhưng sau đó nó trở thành một bài đăng trên blog vì vậy tôi đã dừng lại và không được khuyến khích viết lại nó. Nhưng nếu bạn quan tâm: http://pastie.org/4828933 – Zirak

Trả lời

8

Nó sẽ giảm xuống indexOf() so sánh với từng thuộc tính mảng lần lượt bằng cách sử dụng cùng một thuật toán với toán tử ===.

Phần có liên quan của thông số ECMAScript 5 là phần 15.4.4.14 bước 9, phần b (đánh dấu mỏ):

Nếu kPresent là đúng, sau đó

i. Gọi elementK là kết quả của việc gọi phương thức bên trong [[Get]] của O với đối số ToString (k).

ii. Hãy cùng là kết quả của việc áp dụng Thuật toán so sánh chính xác nghiêm ngặt vào searchElement và elementK.

iii. Nếu cùng là đúng, trả về k.

Tài liệu tham khảo:

+0

cảm ơn bạn. Tuy nhiên, * so sánh bình đẳng nghiêm ngặt * được mô tả ở đó không mô tả cách đối phó với các đối tượng nói chung? Có vẻ như chúng chỉ mô tả cho số, chuỗi, booleans và null/undefined values. Ngoài ra, tôi tò mò về phần đầu tiên là tốt mà nói, "* gọi toString() *" trên các đối số. Nếu đó thực sự là bản gốc 'toString' thì tất cả các đối tượng sẽ trả về * đối tượng Object * no? – jAndy

+0

@jAndy: bit 'ToString (k)' là tham chiếu đến tên thuộc tính, không phải là giá trị. Phần so sánh bình đẳng nghiêm ngặt mô tả hoàn toàn thuật toán. Xem bước 7 trong 11.9.6: * "Trả về true nếu x và y tham chiếu đến cùng một đối tượng. Nếu không, trả về false." *. –

2

Tôi không chắc chắn nếu điều này được đảm bảo trên tất cả các triển khai ECMAScript hay không, nhưng Mozilla documentation nói rằng nó sử dụng sự bình đẳng nghiêm ngặt để so sánh (===). Vì vậy, điều này sẽ thể hiện hành vi mà bạn mô tả, so sánh bằng các giá trị trên nguyên thủy, nhưng bằng cách tham chiếu trên các đối tượng (xem strict equality).

+0

Thậm chí '==' sử dụng so sánh theo tham chiếu cho các đối tượng. Vì vậy, nó không có gì để làm với sự bình đẳng nghiêm ngặt – zerkms

+3

Tôi không nói đó là * vì * nghiêm ngặt bình đẳng. Tôi đang nói nó thực sự sử dụng sự bình đẳng nghiêm ngặt và phù hợp với hành vi mà anh ta mô tả. – Thor84no

0

@ Tim Xuống là đúng. indexOf so sánh nghiêm ngặt. Tôi đưa ra một cuộc biểu tình này bằng cách ghi đè valueOf chức năng

var MyObject = function(n, v){ 
    this.name = n; 
    this.value = v; 
} 

MyObject.prototype.valueOf = function(){ 
    return this.value; 
} 

var a = new MyObject("a", 5); 
var b = new MyObject("b", 10); 
var c = new MyObject("c", 15); 

var container = [ ]; 

container.push(a); 
container.push(b); 
container.push(c); 

console.log(b == 10); // true 
console.log(container[1] == 10); // true 

console.log(b === 10); // false 
container.indexOf(10); // -1 
Các vấn đề liên quan