JavaScript不包含传统的类继承模型,而是使用prototypal原型模型。
一、原型
刚开始写代码的时候,如下代码:
1.原型使用方式1:
在使用原型之前,将代码做些修改:
然后,通过给Calculator对象的prototype属性赋值来设定对象的原型。
2.原型使用方式2:
在赋值原型prototype的时候使用function立即执行的表达式来赋值。
Calculator.prototype = function(){}();
它的好处在于可以封装私有的function,通过return的方式暴露出简单的使用名称,以达到public/private的效果,修改后的代码如下:
3.分步声明:
上述使用原型的时候,有一个限制就是一次性设置了原型对象,分别设置原型的每个属性如下:
4.重写原型:
*注意:重写的代码需要放在最后,才能覆盖前面的代码。在使用第三方JS库的时候,往往有时候他们定义的原型方法不能满足我们的需要,但是又离不开这个类库。这个时候我们就需要重写他们的原型中一个或多个属性或function,我们可以通过继续声明同样的add代码的形式来达到重写前面的add功能,代码如下:
二、原型链
1.实例:
上面的例子中,test对象从Bar.prototype和Foo.prototype中继承下来,因此它能访问Foo的原型方法method,它也能访问那个定义在原型上的Foo实例属性value。需要注意的是new Bar()不会创建一个新的Foo实例,而是反复使用它原型上的那个实例;因此,所有的Bar实例都会共享相同的value属性。
2.属性查找:
当查找一个对象的属性的时候,JavaScript会向上遍历原型链,直到找到给定名称的属性为止,到查找到达原型链的顶端,也就是Object.prototype,但是没有找到指定的属性,就会返回undefined。
属性在查找的时候是先查找自身的属性,如果没有再查找原型,再没有再往上走,一直查到Object的原型上,所以在某种层面上说,用for in 语句遍历属性的时候,效率也是个问题。
需要注意的是,我们可以赋值任何类型的对象到原型上,但是不能赋值原子类型的值,比如如下代码是无效的。
function Foo(){ }; Foo.prototype = 1; //无效
3.hasOwnProperty函数
hasOwnProperty是Object.prototype的一个方法,可以判断出一个对象是否包含自定义属性而不是原型链,因为hasOwnProperty是JavaScript中唯一一个处理属性,但是不查找原型链的函数。
只有hasOwnProperty可以给出正确和期望的结果,这在遍历对象属性时会很有用。JavaScript不会保护hasOwnProperty被非法占用,因此如果一个对象碰巧存在这个属性,就需要使用外部的hasOwnProperty函数来获取正确的结果。
我们没办法改变for in 语句的行为,所以想过滤结果就只能使用hasOwnProperty方法,代码如下:
这个版本的代码是唯一一个正确的写法。如果不使用hasOwnProperty,则这段代码在原生对象原型(比如Object.prototype)被扩展的时候可能会出错。
网友评论