2015-05-22 24 views
5

article này định nghĩa instanceof như sau:javascript: Vẫn còn lúng túng bởi các nhà điều hành instanceof

kiểm tra hành

Các instanceof dù một đối tượng có trong chuỗi nguyên mẫu nó thuộc tính prototype của một nhà xây dựng.

Đó là một lời giải thích hợp lý và cuộc sống là tốt cho đến khi tôi đi qua mã này từ cuốn sách hùng biện Javascript:

function TextCell(text) { 
 
    this.text = text.split("\n"); 
 
} 
 

 
TextCell.prototype.minWidth = function() { 
 
    return this.text.reduce(function(width, line) { 
 
    return Math.max(width, line.length); 
 
    }, 0); 
 
} 
 

 
TextCell.prototype.minHeight = function() { 
 
    return this.text.length; 
 
} 
 

 
TextCell.prototype.draw = function(width, height) { 
 
    var result = []; 
 
    for (var i = 0; i < height; i++) { 
 
    var line = this.text[i] || ""; 
 
    result.push(line + repeat(" ", width - line.length)); 
 
    } 
 
    return result; 
 
} 
 

 
function RTextCell(text) { 
 
    TextCell.call(this, text); 
 
} 
 

 
RTextCell.prototype = Object.create(TextCell.prototype); 
 

 
RTextCell.prototype.draw = function(width, height) { 
 
    var result = []; 
 
    for (var i = 0; i < height; i++) { 
 
    var line = this.text[i] || ""; 
 
    result.push(repeat(" ", width - line.length) + line); 
 
    } 
 
    return result; 
 
};

Hãy tạo một thể hiện của RTextCell và thực hiện dưới c

var rt = new RTextCell("ABC"); 
console.log(rt instanceof RTextCell); // true 
console.log(rt instanceof TextCell); // true 

Tôi hiểu tại sao đầu ra của console.log thứ 2 là "true" - bởi vì constructor TextCell là một phần của chuỗi nguyên mẫu.

Tuy nhiên console console đầu tiên gây nhầm lẫn cho tôi.

Nếu bạn nhìn vào mã (dòng thứ 10 từ dưới), nguyên mẫu của RTextCell được cập nhật lên một đối tượng mới, có nguyên mẫu được đặt thành TextCell.prototype.

RTextCell.prototype = Object.create(TextCell.prototype);.

Nhìn vào ảnh chụp nhanh bên dưới, không đề cập đến hàm tạo "RTextCell" trong chuỗi mẫu của đối tượng "rt". Vì vậy, đi theo định nghĩa mà tôi đã đề cập ở đầu bài viết của tôi, không nên đầu ra là sai? Tại sao nó trả về giá trị thực?

Tôi cũng đọc this nhưng không giúp tôi hiểu vấn đề cụ thể này.

Xem bên dưới để biết ảnh chụp nhanh của rt, RTextCell, TextCell theo thứ tự đó.

snapshot of "rt" snapshot of RTextCell snapshot of TextCell

+0

Đó là câu hỏi có cấu trúc thực sự tốt. Bạn đã cho thấy tất cả các điều tra trước đây của bạn, hy vọng bạn nhận được câu trả lời rất tốt. –

+0

Oh! Tôi nên thêm. Tôi đã kiểm tra cây chuỗi nguyên mẫu này trong các ảnh chụp nhanh ở trên trên cả chrome 43.0.2357.65 và firefox 33.1.1. – Harish

Trả lời

1

Từ ngữ chính xác là quan trọng. Bạn nói về constructor là trong chuỗi ban đầu, nhưng báo giá gốc không:

Các instanceof kiểm tra hành dù một đối tượng có trong chuỗi nguyên mẫu của nó nguyên mẫu sở hữu của một nhà xây dựng.

Vì vậy, sự biểu hiện rt instanceof RTextCell thực sự đang thử nghiệm một cái gì đó như thế này (hãy nhớ rằng __proto__ không phải là tiêu chuẩn):

var p = rt.__proto__; 
while(p) 
{ 
    if(p == RTextCell.prototype) 
    return true; 
    p = p.__proto__; 
} 
return false; 

Vì vậy, mặc dù chức năng RTextCell không tham chiếu trực tiếp trên cây đối tượng trên, đối tượng RTextCell.prototype là.

+0

hoặc trong một biểu thức duy nhất, 'RTextCell.prototype.isPrototypeOf (rt)' :-) – Bergi

+0

@Dark Falcon: Trước đó tôi đã nhầm lẫn với toán tử instanceof và isPrototypeOf() và khi tôi xem từ "constructor" trong định nghĩa trên Trang web MDN tôi hoàn toàn hiểu lầm. Bạn trả lời làm tôi dừng lại một chút và nhận ra những gì tôi đã bỏ lỡ. "Từ ngữ". Bây giờ nó có ý nghĩa. Và tôi cũng chỉ đọc [this]. (Http://stackoverflow.com/questions/18343545/javascript-isprototypeof-vs-instanceof-usage) cho sự khác biệt giữa instanceof và isPrototypeOf(). Cảm ơn bạn đời. – Harish

1
obj instanceof RTextCell 

đang thử nghiệm liệu RTextCell.prototype hiện diện trong chuỗi ban đầu của obj. Đó là kể từ khi obj đã được thực hiện bằng cách sử dụng RTextCell mới. Thực tế là RTextCell.prototype có nguyên mẫu TextCell.prototype bên cạnh điểm này và dường như đang ném bạn.

RTextCell.prototype = Object.create(TextCell.prototype); 

không loại bỏ RTextCell.prototype, nó vẫn là một đối tượng, nhưng nguyên mẫu của nó là TextCell.prototype.

4

Bạn thay đổi RTextCell.prototype, nhưng bạn thay đổi trước bạn xây dựng bất kỳ trường hợp RTextCell nào. Hãy xem xét ví dụ ồ ạt khác nhau này, nơi RTextCell.prototype được sửa đổi sau khi một thể hiện được tạo ra với nguyên mẫu ban đầu:

var rt = new RTextCell(); 
RTextCell.prototype = somethingTotallyDifferent; 
rt instanceof RTextCell; // false! 

Khi rt được tạo ra, đó là sự thật mà rt.__proto__ === RTextCell.prototype. Sau khi RTextCell.prototype thay đổi, điều đó sẽ không còn đúng nữa.

Bạn đang không kiểm tra nếu rtgốc tài sảnprototype từ RTextCell trong chuỗi nguyên mẫu của nó. Thay vào đó, bạn đang thử nghiệm nếu giá trị của RTextCell.prototypengay bây giờ tồn tại trong chuỗi nguyên mẫu của đối tượng. Điều đó sẽ luôn đúng đối với RTextCell trường hợp, vì các phiên bản được tạo bởi hàm tạo RTextCell luôn nhận giá trị hiện tại là RTextCell.prototype trong chuỗi nguyên mẫu của chúng và bạn không bao giờ thay đổi RTextCell.prototype sau khi bạn bắt đầu tạo phiên bản.

+0

Ngoài câu trả lời từ @Dark Falcon, ví dụ của bạn về việc thiết lập nguyên mẫu thành "somethingTotallyDifferent" đã giúp tôi. Điều này có ý nghĩa. Cảm ơn. – Harish

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