Js prototype 总结

prototype属性用于返回对象的类的原型。 
    无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,该属性保存着函数的原型对象。prototype属性使我们有能力向原型对象添加属性和方法,并且这些属性和方法是这一类对象所共享的。另外所有函数的 默认原型都是Object的实例,因此所有的对象都具有Object的属性和方法,例如:toString()、valueOf()等。 通过prototype为function类添加的属性和方法只能在类型的实例上体现。
     JavaScript内置对象的prototype属性是只读的,其本身就是一个对象,我们只能够对该对象的属性和方法进行操作,比如添加属性或方法、删除属性和方法,而不能使用另一个对象来替换该对象,哪怕是另外一个原型对象。(这里说的仅仅是JavaScript的内置对象,并不包括自定义的对象)。
    所谓不能用另一个对象来替换该对象即是说用新对象(或原型对象)替换后,该对象原有的prototype对象属性将不存在了,这种做法从规范的角度不建议采用,下面举例说明这种情况:
var Person = function (){};
Person.prototype.ask = function (){
	return "Person ask called"
}
var Programmer = function(){};
Programmer.prototype.writeName= function(){
	return "Programmer writeName called"
}
Programmer.prototype = new Person();//更改Programmer的Prototype对象,不建议这种做法
var p = new Programmer(); 
p.writeName();//Error writeName未定义
p.ask();//Person ask called

prototype属性的设计来源

首先看一个具体的例子
function Person(){
    this.say = function(name){
        alert(name+" say hello");
    };
}
var zhang = new Person();
zhang.say("zhang"); // zhang say hello
var li = new Person();
li.say("li"); // li say hello
// 为zhang 添加ask方法
zhang.ask = function(name){
        alert(name+" ask");
};
// 调用zhang的ask方法
zhang.ask("zhang");// zhang ask
// 调用li的ask方法
li.ask("li"); //将会报错,因为li没有ask方法
     如上面代码的最后一行报错,是由于在不引入prototype前,实例之间属性和方法都是独立存在,对一个对象的属性和方法进行添加/删除,并不会影响到另一个"同类"对象。这样的设计就造成了极大的资源浪费。至于属性,有些时候我们也是希望能够在两个对象内部共享一些属性的。于是JavaScript的设计者布兰登·艾奇(Brendan Eich)就想到在函数中添加一个prototype属性,这个属性用来保存一些供所有"同类"实例对象共享使用的属性和方法。
     当我们访问一个实例对象的属性和方法时,JavaScript先查找对象本身是否存在这些属性或方法,如果有就直接返回;如果不具备,就查询创建该对象的类(即函数)的prototype属性中是否存在同名的属性或方法,如果有就返回。由于prototype属性本身就是一个对象(一般称之为原型对象),这看起来就有点像"继承":实例对象"继承"了prototype对象的属性和方法。
注:在实例上不能使用prototype,否则发生编译错误。
function Person(){
    this.say = function(name){
        alert(name+" say hello");
    };
}
var zhang = new Person();
zhang.say("zhang"); // zhang say hello
var li = new Person();
li.say("li"); // li say hello
//为prototype添加ask方法
Person.prototype.ask= function(name){
        alert(name+" ask");
};
// 调用zhang的ask方法
zhang.ask("zhang");// zhang ask
// 调用li的ask方法
li.ask("li");// li ask

拓展知识:

JS中的prototype和__proto__区别

prototype
    函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。它是显示修改对象的原型的属性。
__proto__
    是一个 对象拥有的内置属性(请注意: prototype是函数的内置属性,__proto__是对象的内置属性),是JS内部使用寻找原型链的属性。
  用chrome和FF都可以访问到对象的__proto__属性,IE不可以。

下面我们看下new 过程
var Person = function(){};
var p = new Person();
new的过程拆分成以下三步:
(1) var p={}; 也就是说,初始化一个对象p
(2) p.__proto__ = Person.prototype;
(3) Person.call(p); 也就是说构造p,也可以称之为初始化p

当调用p的内部方法(或属性)时 会先在this的内部查找(也就是构造函数内部),如果没有找到然后再沿着原型链向上追溯。 这里的向上追溯是怎么向上的呢?这里就要使用__proto__属性来链接到原型(也就是Person.prototype)进行查找。最终在原型上找到方法(或属性)。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值