原型是 JavaScript 中一個比較難理解的概念,原型相關的屬性也比較多,對象有"[[prototype]]"屬性,函數對象有"prototype"屬性,原型對象有"constructor"屬性。數組
開始原型的介紹以前,咱們首先說說什麼是原型?瀏覽器
在 JavaScript 中,原型也是一個對象,經過原型能夠實現對象的屬性繼承,JavaScript 的對象中都包含了一個"[[prototype]]"內部屬性,這個屬性所對應的就是該對象的原型。"[[prototype]]"做爲對象的內部屬性,是不能被直接訪問的。全部爲了方便查看一個對象的原型,Chrome 等大型瀏覽器廠商提供了"__proto__"這個非標準的訪問器(ECMA 引入了標準對象原型訪問器 "Object.getPrototype(Object)")函數
function Animal(name, type) {
this.name = name;
this.type = type;
this.getInfo = function(){
console.info("當前動物屬性==>",this.name + 'is' + this.type)
}
}
let dog = new Animal("狗", "犬科哺乳動物") // 當前動物屬性==> 狗is犬科哺乳動物複製代碼
Step-->1: 查看對象 dog 的原型this
console.info("__proto__",dog.__proto__);
// __proto__ Objectconstructor: ƒ Animal(name, type)__proto__:
console.info("constructor=====>",dog.constructor)
//constructor=====> ƒ Animal(name, type) {
// this.name = name;
// this.type = type;
// this.getInfo = function(){
// console.info("當前動物屬性==>",this.name + 'is' + this.type)複製代碼
// 拓展 能夠判斷一個對象是否是數組類型
function isArray(arr){
return arr.constructor.toString().indexOf("Array") > -1;
}複製代碼
*在這裏,dog 對象自己沒有"constructor"這個屬性,可是經過原型鏈查找,這到了 dog 原型(dog.__proto__)的 "constructor"屬性,並找到了Animal函數spa
Step-->2: 查看對象 dog 的原型(dog.proto)的原型prototype
既然 dog 的原型"Animal{}"也是一個對象,那麼咱們就一樣能夠來查看 dog 的原型(dog.proto)的原型3d
console.info(dog.__proto__ === Animal.prototype)
console.info(Animal.prototype.__proto__)
console.info(Animal.prototype.constructor)
console.info(Animal.prototype.constructor === Animal)複製代碼
經過上面能夠看到,"Animal.prototype"對象和 Animal 函數對象經過"constructor"和 "prototype"屬性實現了相互引用code
Step-->3: 查看對象 Object 的原型cdn
經過前一部分能夠看到,will的原型的原型是"Object{}"對象。實際上在JavaScript中,全部對象的原型都將追溯到"Object {}"對象。下面經過一段代碼看看"Object {}"對象:對象
console.log(Animal.prototype.__proto__ === Object.prototype);
console.log(typeof Object);
console.log(Object);
console.log(Object.prototype);
console.log(Object.prototype.__proto__);
console.log(Object.prototype.constructor);複製代碼
Step-->4: 查看對象Function的原型
在上面的例子中,Animal是一個構造函數,在JavaScript中函數也是對象,因此,咱們也能夠經過"proto"屬性來查找Animal函數對象的原型。
console.log(Animal.__proto__ === Function.prototype);
console.log(Animal.constructor === Function)
console.log(typeof Function);
console.log(Function);
console.log(Function.prototype);
console.log(Function.prototype.__proto__);
console.log(Function.prototype.constructor);複製代碼
對於"prototype"和"proto"這兩個屬性有的時候可能會弄混,"Person.prototype"和"Person.proto"是徹底不一樣的。
在這裏對"prototype"和"proto"進行簡單的介紹:
"hasOwnProperty"是"Object.prototype"的一個方法,該方法能判斷一個對象是否包含自定義屬性而不是原型鏈上的屬性,由於"hasOwnProperty" 是 JavaScript 中惟一一個處理屬性可是不查找原型鏈的函數。
相信你還記得文章最開始的例子中,經過dog咱們能夠訪問"constructor"這個屬性,並獲得dog的構造函數Animal。這裏結合"hasOwnProperty"這個函數就能夠看到,dog對象並無"constructor"這個屬性。
從下面的輸出能夠看到,"constructor"是dog的原型(dog.proto)的屬性,可是經過原型鏈的查找,dog對象能夠發現並使用"constructor"屬性。
"hasOwnProperty"還有一個重要的使用場景,就是用來遍歷對象的屬性。
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.getInfo = function(){
console.log(this.name + " is " + this.age + " years old");
};
var will = new Person("Will", 28);
for(var attr in will){
console.log(attr);
}
// name
// age
// getInfo
for(var attr in will){
if(will.hasOwnProperty(attr)){
console.log(attr);
}
}
// name
// age複製代碼
本文介紹了JavaScript中原型相關的概念,對於原型能夠概括出下面一些點:
全部的對象都有"[[prototype]]"屬性(經過__proto__訪問),該屬性對應對象的原型全部的函數對象都有"prototype"屬性,該屬性的值會被賦值給該函數建立的對象的"proto"屬性全部的原型對象都有"constructor"屬性,該屬性對應建立全部指向該原型的實例的構造函數函數對象和原型對象經過"prototype"和"constructor"屬性進行相互關聯經過這些介紹,相信必定能夠對原型有個清晰的認識。