理解原型原型是一个对象,其他对象可以通过它实现属性继承。任何对象都可以被继承,所有的对象默认都有一个原型,因为原型本身也是一个对象,所以每个原型都有自己的原型。任何对象都有一个原型属性,记录为:__proto__。每当我们定义一个对象时,它的__proto__属性指向它的原型。例子如下:varfoo={x:10,y:20};即使我们没有指定原型,这个属性也是保留的。如果我们有一个明确的点,那么这个链表就是连通的。需要注意的是,prototype本身还有一个点,就是第一层的object.prototype。例子如下:vara={x:10,calculate:function(z){returnthis.x+this.y+z}};varb={y:20,__proto__:a};varc={y:30,__proto__:a};//calltheinheritedmethodb.calculate(30);//60使用原型了解了原型的原理之后,如何使用原型呢?或者原型的作用是什么?一般的初学者,在学习基本的javascript语法后,通过面向函数的编程来编程。以下代码:vardecimalDigits=2,tax=5;functionadd(x,y){returnx+y;}functionsubtract(x,y){returnx-y;}//alert(add(1,3));通过执行每个功能以获得最佳结果。但是使用原型,我们可以优化我们的一些代码并使用构造函数:首先,只有变量存储在函数体中:varCalculator=function(decimalDigits,tax){this.decimalDigits=decimalDigits;this.tax=tax;};它的具体方法是通过prototype属性设置的:Calculator.prototype={add:function(x,y){returnx+y;},subtract:function(x,y){returnx-y;}};//alert((newCalculator()).add(1,3));这样实例化对象后就可以进行相应的函数操作了。这也是一般的js框架采用的方法。原型的另一个功能是实现继承。首先定义父对象:varBaseCalculator=function(){this.decimalDigits=2;};BaseCalculator.prototype={add:function(x,y){returnx+y;},subtract:function(x,y){返回x-y;}};然后定义子对象,将子对象的原型指向父元素的实例化:varCalculator=function(){//为每个实例声明一个税号this.tax=5;};计算器。原型=newBaseCalculator();我们可以看到Calculator的原型指向了一个BaseCalculator的实例,目的是让Calculator集成它的add(x,y)和subtract(x,y)两个函数,还有一点我想说的就是因为它的原型是BaseCalculator的一个实例,所以无论你创建多少个Calculator对象实例,它们的原型都指向同一个实例。运行上面的代码后,我们可以看到,因为Calculator的原型指向了BaseCalculator的实例,所以我们可以访问它的decimalDigits属性值。如果我不想让Calculator访问BaseCalculator的构造函数中声明的属性值,那怎么办呢?只需将Calculator指向BaseCalculator的原型而不是实例。代码如下:varCalculator=function(){this.tax=5;};Calculator.prototype=BaseCalculator.prototype;在使用第三方库的时候,有时候他们定义的原型方法不能满足我们的需求,那么我们可以自己添加一些方法,代码如下://overridetheadd()functionCalculator.prototype.add=function(x,y){returnx+y+this.tax;};varcalc=newCalculator();alert(calc.add(1,1));原型链对象的原型指向对象的父对象,父对象的原型指向父对象的父对象。这种原型层层叠叠的关系称为原型链。在查找对象的属性时,javascript将遍历原型链,直到找到具有给定名称的属性。当查找到原型链的顶端,即Object.prototype,仍然没有找到指定的属性时,会返回undefined。这是一个例子:functionfoo(){this.add=function(x,y){returnx+y;}}foo.prototype.add=function(x,y){returnx+y+10;}Object.prototype.subtract=function(x,y){returnx-y;}varf=newfoo();alert(f.add(1,2));//结果是3,不是13alert(f.subtract(1,2)));//结果为-1。我们可以发现subtrace遵循的是向上查找的原则,而add却出了意外。原因是在查找属性时,先查找自己的属性,如果没有,再查找原型。说到Object.prototype,就不得不提到它的一个方法,hasOwnProperty。它可以判断一个对象是否包含自定义属性而不是原型链上的属性。它是javascript中唯一处理属性但不查找原型链的函数。代码如下://修改Object.prototypeObject.prototype.bar=1;varfoo={goo:undefined};foo.bar;//1'bar'infoo;//truefoo.hasOwnProperty('bar');//falsefoo.hasOwnProperty('goo');//true为了判断原型对象与实例的关系,我们不得不引入isPrototyleOf方法,如下所示:alert(Cat.prototype.isPrototypeOf(cat2));//真的
