Được rồi, chúng ta hãy chơi một chút tâm trí trò chơi:
Từ hình trên chúng ta có thể thấy:
- Khi chúng ta tạo một hàm như
function Foo() {}
, JavaScript tạo ra một trường hợp Function
.
- Mỗi trường hợp
Function
(hàm hàm dựng) có thuộc tính prototype
là con trỏ.
- Thuộc tính
prototype
của hàm xây dựng trỏ đến đối tượng mẫu thử nghiệm của nó.
- Đối tượng nguyên mẫu có thuộc tính
constructor
cũng là một con trỏ.
- Thuộc tính
constructor
của đối tượng mẫu thử trỏ về hàm khởi tạo của nó.
- Khi chúng tôi tạo một phiên bản mới
Foo
như new Foo()
, JavaScript sẽ tạo một đối tượng mới.
- Nội bộ
[[proto]]
thuộc tính của cá thể trỏ đến nguyên mẫu của hàm tạo.
Bây giờ, câu hỏi đặt ra là tại sao JavaScript không đính kèm thuộc tính constructor
vào đối tượng mẫu thay vì mẫu thử nghiệm. Xem xét:
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
var Square = defclass({
constructor: function (side) {
this.side = side;
},
area: function() {
return this.side * this.side;
}
});
var square = new Square(10);
alert(square.area()); // 100
Như bạn có thể thấy constructor
bất động sản chỉ là một phương pháp của nguyên mẫu, như area
trong ví dụ trên. Điều làm cho đặc tính constructor
đặc biệt là nó được sử dụng để khởi tạo một thể hiện của nguyên mẫu. Nếu không, nó chính xác giống như bất kỳ phương pháp nào khác của nguyên mẫu.
Xác định constructor
tài sản trên nguyên mẫu là thuận lợi vì những lý do sau đây:
- Đó là logic đúng. Ví dụ: xem
Object.prototype
. Thuộc tính constructor
của Object.prototype
trỏ đến Object
. Nếu thuộc tính constructor
được xác định trên cá thể thì Object.prototype.constructor
sẽ là undefined
vì Object.prototype
là một phiên bản null
.
- Nó được xử lý không khác với các phương pháp thử nghiệm khác. Điều này làm cho công việc của
new
dễ dàng hơn vì nó không cần phải xác định thuộc tính constructor
trên mọi trường hợp.
- Mỗi trường hợp có cùng thuộc tính
constructor
. Do đó nó hiệu quả.
Bây giờ khi chúng ta nói về thừa kế, chúng tôi có các tình huống sau:
Từ hình trên chúng ta có thể thấy:
- tài sản
prototype
Các nhà xây dựng có nguồn gốc được thiết lập để trường hợp của hàm tạo cơ sở.
- Do đó thuộc tính nội bộ
[[proto]]
của cá thể của hàm tạo dẫn xuất cũng trỏ đến nó.
- Do đó, thuộc tính
constructor
của cá thể khởi tạo có nguồn gốc hiện trỏ đến hàm tạo cơ sở.
Đối với nhà điều hành instanceof
, trái với niềm tin phổ biến, nó không phụ thuộc vào tài sản constructor
của cá thể. Như chúng ta có thể thấy từ trên, điều đó sẽ dẫn đến kết quả sai lầm.
Toán tử instanceof
là toán tử nhị phân (có hai toán hạng). Nó hoạt động trên một đối tượng instance và một hàm khởi tạo. Như giải thích trên Mozilla Developer Network, nó chỉ đơn giản nào sau đây:
function instanceOf(object, constructor) {
while (object != null) {
if (object == constructor.prototype) { //object is instanceof constructor
return true;
} else if (typeof object == 'xml') { //workaround for XML objects
return constructor.prototype == XML.prototype;
}
object = object.__proto__; //traverse the prototype chain
}
return false; //object is not instanceof constructor
}
Nói một cách đơn giản là nếu Foo
thừa hưởng từ Bar
, sau đó là chuỗi nguyên mẫu cho trường hợp của Foo
sẽ là:
foo.__proto__ === Foo.prototype
foo.__proto__.__proto__ === Bar.prototype
foo.__proto__.__proto__.__proto__ === Object.prototype
foo.__proto__.__proto__.__proto__.__proto__ === null
Như bạn có thể thấy, mọi đối tượng kế thừa từ hàm tạo Object
. Chuỗi nguyên mẫu kết thúc khi một thuộc tính nội bộ [[proto]]
trỏ đến null
.
Chức năng instanceof
chỉ cần đi qua chuỗi mẫu của đối tượng thể hiện (toán hạng đầu tiên) và so sánh thuộc tính nội bộ [[proto]]
của mỗi đối tượng với thuộc tính hàm xây dựng (toán hạng thứ hai). Nếu chúng phù hợp, nó trả về true
; và nếu chuỗi nguyên mẫu kết thúc, nó trả về false
.
Bất kỳ lý do nào bạn cần hàm khởi tạo được cập nhật? Tôi thấy cuộc sống của mình dễ dàng hơn nếu tôi giả vờ rằng tài sản không tồn tại. – hugomg
Tôi đang gặp khó khăn khi đóng bản sao này thành bản sao - tất cả các questinos khác đều quá chi tiết ... – hugomg
'c.prototype' là' b() 'và' b.prototype' là 'a()', do đó 'c.prototype' là' a() ' –