你的位置:首页 > Java教程

[Java教程]谈谈我对JS原型的理解


昨天阿里实习的第一次电面,也是我人生中的第一次电面,问了很多问题。结果还行吧,算是进入了下一轮。虽然不知道姓名,但还是要感谢面我的那个前辈。好吧,言归正传,为什么要写这篇关于原型的博文呢?因为电面时被问到了。当时有点紧张,感觉回答的很不理想,也许是自己还没有牢固的掌握吧!所以今天就写一写我对原型的理解,顺便理一下自己的思路。

首先,JS没有类继承机制,它是靠原型机制实现继承的,两种方式孰优孰劣,在此不做评判(知识量不足╮(╯▽╰)╭)

先上代码解释这一机制:

var people = {  name: 'xiaoliu'};

对于JS中所有对象,都有一个内部属性(供解释器使用)_proto_,这个属性指向新建对象的原型,people对象字面量的原型是什么呢,它是Object.prototype。

如图:

当我们想执行toString()方法时,JS解释器做了什么呢?首先它会到peope对象里去找,即去找people里的自有属性,当找到了就去调用该方法,没找到,就到它_proto_所引用对象里去找,找到了,他就执行原型里的这个方法(子类属性覆盖父类属性)。所以我们说people对象继承了object.prototype里的方法,但是我更推荐大家这么说Object.prototype是所有对象(people)的原型。

下面咱们来做这么一件事:

people.toString = functino(){};

JS解释器会做什么呢,他还会到原型上找到toString属性然后赋值么。当然不行,这样做的话,所有继承了Object.prototype的对象的toString属性都会改变。因此赋值时JS解释器就直接看people对象里的自有属性有没有,如果有,改。如果没,就新建一个属性赋值。

上代码证明:

var people = {  name: 'xiaoliu'};console.log(people.hasOwnProperty('toString'));/*赋值前 false*/people.toString = function(){};console.log(people.hasOwnProperty('toString'));/*赋值后 true*/

这样查找属性和属性赋值都没问题了,原型继承就这么实现了。

不过JS是不允许我们随意修改对象的原型链的,ES5中Object对象上有个getPrototypeOf()方法可以查看原型,但是无法修改。

下面再说说JS怎么初始化新建对象的原型的:

首先, 是对象字面量,上面已经说了,原型初始化成Object.prototype对象。

其次, 是利用对象模板(函数),使用new 运算符创建的对象,它会初始化成为该函数的prototype属性所指向的对象。

代码实例:

function People(){  this.name = 'xiaoliu';}/*对象模板*/People.prototype = {
constructor: People,/*原来People.prototype指向的对象中默认的唯一不可枚举属性,现在修改了prototype的引用,所以最好再恢复一下*/
toString: function(){return this.name}
};/*修改原型*/var people = new People();/*创建对象*/people.toString();/*执行继承方法*/

最后,是通过ES5提供的Object.create()方法

代码实例:

var people = {name: 'xiaoliu'};var a = Object.create(people);/*创建一个新对象,并把原型_proto_初始化为people对象*/a.name;/*返回原型链上的name属性*/

好吧,先到此为止吧,以后有机会再谈谈this。

如有错误,欢迎指正^_^