JavaScript小进阶9--一张图看尽原型及底层模拟
一张图就可以看尽js的原型:注意红色箭头,就是js的原型链!!
由上面,两个注意:
1. console.log(X.prototype.__proto__);// 一个Object对象:{}
console.log(X.prototype.__proto__.__proto__);//null
__proto__是每个对象都具有的属性(在W3C标准的浏览器中,我们才可以直接访问);prototype是每个function对象都具有的属性;然而,constructor确是原型对象而非普通实例对象具有的属性,系统自动为原型对象预添加的。
问题1:原型对象是怎么来的?什么是原型的继承??
答:其实,在系统载入定义的(任何函数)function Person时,会同时执行:Person.prototype = new Object(); Person.prototype.constructor = Person; 两者的关系的建立是系统底层自动完成的。因此原型对象Person.prototype的所有初始属性都是从Object中继承而来,而Person类的实例对象的初始属性再继承自原型对象,即也是从Object中继承而来,此乃原型继承。是故,可以理解为:Object类是所有类的父类。
如下一个例子:
Object.prototype.appleCount = 1000;//所有实例对象都会具有appCount属性!!!
console.log(p1.appleCount);//打印:1000
问题2:当实例对象和其原型具有部分同名属性时,js引擎会如何选择?
当实例对象和其原型具有部分同名属性时的一种情况:
var base = {
name : "base",
getName : function(){
console.log(this.name);//会打印
}
}
var p1 = {
name : "p1",
}
p1.__proto__ = base;
p1.getName();//!!!!打印出p1
这里有点类似于java中的:覆盖!!!可以理解为:父类的引用指向子类的对象!!
js对象产生对象的底层模拟(纯属意淫):
//首先我们有一个Person函数:
function Person(){this.name = "luozhixiao";}
//1)当加载函数Person时,创建Person函数对象,然后执行:
Person.prototype = {};
Person.prototype.constructor = Person;
//2)当我们执行:new Person() 创建类对象时,底层实现模拟如下:
var __Person_Obj__ = {};
__Person_Obj__.__proto__ = Person.prototype;//这里是重点!
Person.apply(__Person_Obj__);