幾個概念
- 構造函數: 構造函數實際上是一個普通函數,通過new操作符,可以利用構造函數快速創建對象;
- prototype:每個構造函數自身上都會有一個prototype屬性,該屬性值爲一個對象,這個對象具有一個constructor屬性,constructor指向構造函數自身;
- 實例: 通過構造函數創建的對象,可以看做是該構造函數的實例;
- __proto__:通過構造函數創建的每個對象上面,都會有一個__proto__屬性,該屬性指向構造函數的prototype;
什麼是原型
在JavaScript中,每個對象會有一個原型對象。對象會從原型對象繼承一些屬性和方法。
什麼是原型鏈
在JavaScript中,訪問一個對象的屬性時,JS引擎會首先在該對象自身上線查找該屬性。如果找到了,則直接返回該屬性的值;如果沒有找到,則會去改對象的原型上面繼續查找。如果對象的原型上面也沒有這個屬性,則繼續在原型對象的上原型上面查找,如此一級級繼續往上,直到原型爲null,此時JS引擎返回該對象的屬性值爲undefined。
繼承
/**
* two methods to implement inheritance;
*/
function Base(type){
this.type = type;
}
Base.prototype.base=function(){
console.log(`${this.type} is in base func`);
}
// method one
function Sub(type){
this.type = type;
}
Sub.prototype = Object.create(new Base('base'));
Sub.prototype.sub=function(){
console.log(`${this.type} is in sub func`);
}
// method two
function Foo(type){
this.type = type;
}
Object.setPrototypeOf( Foo.prototype, new Sub('sub'));
Foo.prototype.foo=function(){
console.log(`${this.type} is in foo func`);
}
let sub = new Sub('sub1');
sub.base();
sub.sub();
sub instanceof Sub; // true
sub instanceof Base; // true
let foo = new Foo('foo1');
foo.base();
foo.sub();
foo.foo();
foo instanceof Foo; // true
foo instanceof Sub; // true
foo instanceof Base; // true
一些實例
Object.getPrototype
預測下面幾個表達式的結果
Object.getPrototypeOf(function(){}).constructor === Function;
Object.getPrototypeOf(Function).constructor === Function;
Object.getPrototypeOf(Object.getPrototypeOf(Function)).constructor === Object;
答案:
true;
如何創建一個沒有任何原型的對象?
let obj = Object.create(null);
console.log(obj);
這篇medium上獲得8.6K讚的文章Prototypes in JavaScript講得很清楚了。