2013-05-01 23 views
7

Vì vậy, tôi có một isPlainObject phương pháp đơn giản mà tôi sử dụng để kiểm tra cho literals đối tượng JavaScript:Tại sao việc thêm một thuộc tính vào nguyên mẫu của đối tượng theo nghĩa đen thay đổi "kiểu" của nó?

var isPlainObject = function (obj) { 
    return typeof obj === "object" && {}.toString.call(obj) === "[object Object]"; 
}; 

Bây giờ tôi có một đối tượng đơn giản:

var obj = {'one': 1, 'two': 2, 'three': 3}; 

Khi tôi chạy nó thông qua isPlainObject(obj) chức năng nó hoạt động như mong đợi và trả về true. Câu hỏi của tôi đến từ việc thêm một tài sản để nguyên mẫu của đối tượng:

obj.constructor.prototype.four = 4; 

Bây giờ khi tôi chạy isPlainObject(obj) trên obj nó trả false. typeof obj trả về object trong cả hai trường hợp. toString trả về [object Number] trong trường hợp thứ hai sau khi tôi đã thêm thuộc tính vào mẫu thử nghiệm.

Chính xác điều gì đã xảy ra để thay đổi obj? Chuyện gì vậy?

CHỈNH SỬA: Điều này chỉ xảy ra khi được kiểm tra trong giới hạn của cuộc gọi chức năng QUnit.

test("each", function() { 

    _.each([1, 2, 3], function(i,v) { 
     equal(v, i + 1, 'each iterator provided index and value from array'); 
    }); 

    var obj = {'one': 1, 'two': 2, 'three': 3}; 
    console.log(_.isPlainObject(obj)); // => true 
    obj.constructor.prototype.four = 4; 
    console.log(_.isPlainObject(obj)); // => false 

}); 

EDIT: Đây là console.log tôi nhận được khi đăng nhập các đối tượng arguments mảng giống như trong isPlainObject.

Logging out the <code>arguments</code> object

Nhìn vào các bản ghi sẽ dường như chỉ ra mảng hiện có hai đối số. Nhưng độ dài vẫn còn đọc 1.

+9

Bạn đang sử dụng trình duyệt (lạ) nào? [Nó cho thấy 'true' đối với tôi ...?] (Http://jsfiddle.net/mattlunn/bR7PX/) – Matt

+0

Tôi đang thử nghiệm trong một cuộc gọi thử nghiệm QUnit(). Và bạn nói đúng Tôi chỉ chạy thử nghiệm trong giao diện điều khiển và mọi thứ hoạt động như mong đợi. Tại sao chạy thử nghiệm này trong QUnit lại có hiệu ứng này. Một số loại vấn đề phạm vi? – Xaxis

+4

Điều đó cũng đúng với tôi. 'Typeof obj' và' {} .toString.call (obj) 'trả về cho bạn là gì? – Barmar

Trả lời

1

Bằng cách gọi

({}).constructor.prototype 

Bạn đang truy cập nguyên mẫu cho tất cả các đối tượng. Vì vậy, về cơ bản bạn đã thêm một "bốn" tài sản cho mọi đối tượng bản địa.

Nếu bạn muốn mở rộng trường hợp đối tượng của bạn, bạn lý tưởng sẽ cần một hàm constructor mới, như:

var Count = function() { 
    this.one = 1; 
    this.two = 2; 
    this.three = 3; 
} 

var obj = new Count(); 
obj.four = 4; 

Hoặc để mở rộng chức năng xây dựng:

Count.prototype.four = 4; 

Bất kể ... Không chắc điều này sẽ phá vỡ QUnit, nhưng như một poster khác đã đề xuất hasOwnProperty nên thực hiện thủ thuật. Đây là similar question

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