JS中的原型对象与原型链
一、原型对象
我们先来认识一下原型对象吧!
原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。
1. 函数的原型对象
在JavaScript中,我们创建一个函数A,那么浏览器就会在内存中创建一个对象B,而且每个函数都默认会有一个属性 prototype 指向了这个对象(即:prototype的属性的值是这个对象 )。这个对象B就称作是函数A的原型对象,简称函数的原型。这个原型对象B 默认会有一个属性constructor指向了这个函数A ( 意思就是说:constructor属性的值是函数A )。
说这么多,看得懂吗?上图
2. 使用构造函数创建对象
当把一个函数作为构造函数,使用new创建对象的时候,那么这个对象就会存在一个默认的不可见的属性,来指向了构造函数的原型对象。这个不可见的属性我们一般用[[prototype]]来表示,只是这个属性没有办法直接访问到。
- 创建出的对象虽然使用的是构造函数,但是对象创建出来之后,这个new出来的对象其实已经与Function构造函数没有任何关系了,[[prototype ]]属性指向的是Function构造函数的原型对象。
- 如果使用new Function()创建多个对象,则多个对象都会同时指向Function构造函数的原型对象。
- 我们可以手动给这个原型对象添加属性和方法,那么p1,p2,p3…这些对象就会共享这些在原型中添加的属性和方法。
- 如果我们访问p1中的一个属性name,如果在p1对象中找到,则直接返回。如果p1对象中没有找到,则直接去p1对象的[[prototype]]属性指向的原型对象中查找,如果查找到则返回。(如果原型中也没有找到,则继续向上找原型的原型—原型链。
后面再讲)。 - 如果通过p1对象添加了一个属性name,则p1对象来说就屏蔽了原型中的属性name。换句话说:在p1中就没有办法访问到原型的属性name了。
- 通过p1对象只能读取原型中的属性name的值,而不能修改原型中的属性name的值。 [p1.name] = “李四”;并不是修改了原型中的值,而是在p1对象中给添加了一个属性name。
- 所有的原型对象都是由Object函数对象创建的
- Function函数对象由自己Function,Function.proto == Function.prototype
- 所有的函数都是由Function函数对象创建
- 构造函数创建的对象,对象的proto指向构造函数的prototype
- 不是构造函数创建的对象,对象的proto指向Object函数对象的prototype
- 对象访问某个属性,如果自己身上有这个属性 优先访问自己的 如果没有再访问原型链上的 沿着原型链依次往上层链找
二、继承-原型链
ECMAScript需要通过原型链来实现继承。
每一个对象都从原型继承属性,直到null结束。
所有的内置构造函数都有一个继承自Object.prototype的原型。
利用下面这个例子来深入一下
var arr1 = new Array(1,2,3);
/* arr1.__proto__
-->Array.prototype的原型__proto__
-->Object.prototype的原型__proto__
-->null
形成链,到null结束; */
var date1 = new Date();
/* date1.__proto__
-->Date.prototype的原型__proto__
-->Object.prototype的原型__proto__
-->null
形成链,到null结束;*/
一、构造函数、原型和实例的关系
a,构造函数都有一个属性prototype,这个属性是一个对象,是Object的实例;
b,原型对象prototype里有一个constructor属性,该属性指向原型对象所属的构造函数;
c,实例对象都有一个__proto__属性,该属性指向构造函数的原型对象;
obj.proto===Object.prototype
二、prototype与_proto_的关系
a,prototype是构造函数的属性;
b,__proto__是实例对象的属性;
c,两者都指向同一个对象;
来道练习题练练手吧
function Person() {
this.name = 'qwer';
}
var person1 = new Person();
Person.prototype.w = '这是w属性';
Function.prototype.q = '这是q属性';
Object.prototype.e = '这是e属性';
console.log(person1.w); // person1.__proto__.__proto__.__proto__
console.log(person1.q); // undefined
console.log(person1.e);
console.log(Person.w); // undefined Person.__proto__.__proto__.__proto__
console.log(Person.q);
console.log(Person.e);
console.log(Function.q); // Function.__proto__.__proto__
console.log(Function.e);
console.log(Object.q); // Object.__proto__.__proto__