構造函數和實例
假設你聲明一個方法叫做Foo()
,那么我們可以通過new Foo()來聲明實例。
function Foo() {
console.log("我是一個構造方法");
}
const f1 = new Foo();
現在你可以很清晰的明白Foo()是構造函數
,f1是它的實例
。
屬性Prototype
Foo()這個構造函數是一個方法。
方法也是對象數據類型,所以可以說方法是個對象。
對象就有屬性,不過方法
有自己特殊的一個屬性,叫做prototype
,其他對象沒有哦。
這個屬性會指向一個原型對象(Foo.prototype)
,而原型對象也會有一個自己的屬性叫做constructor
,指向屬性包含了一個指針,指回原構造函數。
function Foo() {
console.log("我是一個構造方法");
}
const f1 = new Foo();
console.log(Foo.prototype);//Foo的原型對象
console.log(f1.prototype);//f1沒有 underfied
屬性__proto__
上文的prototype是給構造函數的所有實例
提供共享方法和屬性的。
實例又是怎么訪問到共享方法和屬性的呢?
f1實例沒有prototype,而有一個屬性__proto__,這是所有對象都有的屬性,它指向到構造自己的構造函數
的原型對象
,然后js這個語言就是根據這個屬性來讓實例訪問到共享屬性和方法的
Foo是f1的構造函數,Foo.prototype是Foo的原型對象,所以f1.__proto__指向Foo.prototype
function Foo() {
console.log("我是一個構造方法");
}
const f1 = new Foo();
console.log(Foo.prototype);
console.log(f1.__proto__);
訪問原型上的方法
Foo這個構造函數如果希望自己的實例能夠擁有同一個屬性,比如name,就在自己的原型對象上加上。
function Foo() {
console.log("我是一個方法");
}
Foo.prototype.name = "我是Foo創造的實例共享的屬性";
const f1 = new Foo();
const f2 = new Foo();
console.log(f1.name);//我是Foo創造的實例共享的屬性
console.log(f2.name);//我是Foo創造的實例共享的屬性
構造函數也有__proto__
上面說所有對象都有__proto__,Foo是函數也是對象啊,所以Foo.__proto__是啥呢?
那就去找Foo的構造函數是誰呢,Foo是一個函數,擁有函數特有的方法和屬性,創造的它的構造函數就是Function,這個js自帶的的一個構造函數,它的Function.prototype給所有js中你創建的函數提供函數自帶的一些公共方法和屬性。
所以Foo.__proto__指向Funtion.prototype
構造函數的原型也有__proto__
Foo.prototype也是對象,所以它也有__proto__。
每當我們要找__proto__,就得找它的構造函數,Foo.prototype是個對象,純對象,所以它的構造函數是Object,那么Object的原型就是Object.prototype。
Foo.prototype.__proto__指向Object.prototype
Object.prototype這個原型對象很特殊
Array、String、Funtion、Object
這些構造函數
都是函數
,
都是Funtion
構造函數的實例,
Array.__proto__、String.__proto__、Funtion.__proto__、Object.__proto__
指向Funtion.prototype
原型,
可以調用Funtion.prototype
原型的一些公共方法,
例如都可以調用.name查看自己的函數名字。
Array.prototype、String.prototype、Funtion.prototype
這些原型對象
都是對象
,
都是Object
構造函數的實例,
Array.prototype.__proto__、String.prototype.__proto__、Funtion.prototype.__proto__
指向Object.prototype
原型,
所以可以調用Object.prototype
這個原型對象的公共方法,
而
Object.prototype
有些特殊,它雖然是對象,但是並不是Object自己的實例,
Object.prototype.__proto__指向null
,作為原型鏈的終點
總結
- 方法,也就是函數,才有
prototype
,就是方法的原型。 - 所以實例,一般都會有個對應的構造方法,也就是構造函數,實例的
__proto__
指向構造方法的原型。 - js有很多自帶的構造方法,例如Array、String、Funtion、Object,都是根據js一些對象類型分配的,他們的原型上提供了許多封裝好的常用方法。
- 所有
構造方法
本身是函數
,是Funtion
這個js自帶構造函數的實例
。 - 除了Object.prototype,所有
構造方法的原型
本身是對象
,是Object
這個js自帶構造函數的實例
。 - Object.prototype.__prototype指向
null
,作為原型鏈終點
。