一张图解释javascript原型、原型链,对象、原型对象,模拟类,模拟继承。

来源:互联网 时间:1970-01-01

 

 

 

 

 

                                                            图1 关系图解

 

 

__proto__(双横线):javascript中对象内置的隐藏属性,类似指针,指向其引用对象的原型对象。

prototype:函数对象的一个属性,也类似于一个指针,指向其原型对象。

Point{}:Point的原型对象。

Point:Point的构造函数。

 

如图1,定义一个函数 Point(),其中Poin对象增加p1属性,Point原型对象增加一个sum方法。p1,p2为Point()的实例化对象,name1,name2分别为p1,p2的属性。代码如下:

function Point(){

      var p1 = "测试点";

}

Point.prototype.sum = function (){

   var sum = function(){

       return 1+2;

     }     

}

var P1 = new Point();

var P2 = new Poin();

P1.name1 = "点1";

P2.name2 = "点2";

 

P1拥有的属性和方法:sum方法,Name1属性。

P2拥有的属性和方法:sum方法,Name2属性。

javascript搜索一个对象的属性和方法,先默认搜索自身的属性和方法,如果自身没搜索到,再通过__proto__属性找到其引用对象的原型对象,如此通过__proto__一层层往下找,最终__proto__的指针指向null;

诸如:P1-->Point{}-->Object{}-->null 通过__proto__形成的一条链路,这条链路便是原型链。

 

通过上述代码模拟了一个Point类 ,其中p1为Point的私有属性,sum为Point的公共方法。通过new Point()建立的为Point的实例化对象,拥有Point的所有公共属性和方法。

若想获取 Point的私有属性,可以进行如下改造:

function Point(){

      var p1 = "测试点";

      this.getP1 = function (){

            return this.p1;

     }

}

这样,就能对Point实现封装,提供读取p1属性的方法。

 

有了Point类,也能进行封装了,那如何实现继承?

由关系图可知,通过 Animal.prototype = new Point(); 就可以实现继承,Animal继承了Point,拥有Point的所有公共属性和方法。A1为Animal的实例化对象,则A1 不仅拥有Animal的所有公共属性和方法,而且拥有Point的所有公共属性和方法。代码如下:

function Animal(){

          var add1 = function (){ return "add1";};

          this.add2 = function (){ return "add2";};

}

 Animal.prototype.run = "run";   //此行不是代码内容,只是为了测试更改原型对象后此属性是否还存在。

Animal.prototype = new Point();

var A1 = new Animal();

 

此时A1拥有的属性和方法为:add2方法,sum方法。add1作为Animal的私有方法无法获取,run则属性Animal以前的原型对象的属性,也无法获取,sum作为Animal继承的方法,能够获取。而A1能够拥有add2方法则是因为在Javascript中,this指向函数执行时的当前对象该关键字在Javascript中和执行环境,而非声明环境有关。 this关键字虽然是在定义Animal的时候生成的,但是在new Animal()的时候才执行,因此add2得以存在。

 

 

PS:自己画的图和写的内容,非转载,刚毕业的菜鸟,如果我理解的有不对的地方欢迎大家指正。

另:原型链固然强大,但是因为javascript是动态语言,通过原型链甚至能修改继承的父类的属性和方法,还能给父类增加读写方法。关于如何防止别人随意篡改父类的属性,还请大牛们指点一二。

 



相关阅读:
Top