您的位置:首页 > 编程语言 > Java开发

javaScritp 中prototype属性继承原理详解

2016-02-25 17:28 405 查看
转载请说明出处:http://blog.csdn.net/liuqiwen0512/article/details/8095306

上一篇文章我们说了jQuery 运用jQuery.fn.init.prototype = jQuery.fn;巧妙的避开了 instanceof 的运算。

要解释这个问题就需要先了解prototype属性的继承原理,比如toString方法,我们创建一个对象不用给对象

添加toString方法照样可以用。这是为什么,是创建对象的时候js自动给对象添加了toString方法,还是通过上面途径

找到了toString方法。这里可以告诉你我们用new关键字创建出来的对象要是你没给它添加toString属性的话,

那么它调用的就是Object对象的prototype.toString。这是为什么,有的童鞋说是继承,但是它又是怎样继承的,

toString到底放在哪,看完这篇文章你就明白了。还有一个问题就是instanceof运算符到底是怎么运算的,

它的依据和原理是什么,同样看完这篇文章你也就明白了。

protype继承原理:

其实我们用function关键字声明的方法,在后台js会把他们创建成Function对象。这个对象中有两个属性,一个是prototype

这个属性是显式属性也就是说我们可以访问的属性。还有一个属性就是__proto__这个属性是隐式的,也就是说默认

情况下我们不可以访问,而且这个属性在个浏览器的表示可能还不一致,默认情况下是__proto__。这个属性在chrome

浏览器是可以访问的,但是在IE下就不可以访问,不知道是IE不让访问,还是表示不一样,没研究。

prototype属性是一个指针,指向一个实例化的Object对象。这个对象默认有两个属性,一个是显式属性constructor,

这个属性是指向prototype属性所在的构造函数,这样prototype属性所指向的Object对象和构造函数就形成了循环

指向。还有一个隐式属性默认是__proto__指向它的父对象也就是js内置的Object对象的prototype属性所指向的

一个实例化的Object对象。

下面看例子说话:

[javascript] view plain copy

print?

function Person(){

this.name="刘奇文";

this.age=22;

}

Person.prototype={

showName:function(){

console.log(this.name);

},

name:"liuqiwen"

}

function Man(){

this.name="刘奇文man";

this.age=22;

}

Man.prototype=Person.prototype;

var man1=new Man();

console.log(man1.name);//结果:刘奇文man

man1.showName();//结果:刘奇文man

delete man1.name;//删除实例中的name属性

console.log(man1.name);//结果:liuqiwen

man1.showName();//结果:liuqiwen

console.log(man1.constructor);//结果:function Object() {[native code]}

console.log(man1 instanceof Man);//结果:true

console.log(man1 instanceof Person);//结果:true

console.log(man1 instanceof Object);//结果:true

上面代码解释:

创建一个构造函数Person,给构造函数添加两个属性。然后再初始化构造函数的原型链prototype属性,

给prototype添加两个属性,在创建一个构造函数Man,给构造函数添加两个属性。然后再初始化 构造函数

的原型链prototype属性,让prototype属性等于Person的prototype属性,也就是说这两个构造函数的prototype

指向的是同一个Object对象。然后创建一个man1的一个实例,调用man1的name属性得到结果正是实例中

属性的值,调用man1的showName方法得到也是实例中属性值结果都正确,我们再删除实例中name属性

我们再重复上面的操作发现结果是原型链中属性的值,我们再调用man1的constructor属性,这个属性

上面已经说过是得到这个实例的构造函数的引用,上面我们既没有给实例定义这个属性,原型链中也

没有这个属性,那么调用这个属性得到的值是哪里来的,为什么还是Object。

对象属性的查找顺序:

其实我们没有给prototype属性赋值时,prototype属性默认指向的Object对象是有

constructor这个属性的,由于这个属性是显式的是我们可控制的,所以当我们给prototype属性初始化

时是让它指向了另一个对象,而这个对象中没有此属性,我们也可加上这个属性。当对象在实例中

没有找到要调用的属性,那么他会从他的隐式属性__proto__所指向的原型链中查找,如果还没找到,

那么他会继续查找原型链中的隐式__proto__属性所指向的对象,

也就是实例的父对象Object对象的原型链,所以返回值是Object的构造函数。

总结:实例对象属性查找顺序是 实例对象内部---->构造函数原型链---->实例对象父对象的原型链。

instanceof运算符:

上面man1 instanceof Man结果为true,运算符先运算Man.prototype然后再查找man1中的__proto__

所指向的Object是否为Man.prototype。由于Person.prototype和Man.prototype指向的是同一个Object

所以man1 instanceof Person结果为true。man1 instanceof Object由于man1中的__proto__指向的

不是Object.prototype所以运算符会继续查找__proto__指向的对象中的__proto__属性,也就是实例

父对象的prototype指向的对象,Object是实例man1的父对象所以运算结果为true。

通过关系图来了解他们之间的关系

继承关系图:



下篇分析下构造函数和Object之间的关系 ,js内置对象之间的关系。

上图中 Function 和 Object之间的关系有些地方好像不太对,

还需研究,如果哪位仁兄知道的话,请赐教。

转载请说明出处:http://blog.csdn.net/liuqiwen0512/article/details/8095306
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: