Javascript OO 基础概念(二)-prototype

函数的原型

无论什么时候,只要创建了一个新函数,就会根据js特定的规则为该函数创建一个prototype原型,默认的prototype是一个对象,并且拥有一个constructor属性,该属性指向那个构造函数。

1function Person(){}
2alert(typeofPerson.prototype); //[object]
3alert(Person.prototype.constructor == Person);// true

实例与原型的关系

构造函数的实例有一个隐藏的指向原型的指针(_proto_),但是我们不能通过脚本来访问它,但是这里有个关系:这个指针存在于实例与原型之间,而不是存在于实例与构造函数之间。换句话说,实例与构造函数之间没有直接的关系。

01function Person(){}
02    Person.prototype = {
03        name:'samir',
04        getName:function(){
05            returnthis.name;
06        },
07        copyright:'cmstop'
08    }
09    vara = new Person();
10    varb = new Person();
11    alert(a.name);
12    alert(b.name);

上边这个例子中,虽然Person是个空函数,但是它的实例却有name属性,因为它们的指针都指向prototype,我们可以a.name,a.getName(),
a.copyright来读取属性或方法,那他们到底是怎样的机制呢?
实例搜索原型流程

当代码流执行到实例的对象或方法时,首先会搜索实例对象本身,如果实例对象有对应的属性和方法的时候,就会停止搜索原型对象,如果搜索到实例对象没有相关方法或属性时,就会搜索对应构造函数的原型对象,最终还会搜索到Object.prototype,如果开始到结束都未搜索到相关方法或属性,则undefined,未定义相关属性或方法。
优先级:由搜索过程可知,实例对象自身的属性优先级最高,可决定搜索过程是否中断。
优先级决定了读写问题,给实例添加属性以后,程序就不会再去访问prototype上的相关属性了,所以就起到了原型对象对于实例对象来说是不可写的的机制。

01function Person(){}
02    Person.prototype = {
03        name:'samir',
04        getName:function(){
05            returnthis.name;
06        },
07        copyright:'cmstop'
08    }
09    vara = new Person();
10    a.name ='zsen';
11    //a.name已经在上一行添加了,(实例对象本身优先级高)
12    //所以代码读到a.name时候,就不会再去读prototype.name了,
13    alert(a.name);// zsen
14
15    a.qq = 263575319;
16    //qq这个属性在原型中是不存在的,在添加的时候实际上是添加到了实例对象上,实例对象具有读写优先级。
17    alert(a.qq);
18    //我们可以验证上边的结论
19    alert(Person.prototype.hasOwnProperty('qq'));//false
20    alert(a.hasOwnProperty('qq'));//true

总结一下:
1、实例对象指向原型对象,包括实例.constructor属性也是从原型对象读到的
2、实例对象具有读写优先级,往实例上添加属性或方法后,那么原型对象上的相关属性和方法则被覆盖,这是由搜索机制决定的。
原型的共享

由实例与原型的关系可知,一个构造函数的所有实例都是指向同一个原型的,换句话说:构造函数的所有实例都共享同一个原型。

而每个实例之间都是相互独立的,换句话说:每个实例都是一份拷贝。

通常的做法,把方法的定义都写在原型上,这样可以避免重复定义相同方法。减少内存资源的消耗,当然总会有特殊情况。

凡事都有两面性,共享的好处之外也会引起其他问题
原型模式的问题

那就是引用类型的数据,

1function Person(){}
2    Person.prototype.friends = ['a','b'];
3    vara = new Person();
4    varb = new Person();
5    a.friends.push('c');
6
7    alert(b.friends[2]);//c

从这个例子来说,我们改变了一个实例的属性后,却在另一个实例中反映出来了,有些时候我们并不想这样,那我们对于这种引用类型来说,
我们应该给各自的实例特权方法呢,下一节在续。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值