艾利百科--临沂网站制作,临沂网页设计,临沂微信公众号,兼容并蓄,开放共赢!

艾利百科

当前位置: 主页 > 网站制作 > jQuery/JS >

JS中构造函数、原型及实例对象之间的关系

时间:2018-09-21 17:08来源:未知 作者:kunbeatable 点击:
构造函数和实例对象 构造函数就是一个函数,只不过它于普通的函数又有点不同: 没有显示的创建对象; 直接将属性和方法赋给this; 没有return语句; 构造函数是用来构造新对象的。可以是用new关键词来调用构造函数,以创建特定类型的新对象。如,创建一个Obj

构造函数和实例对象

构造函数就是一个函数,只不过它于普通的函数又有点不同:
  • 没有显示的创建对象;
  • 直接将属性和方法赋给this;
  • 没有return语句;
构造函数是用来构造新对象的。可以是用new关键词来调用构造函数,以创建特定类型的新对象。如,创建一个Object类型的对象实例:
         var o=new Object();
 
为了区别构造函数和普通函数,通常规定构造函数的命名首字母大写,而普通函数的命名首字母小写。

通过用构造函数创建并初始化的属性是实例属性。所谓的实例属性就是指,通过该构造函数创建的每个对象,都将拥有一份实例属性的单独拷贝。这些属性都是通过实例来访问的,值根据每个实例所定义的为准,若实例中没有定义,则为构造函数初始化时的默认值。来看一个例子:

function Person(name,age){
   this.name=name;
   this.age=age;
   this.friends=["Tom","Boo"];
}
 
var p1=new Person("Lily",20);
var p2=new Person("Sam",30);
 
alert(p1.name);  //Lily
alert(p2.name);  //Sam
p1.friends.push("Susan");
alert(p1.friends);  //Tom,Boo,Susan
alert(p2.friends);  //Tom,Boo
 
上面的例子定义了一个Person构造函数,并初始化了name、age和friends三个属性。接着创建了两个实例对象,分别为p1和p2。观察这个例子,每个属性都是为各自所拥有的,并不会相互影响。这就是因为每个实例对象都拥有一份属性的副本。

每个实例对象都有一个属性指向它的构造函数,这属性就是constructor:

function Person(name,age){
    this.name=name;
    this.age=age;
}
 
var p1=new Person("Lily",20);
var p2=new Person("Sam",30);
 
alert(p1.constructor==Person); //true
alert(p2.constructor==Person); //true
 
构造函数有一个prototype属性,指向原型对象。

原型对象和实例对象

在javascript中,每个对象都有一个与之相关联的对象,那就是它的原型对象。

造函数拥有一个prototype属性,指向原型。换句话来说,一个对象的原型就是它的构造函数的prototype属性的值。当一个函数被定义的时候,它会自动创建和初始化prototype值,它是一个对象,这时这个对象只有一个属性,那就是constructor,它指回和原型相关联的那个构造函数。看个例子:

function Person(name,age){
   this.name=name;
   this.age=age;
}
 
alert(Person.prototype); //[object Object]
alert(Person.prototype.constructor==Person); //true

也可以通过原型来创建属性和方法。通过原型创建的属性和方法是被所有实例所共享的。即,在一个实例中修改了该属性或方法的值,那么所有其他实例的属性或方法值都会受到影响:
 
function Person(name,age){
   this.name=name;
   this.age=age;
}
 
Person.prototype.friends=["Tom","Sam"];
 
var p1=new Person("Lily",24);
var p2=new Person("Susan",20);
 
alert(p1.friends); //Tom,Sam
alert(p2.friends); //Tom,Sam
 
p1.friends.push("Bill");
alert(p1.friends); //Tom,Sam,Bill
alert(p2.friends); //Tom,Sam,Bill
 

其实,很多情况下,这种现象并不是我们想看到的。那么什么时候应该用构造函数初始化属性和方法,哪些时候又该由原型对象来定义呢?

通常建议在构造函数内定义一般成员,即它的值在每个实例中都将不同,尤其是对象或数组形式的值;而在原型对象中则定义一些所有实例所共享的属性,即在所有实例中,它的值可以是相同的属性。

当用构造函数创建一个实例时,实例的内部也包含了一个指针,指向构造函数的原型对象。一些浏览器中,支持一个属性__proto__来表示这个内部指针:

function Person(name,age){
   this.name=name;
   this.age=age;
}
 
Person.prototype.sayName=function(){
   alert(this.name);
}
 
var p1=new Person("Lily",24);
 
alert(p1.__proto__.sayName); //function (){alert(this.name);}
 
alert(p1.__proto__.constructor==Person);  //true
 
在ECMAscript5中新增了一个方法,Object.getPrototypeOf(),可以返回前面提到的实例对象内部的指向其原型的指针的值:

function Person(name,age){
  this.name=name;
  this.age=age;
}
 
var p1=new Person("Lily",24);
 
alert(Object.getPrototypeOf(p1)==Person.prototype); //true

isPrototypeOf()方法也可用于确定实例对象和其原型之间的这种关系:

function Person(name,age){
   this.name=name;
   this.age=age;
}
 
var p1=new Person("Lily",24);
 
alert(Person.prototype.isPrototypeOf(p1)); //true

原型语法

从前面介绍原型对象于实例对象及构造函数的关系中,我们已经知道,给原型对象添加属性和方法只要像这样定义即可:Person.prototype=name。

那么是否每定义一个Person的属性,就要敲一遍Person.prototype呢?答案是否定的,我们也可以像用对象字面量创建对象那样来创建原型对象:

function Person(){
}
 
Person.prototype={
   name:"Tom",
   age:29
}
 
var p1=new Person();
 
alert(p1.name); //Tom
alert(p1.age);  //29

有一点要注意,这个方法相当于重写了整个原型对象,因此切断了它与构造函数的关系,此时Person.prototype.constructor不再指向Person:

function Person(){
}
 
Person.prototype={
   name:"Tom",
   age:29
}
 
var p1=new Person();
 
alert(Person.prototype.constructor==Person); //false
alert(Person.prototype.constructor==Object); //true

因此,如果想要让它重新指向Person,可以显示的进行赋值:

function Person(){
}
 
Person.prototype={
  constructor:Person,
  name:"Tom",
  age:29
}
 
var p1=new Person();
 
alert(Person.prototype.constructor==Person); //true
alert(Person.prototype.constructor==Object); //false
 

总结

最后,我们拿一个例子,再来理理构造函数、原型对象以及实例对象之间的关系:

function Person(name,age){
           this.name=name;
           this.age=age;
       }
 
       Person.prototype.sayName=function(){
           alert(this.name);
       }
 
 
       var p1=new Person("Tom",20);
 
       alert(Person.prototype); //object
       alert(Person.prototype.constructor==Person); //true
       alert(p1.constructor==Person); //true
       alert(p1.__proto__==Person.prototype);  //true 
       alert(p1.__proto__.__proto__==Object.prototype); //true
       alert(p1.__proto__.__proto__.constructor==Object); //true
       alert(Person.constructor==Function); //true
 
       alert(Object.prototype.constructor==Object);
 

顶一下
(1)
100%
踩一下
(0)
0%
------分隔线----------------------------
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片