一.什么是原型呢?
我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象.(即prototype即为函数的原型该原型指向的是一个原型对象)
二.什么是原型对象呢?
我们创建每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象(即原型对象).而这个对象的用途是包含
可以由特定类型的所有 实例 共享的属性和方法.(字面意思prototype就是通过调用构造函数而创建的实例对象的原型对象)
使用原型对象的好处是可以让所有的对象实例(实例对象)共享他包含的所有的属性和方法
需要特别注意的是原型对象的理解,只要创建一个函数,该函数就会创建一个prototype(原型)属性,这个属性指向函数的原型对象
三.原型对象和原型的关系?
__proto__是什么呢?
这是每一个JavaScript对象(除了 null )都具有的一个属性,叫__proto__,这个属性会指向该对象的原型。
当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性即__proto__),指向构造函数的原型对象
constructor是什么呢?
在默认情况下,所有的原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针即(Person.prototype.constructor指向Person),而通过这个构造函数,我们可以继续为原型对象添加起他属性和方法
通过一张图片展示他们之间的关系
代码示例:
//创建一个构造函数,并在构造函数的原型上添加一个name属性
functionPerson(){
}
Person.prototype.name= "kebi"
var person1 = new Person();
console.log(person1.name) //kebi
var perso2 = new Person();
console.log(person2.name) //kebi
console.log(person.__proto__ === Person.prototype); // true 他两个的关系也是完全相等的console.log(Person.prototype.constructor == Person) // true
// 顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
//b.isPrototypeOf(a) 这个方法的意思是,a对象是否指向b对象
Person.prototype.isPrototypeOf(person1) //true 因为person1中有一个__proto__属相指向原型对象(Person.prototype)
Person.prototype.isPrototypeOf(person2) //true 同理
总结一下prototype和__proto__到底是什么关系呢?
函数对象的prototype属性, 可以称之为显式原型属性(简称: 显式原型)
实例对象的__proto__属性, 可以称之为隐式原型属性(简称: 隐式原型)
原型对象: 也就是prototype属性和_proto__属性指向的对象
四.什么是原型链?
1.原型的搜索机制
当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。
代码例子:
functionPerson() {
}
Person.prototype.name= 'heyushuo';var person = newPerson();
person.name= 'kebi';
console.log(person.name)//kebi
deleteperson.name;
console.log(person.name)//heyushuo
在这个例子中,我们给实例对象 person 添加了 name 属性,当我们打印 person.name 的时候,结果自然为 kebi。
但是当我们删除了 person 的 name 属性时,读取 person.name,从 person 对象中找不到 name 属性就会从 person 的原型也就是 person.__proto__ ,也就是 Person.prototype中查找 (原型对象中),幸运的是我们找到了 name 属性,结果为 heyushuo。
但是万一还没有找到呢?原型的原型又是什么呢? ( 肯定需要一环一环地前行到原型链的末端才会停下来)
最顶层为默认的原型
所有的函数的默认原型都是Object的实例,所以默认原型都会包含一个内部指针,指向Object.prototype(默认原型的原型对象),这也真是所有自定义类型都会继承toString()/valueOf等默认的方法的根本原因.一直查到最顶层才算一个完整的原型链
如图所示: 蓝色线为完整的原型链
参考:Javascript:高级程序设计