原型是 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"属性进行相互关联经过这些介绍,相信必定能够对原型有个清晰的认识。