【有书共读】JavaScript面向对象编程指南 5

原型属性 prototype
在函数定义是,被创建的属性中包括有prototype,这就是原型属性。其初始值是一个空对象。如:



可通过foo.prototype = {}添加自身属性。

添加方法与属性
1、在构建构造函数时,添加方法与属性:




2.通过原型prototype添加属性




原型prototype添加属性可以逐条添加,也可以定义对象覆盖之前的原型上。


使用原型的方法与属性
向prototype 属性添加方法与属性后,可以直接使用构造器创建对象,从而访问添加的属性与方法。


原型具有实时性,我们可以随时修改prototype属性,而且同一构造器创建的所有对象的prototype属性也会同时改变。
如为Gadget添加新的方法

而之前Gadget创建的newtoy对象还是能访问新增的方法:


自身属性与原型属性
当访问对象的某个属性时,JavaScript引擎会遍历该对象的所有属性,并查找该属性,若是找到则返回其值。如果没找到,则会查询该对象构造函数的原型,若是找到则使用属性。若是找不到,则继续找原型的原型,直到最高级的父级对象object。
如newtoy对象,name属性在newtoy对象中,但是rating在prototype中

> newtoy.name;
"webcam"
> newtoy.rating;
3

利用自身属性重写原型属性
对象自身属性优先级高于原型属性。当同一个属性名,同时出现在对象自身的属性与原型时,会优先取对象自身属性。


可以通过hasOwnProperty()方法判断属性是自身还是原型的。
> toy.hasOwnProperty('name');
true


如果删自身属性,则同名的原型属性生效:
> delete toy.name;
true
> toy.name;
"mirror"
> toy.hasOwnProperty('name');
false

属性删除后,也可以随时重建
> toy.name = 'camera';
"camera"
> toy.name;
"camera"

也可通过hasOwnProperty()判断原型属性是属于原型链中的哪个原型。
> toy.toString();
"[object Object]"
> toy.hasOwnProperty('toString');
false
> toy.constructor.hasOwnProperty('toSrting');
false
> toy.constructor.prototype.hasOwnProperty('toString');
false
> Object.hasOwnProperty('toString');
false
> Object.prototype.hasOwnProperty('toString');
true


枚举属性
可以通过for-in循环显示对象的属性列表,但是不能显示所有。通过枚举propertyIsEnumerable()方法判断对象的某个属性是否可枚举,从而获取对象的显示属性。
若是原型链中的属性可枚举,也可显示出来。但所有原型的属性propertyIsEnumerable()都返回false,包括for-in中可枚举的属性。
function Gadget(name,color){
this.name = name ;
this.color = color;

this.getName = function(){
return this.name;
};
}

Gadget.prototype.price = 100;
Gadget.prototype.rating = 3;

var newtoy = new Gadget('webcam','black');


通过for-in列出对象的所有属性:




通过hasOwnProperty()获取对象自身属性


propertyIsEnumerable对所有非内建对象返回true,内见对象与方法返回false。任何原型链的属性都是不可枚举,但是原型链上的对象,是可枚举的。
> newtoy.propertyIsEnumerable('name');
true
> newtoy.propertyIsEnumerable('constructor');
false
> newtoy.propertyIsEnumerable('price');
false
> newtoy.constructor.prototype.propertyIsEnumerable('price');
true

isPrototypeOf()方法
每个对象都有一个isPrototypeOf()方法。用于判断当前对象是否是另外一个对象的原型。



__proto__链接
在JavaScript环境中,对象存在一个真相先关原型的链接。即是__proto__属性。
> var monkey = {
feeds :'bananas',
breathes : 'air'
};

>function Human(){}
>Human.prototype = monkey;
{feeds: "bananas", breathes: "air"}
>var developer = new Human();
>developer.feeds = 'pizza';
developer.hacks = 'JavaScript';
"JavaScript"
>developer.__proto__ === monkey;
true

注意:__proto__ 只能在学习或调试环境下使用。

扩展内建对象
在JavaScript环境中,内建对象的构造器函数都可以通过对其原型进行扩展。如:定义一个查询数组是否存在某个特定值的方法。





扩展内建对象是非常强大,但是必须谨慎。因为通过原型内建对象的方法属性,若是被他人修改,则容易引起该对象的行为改变,容易导致难以维护。另外原型内建的对象,若是随着JavaScript的发展,变为JavaScript的内置对象,就会导致两者冲突。
此时,我们可以通过方法解决:

>if (typeof String.prototype.trim !== 'function'){
String.prototype.trim = function(){
return this.queryReplace(/^\s+|\s+&/g,'');
}
};

> "hello ".trim();
"hello"




小结:
  • 在JavaScript中,所有函数都会拥有一个叫做prototype的属性。默认是为‘空’对象。
  • 可在原型对象中添加新的方法属性,也可以自定义对象来完全替换原有的原型对象。
  • 通过构造器新建对象时(new),该对象会自动拥有指向prototype属性的链接。可通过prototype属性访问相关原型对象的属性。
  • 对象自身属性优先级高于原型对象中的同名属性
  • 可通过hasOwnProperty()方法区分对象自身属性与原型属性
  • 当原型链接中,访问某个对象的属性,JavaScript引擎会先搜索该对象,若对象中不存在该属性,则会继续搜索其他原型的原型,直到最高父级原型Object.prototype。
  • 可对内建的构造器进行扩展,以便所有的对象都能引用添加的功能。在添加相关方法和属性之前,应该检查已有方法是否已存在。这样会增加脚本对未来环境的适应能力。


#Java#
全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务