1.定义:原型是function对象的一个prototype属性,它定义了构造函数制造出来的对象实例的公共祖先
2.prototype原型也是一个对象,可以覆盖(重写)
3.每个对象实例是可以继承祖先的属性
4.对象实例可以通过__proto__查看prototype原型,这个原型是属于每一个对象实例的
5.function对象的构造函数是可以通过constructor
1.new构造函数的过程
//定义构造函数
function Person(name,age){
this.name=name;
this.age=age;
}
//设置原型的属性sex
Person.prototype.sex='男';
//①创建构造函数对象实例,
//②这时候产生this,然后给this添加属性和方法,
//③接着给【每个对象实例】的this 设置__proto__ ,它指向的就是 Person.prototype原型对象
var p = new Person('wly',18);
//输出sex,自身没有往原型那找
console.log(p.sex);//本质执行的是p.__proto__.sex
console.log(p.__proto__ === Person.prototype)
由于__proto__属性,js并不想我们使用它,所以对于访问自身不存在的属性和方法时是可以省略的
执行过程
var this= {};
this ={
__proto__:Person.prototype
'name':name,
'age':age
}
2.构造函数.prototype
可以打印出当前对象的构造函数.prototype, 发现原型是有constructor属性
这个construtor属性,是为了获取当前对象的构造函数,但直接打印是引用类型,通过dir可以输出详情
//定义一个构造函数
function Person(){
}
//打印出它的原型
console.log(Person.prototype);
//打印出它的原型对象的构造函数
console.dir(Person.prototype.constructor);
2.1有个循环
存在一个有趣的事情:
首先构造函数有prototype属性,prototype属性对象有constroctor属性,constroctor指向构造函数 ...
3.修改prototype原型
3.1修改原型
function Person(){
}
//添加(或修改)属性
Person.prototype.age=18;
3.2覆盖原型
function Person(){
}
//既然prototype是一个对象,直接通过对象赋值
Person.prototype = {
name: 'wly',
age: 18,
//如果不写这个,那么就没有constructor属性了
constuctor:Person
}
说明:覆盖prototype的话,那么等价于重新开辟一块内存地址,重新设置prototype的地址指向,之前创建的实施对象还是用的原地址指向。
好比:var a = [1,2]; var b=a; b=new Array(); //开始a指向了一个内存地址,赋值给了b,那么b也指向这个内存地址,然后现在a不想指向这个内存地址了,重新存储了一个新的内存地址,那么a的新地址肯定不会影响b存储的内存地址,因为地址是实际存在的,每个人都可以存储,你既然存储了,那么你不要就只能自己换地址,别人换了地址是别人的事情!
参考下面例子分析:
为什么之前创建的对象还是用的老的prototype原型呢???
可以这样理解,最开始Person有一个prototype原型,用于实例对象去继承,而prototype原型是一个对象,那么它就会存储一个引用地址,现在创建的var p = new Person(); 的实例对象的__proto__都指向了这块引用地址。然后通过Person.prototype设置属性名,并没有改变引用地址,只是在内部设置值,那么后续实例对象想要拿prototype原型的值,直接取出用。但是现在通过 Person.prototype={} 它要存储一个新的引用地址,那么Person.prototype的原引用地址改变,后续创建的实例对象取出的值就使用这个新的引用地址。
简化等价于:Person.prototype = {name:'无言'} //开始存储了一个引用地址
p.__ proto __ = Person.prototype //p的隐式属性proto已经指向了这个引用地址
Person.prototype = {name:'wlu'} //创建一个新的引用地址,无法改变p的隐式属性proto的地址!
Person.prototype.name='无言';
function Person(){
}
var p = new Person();
//覆盖prototype原型,但改变不了之前的实例对象的prototype指向
Person.prototype = {
name:'wlu'
}
console.log(p.name);//'无言'
结果
图解过程
console.log(p);//打印p查看一下