一、函數對象
-
所有引用類型(函數、數組、對象)都擁有__proto__屬性(隱式原型)
-
所有函數擁有 prototype 屬性(顯式原型)(僅限函數)
-
原型對象:擁有 prototype 屬性的對象,在定義函數時就被創建
關於 prototype 與__proto__
- js中所有的函數都有一個 prototype 屬性,該屬性引用了一個對象,即原型對象,也簡稱原型
- js對象有一個__proto__屬性,指向它的構造函數的prototype屬性
- 對象.__proto__===函數.prototype;
var a = new A; //a 類型:對象 //A 類型:函數 var Object = new Function(); //var 對象 = new 函數; Object.__proto__ === Function.prototype; //對象.__proto__ === 函數.prototype; Function.__proto__ === Function.prototype; //因為 Function 也是 Object
二、構造函數
1、什么是構造函數?
任何一個函數,只要被 new 操作符使用,就可以是一個構造函數(構造函數建議以大寫開頭)
另外,在 JavaScript 的內置對象中,所有的函數對象都是 Function 構造函數的實例,比如:Object、Array等
//創建構造函數 function Demo(name){ this.name= name; } Demo.prototype = { alert(){ alert(this.name); } } //創建實例 var a = new Demo("ming"); a.print = function(){ console.log(this.name); console.log(this); //Person對象 } a.print(); //控制台內容如下
a.alert(); //彈出ming
-
print()方法是a實例本身具有的方法,所以 a.print() 打印 ming
alert()不屬於a實例的方法,屬於構造函數的方法,a.alert() 也會打印 ming,因為實例繼承構造函數的方法
-
實例a的隱式原型指向它構造函數的顯式原型,指向的意思是恆等於
a.__proto__ === Demo.prototype
- 當調用某種方法或查找某種屬性時,首先會在自身調用和查找,如果自身並沒有該屬性或方法,則會去它的__proto__屬性中調用查找,也就是它構造函數的 prototype 中調用查找。
三、原型和原型鏈
1、什么是原型?
每個函數都具有 prototype 屬性,它被默認成一個對象,即原型對象
Function.prototype.a = "a"; Object.prototype.b = "b"; function Person(){} console.log(Person); //function Person() let p = new Person(); console.log(p); //Person {} 對象 console.log(p.a); //undefined console.log(p.b); //b
2、什么是原型鏈?
當對象使用屬性時,先在自身找,有就直接用,沒有就沿着__proto__這條鏈往上找,直到 Object 原型的位置,有就返回相應的值,沒有就返回 underfined。
由於 p 是 Person() 的實例,是一個 Person 對象,它擁有一個屬性值__proto__,並且__proto__是一個對象,包含兩個屬性值 constructor 和__proto__
console.log(p.__proto__.constructor); //function Person(){} console.log(p.__proto__.__proto__); //對象{},擁有很多屬性值
p.__proto__.constructor 返回的結果為構造函數本身,p.__proto__.__proto__有很多參數

console.log(p.__proto__.__proto__)
我們調用 constructor 屬性,
p.__proto__.__proto __.constructor 得到擁有多個參數的Object()函數,
Person.prototype 的隱式原型的 constructor 指向Object(),即 Person.prototype.__proto__.constructor == Object()
從 p.__proto__.constructor 返回的結果為構造函數本身得到 Person.prototype.constructor == Person()
所以 p.__proto__.__proto__== Object.prototype
即 p.b 打印結果為b,p沒有b屬性,會一直通過__proto__向上查找,最后當查找到 Object.prototype 時找到,最后打印出b,
向上查找過程中,得到的是 Object.prototype,而不是 Function.prototype,找不到a屬性,
所以結果為 undefined,這就是原型鏈,通過__proto__向上進行查找,最終到null結束
console.log(p.__proto__.__proto__.__proto__); //null console.log(Object.prototype.__proto__); //null
同理,得出以下結果
//Function function Function(){} console.log(Function); //Function() console.log(Function.prototype.constructor); //Function() console.log(Function.prototype.__proto__); //Object.prototype console.log(Function.prototype.__proto__.__proto__); //NULL console.log(Function.prototype.__proto__.constructor); //Object() console.log(Function.prototype.__proto__ === Object.prototype); //true
3、原型鏈的繼承
function Father(){ this.name = 'Faker'; } function Child(){ this.age = 20; } Child.prototype = new Father(); var son = new Child();
四、總結
- Object 是所有對象的爸爸,所有對象都可以通過 __proto__ 找到它
- Function 是所有函數的爸爸,所有函數都可以通過 __proto__ 找到它
- 函數的 prototype 是一個對象
- 對象的 __proto__ 屬性指向原型, __proto__ 將對象和原型連接起來組成了原型鏈