概念:
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
任何实例对象的隐式原型属性__proto__,指向其构造函数的显示原型属性prototype
也就是说
fn.__proto__ === Fn.prototype 指向Fn的空object对象1
object.__proto__ === Object.prototype === object原型对象
Fn.__proto__ === Function.prototype 指向Function的空object对象2(默认为空)
Object.__proto__ === Function.prototype 指向Function的空object对象2(默认为空)
Function.__proto__ === Function.prototype 都指向Function的空object对象2(默认为空)
看得出构造函数Fn,Object,Function他们的隐式原型属性_proto_,都指向同一个空object对象2,这个object对象2,就是Function()的prototype,因为他们都是被Function()构造的.
而fn,object也是一样,他们的_proto__指向其构造函数的prototype属性对应的那个object对象.
不管是 object对象1 还是 空object对象2 都是普通对象,也有隐式原型属性_proto_.
object1.__proto__ === object原型对象
object2.__proto__ === object原型对象
如果一个方法或者属性,在自己中查找,如果没有找到,就去顺着隐式原型链找,我们拿fn举例.随便写一个查找属性比如 fn.bixin
- fn.bixin 先找自己看看里边有没有
- 没找到就查_proto__指向的那个对象,
- fn.__proto__ === Fn.prototype 就是Fn的prototype对应的 object对象1
- 还没找到,就查 object对象1 的_proto__,所指向的那个对象
- 因为 object对象1 是Object()的实例 所以 object._proto__ ===Object.prototype
- Object.prototype 指向的是 object原型对象(独立的那个)
- 如果还没有找到,那就去找 object原型对象 的_proto__ , 哈哈是null,没有啦
1、
__proto__
和constructor
属性是对象所独有的;
2、prototype
属性是函数所独有的。
但是由于JS
中函数也是一种对象,所以函数也拥有__proto__
和constructor
属性
一、函数的原型对象
我们创建函数
A
的同时, 浏览器会在内存中创建一个对象B
,A
函数默认会有一个prototype
属性。指向了对象B
( 即:prototype
的属性的值是对象B
)。
这个对象B
就是函数A
的原型对象,简称函数的原型。
原型对象B
默认会有一个属性constructor
指向了函数A
(即constructor
属性的值是函数A
)。 原型对象默认只有属性constructor
。其他都是从Object
继承而来。
二、__proto__
属性
__proto__
属性,它是对象所独有的,可以看到__proto__
属性都是由一个对象指向一个对象,即指向它们的原型对象(也可以理解为父对象),那么这个属性的作用是什么呢?它的作用就是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的
__proto__
属性所指向的那个对象(可以理解为父对象)里找,如果父对象也不存在这个属性,则继续往父对象的__proto__
属性所指向的那个对象(可以理解为爷爷对象)里找,如果还没找到,则继续往上找….直到原型链顶端null。此时若还没找到,则返回
undefined
。以上这种通过__proto__
属性来连接对象直到null
的一条链即为我们所谓的原型链。
三、prototype
属性
prototype
是函数所独有的,它是从一个函数指向一个对象。它的含义是函数的原型对象,也就是这个函数所创建的实例的原型对象,由此可知:
f1.__proto__ === Foo.prototype
prototype
属性的作用:
它的作用就是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。
四、constructor
属性
constructor属性也是对象才拥有的,它是从一个对象指向一个函数,含义就是指向该对象的构造函数,每个对象都有构造函数,从图中可以看出
Function
这个对象比较特殊,它的构造函数就是它自己(因为Function
可以看成是一个函数,也可以是一个对象),所有函数最终都是由Function()
构造函数得来,所以constructor属性的终点就是Function()。
五、常用方法
hasOwnProperty()
与in
操作符
作用:判断函数的原型所在位置
function Person () { };
Person.prototype.name = "志玲";
var p1 = new Person();
p1.sex = "女";
//定义一个函数去判断原型所在的位置
function propertyLocation(obj, prop){
if(!(prop in obj)){
alert(prop + "属性不存在");
}else if(obj.hasOwnProperty(prop)){
alert(prop + "属性存在于对象中");
}else {
alert(prop + "对象存在于原型中");
}
}
propertyLocation(p1, "age"); //age属性不存在
propertyLocation(p1, "name"); //name对象存在于原型中
propertyLocation(p1, "sex"); //sex属性存在于对象中
六、动态原型模式创建对象
//构造方法内部封装属性
function Person(name, age) {
//每个对象都添加自己的属性
this.name = name;
this.age = age;
/*
判断this.eat这个属性是不是function,如果不是function则证明是第一次创建对象,
则把这个funcion添加到原型中。
如果是function,则代表原型中已经有了这个方法,则不需要再添加。
perfect!完美解决了性能和代码的封装问题。
*/
if(typeof this.eat !== "function"){
Person.prototype.eat = function () {
alert(this.name + " 在吃");
}
}
}
var p1 = new Person("志玲", 40);
p1.eat(); //志玲 在吃