JS中prototype属性的理解

来源:互联网 发布:淘宝店设计多少钱 编辑:程序博客网 时间:2024/04/26 09:05

1.prototype属性在js中模拟了父类的角色,在js中体现面向对象的思想


首先让我们来看两个demo:

demo1:

function Person(name,sex){this.name=name;this.sex=sex;}Person.prototype.age=12;Person.prototype.print=function(){alert(this.name+"_"+this.sex+"_"+this.age);};var p1 = new Person("name1","male");var p2=new Person("name2","male");p1.print();//name1_male_12p2.print();//name2_male_12Person.prototype.age=18;p1.print();//name1_male_18p2.print();//name2_male_18

demo2:

function Person(name,sex){this.name=name;this.sex=sex;}Person.prototype.age=12;Person.ptototype.print=function(){alert(this.name+"_"+this.sex+"_"+this.age);}var p1=new Person("name1","male"); //p1的age属性继承了Person类的父类(即prototype对象)var p2=new Person("name2","male");p1.print();//name1_male_12p2.print();//name2_male_12 p1.age=34 //改变p1实例的age属性p1.print();//name1_male_34p2.print();//name2_male_12Person.prototype.age=22;//改变Person类的超类的age属性p1.print();//name1_male_34(p1的age属性没有随着prototype属性的改变而改变)p2.print();//name2_male_22(p2的age属性发生了改变)p1.print()=function(){alert("i am p1")};p1.print();//I am p1(p1的方法发生了改变)p2.print();//name2_male_22(p2的方法并没有改变) Person.prototype.print=function(){alert("new print method")};//改变超类的方法p1.print();//I am p1(p1的print方法仍旧是自己的方法 )p2.print();//newprint method(p2的print方法随着超类的方法改变而改变)

js中对象的prototype属性相当于java中的static变量,可以被这个类下的所有对象公用。


从基础上来分析:

1.普通函数与构造函数

调用构造函数:new function_name();
调用普通函数:function_name();
在函数中有一个this对象,this始终代表该函数的调用者。
如果是构造函数,this就是构造出来的新对象。
如果是普通函数,this就是 window 对象。

如果使用new 关键字调用,那么函数的 return 语句不再起作用,因为这时还回的是 this 对象。

function Boo(name){  this.name=name;    this.whatAreYou=function(){    return 'I am a '+ this.name;    };  }  var obj  = new Boo("obj");  Boo.name = "Boo";  alert(obj.name + "\n" + Boo.name); 


创建对象最好采用下面方式
用构造函数定义对象的成员属性属性,用原型方式定义对象的成员方法。
这样的好处是:每个对象都共享一个方法,并且都具有自己独立的属性实例。

function Car(sColor,iDoors,iMpg) {    this.color = sColor;    this.doors = iDoors;    this.mpg = iMpg;    this.drivers = new Array("Mike","John");  }  Car.prototype.showColor = function() {    alert(this.color);  };  var oCar1 = new Car("red",4,23);  var oCar2 = new Car("blue",3,25);  oCar1.drivers.push("Bill");  alert(oCar1.drivers); //输出 "Mike,John,Bill"  alert(oCar2.drivers); //输出 "Mike,John"  




js中的this的用法:

1、全局变量用法,纯粹函数调用。

function test() {    this.x = 1;    alert(x);}test();

var x = 1;function test() {    alert(this.x);}test();//1var x = 1;function test() {    this.x = 0;}test();alert(x);//0

2.作为方法调用,那么this就是指这个上级对象。

function test() {    alert(this.x);}var o = {};o.x = 1;o.m = test;o.m(); //1

3、作为构造函数调用。所谓构造函数,就是生成一个新的对象。这时,这个this就是指这个对象。

function test() {    this.x = 1;}var o = new test();alert(o.x);//1

4、apply调用

this指向的是apply中的第一个参数。

var x = 0;function test() {    alert(this.x);}var o = {};o.x = 1;o.m = test;o.m.apply(); //0o.m.apply(o);//1

当apply没有参数时,表示为全局对象。所以值为0。


------this指针代表的是执行当前代码的对象的所有者。


js原型链和prototype的深入理解:

说到prototype,就不得不先说下new的过程。

<script type="text/javascript">var Person = function () { };var p = new Person();</script>

我们可以把new的过程拆分成以下三步:

<1> var p={}; 也就是说,初始化一个对象p。

<2> p.__proto__=Person.prototype;

<3> Person.call(p);也就是说构造p,也可以称之为初始化p。

关键在于第二步,我们来证明一下:

<script type="text/javascript">2var Person = function () { };3var p = new Person();4alert(p.__proto__ === Person.prototype);5</script>

这段代码会返回true。说明我们步骤2的正确。

那么__proto__是什么?我们在这里简单地说下。每个对象都会在其内部初始化一个属性,就是__proto__,当我们访问一个对象的属性 时,如果这个对象内部不存在这个属性,那么他就会去__proto__里找这个属性,这个__proto__又会有自己的__proto__,于是就这样 一直找下去,也就是我们平时所说的原型链的概念。

按照标准,__proto__是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。

<script type="text/javascript">2var Person = function () { };3Person.prototype.Say = function () {4alert("Person say");5}6var p = new Person();7p.Say();8</script>

那就让我们看下为什么p可以访问Person的Say。

首先var p=new Person();可以得出p.__proto__=Person.prototype。那么当我们调用p.Say()时,首先p中没有Say这个属性, 于是,他就需要到他的__proto__中去找,也就是Person.prototype,而我们在上面定义了 Person.prototype.Say=function(){}; 于是,就找到了这个方法。

<script type="text/javascript">02var Person = function () { };03Person.prototype.Say = function () {04alert("Person say");05}06Person.prototype.Salary = 50000; 07var Programmer = function () { };08Programmer.prototype = new Person();09Programmer.prototype.WriteCode = function () {10alert("programmer writes code");11}; 12Programmer.prototype.Salary = 500; 13var p = new Programmer();14p.Say();15p.WriteCode();16alert(p.Salary);17</script>


好,算清楚了之后我们来看上面的结果,p.Say()。由于p没有Say这个属性,于是去p.__proto__,也就是 Programmer.prototype,也就是p1中去找,由于p1中也没有Say,那就去p.__proto__.__proto__,也就是 Person.prototype中去找,于是就找到了alert(“Person say”)的方法。

其余的也都是同样的道理。

这也就是原型链的实现原理。

最后,其实prototype只是一个假象,他在实现原型链中只是起到了一个辅助作用,换句话说,他只是在new的时候有着一定的价值,而原型链的本质,其实在于__proto__!









0 0
原创粉丝点击