821次阅读
原型链初步

首先,我们先来总结一下javascript定义对象的几种方法:

html:

<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>原型链初步</title>
</head>
<body>
  <script src="script.js"></script>
</body>	
check the result

javascript:

// 第一种方法
var obj1 = {
  name: 'wanmingniu',
  sex: 'male',
  show: function() {
    document.write('I am ' + this.name + ', ' + this.sex + '<br/>');
  }
}
obj1.show();
// 第二种方法
function Person(name, sex) {
  this.name = name;
  this.sex = sex;
  this.show = function() {
    document.write('I am ' + this.name + ', ' + this.sex + '<br/>');
  }
}
var xinxin = new Person('xinxin', 'male');
var wanmingniu = new Person('wanmingniu', 'male');
xinxin.show();
wanmingniu.show();
// 第三种方法
var obj2 = new Object;
obj2.name = 'wanmingniu';
obj2.sex = 'male';
obj2.show = function() {
  document.write('I am ' + this.name + ', ' + this.sex + '<br/>');
}
obj2.show();	

在这里,我们总结了三种方法。第一种方法,也是最简单的一种,一种类似json格式的定义,就能产生一个对象。第二种方法其实我们是见过的,通过一个函数来创建对象。第三种方法是先new一个Object,然后再给它赋值,也是一种方法。其实在javascript中,对象就是Object,也就是说,第三种方法是最原始的,但是并不常用。第一种方法和第二种方法是最常用的,因为它们用法简单。而它们两者的区别是,第一种方法一次只能定义一个对象,第二种方法相当于定义了一个对象的模板,通过new我们可以定义很多结构相同的对象。在实际编程中大家要尽量使用第一种或者第二种方法。

那么我们所说的prototype是什么东西呢?就是我们在通过第二种方法来定义对象时需要注意的一个东西。我们来看一个例子:

html:

<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>原型链初步</title>
</head>
<body>
  <script src="script.js"></script>
</body>	
check the result

javascript:

var Person = function(name, sex) {
  this.name = name;
  this.sex = sex;
  this.hello = function() {
    document.write("hello " + this.name + "<br/>");
  }
  this.tellAge = function() {
    document.write("i am " + this.age + "<br/>");
  }
}
Person.life = 100;
Person.tellLife = function() {
  document.write("I can live " + Person.life + " years<br/>");
}
Person.prototype.age = 0;
Person.prototype.grow = function() {
  this.age++;
}
var xinxin = new Person('xinxin', 'male');
xinxin.hello();
//xinxin.tellLife(); error,xinxin has no tellLife function
Person.tellLife();
xinxin.tellAge();
xinxin.grow();
xinxin.tellAge();
var wanmingniu = new Person('wanmingniu', 'male');
wanmingniu.hello();
wanmingniu.tellAge();	

在这个例子中,我们有三种方式定义属性或方法,第一种是最熟悉的通过this来定义,第二种是通过Person来定义,但是注意,通过new Person出来的对象是没有这些属性和方法的,第三种是我们的重点,通过Person.prototype来定义,它的使用方式和第一种是一样的。

关于prototype,有这么一句话:做为一个对象,当你访问其中的一个成员或方法的时候,如果这个对象中没有这个方法或成员,那么Javascript引擎将会访问这个对象的prototype成员所指向的另外的一个对象,并在那个对象中查找指定的方法或成员,如果不能找到,那就会继续通过那个对象的prototype成员指向的对象进行递归查找,直到这个链表结束。

这就是为什么我们new出来的对象能够访问prototype上定义的属性。而且每个对象都有prototype这个属性,这个属性本身又是一个对象,它也有自己的prototype,这样就形成一个链,这也就是原型链的意义。

既然prototype和this这两种方法都能定义属性和方法,那他们就没有区别吗?当然有。使用prototype定义的属性和方法所产生的内存消耗要小很多,它在内存中只有一份,都有的对象只保留它的引用,而this定义的属性和方法,每个对象都会保留一份,所以消耗内存较大。

这么说可能大家不理解,举个例子说明一下,比如你定义了一个Person,里面有一个方法叫getAge,然后new了100个Person,如果是用this定义的getAge,那么这100个Person,每一个都要在内存中生成这个getAge,但是如果是用prototype定义的,那么内存中只有一份getAge,100个Person会有100个prototype,但是这些prototype都指向一个getAge。

再举个生活中的例子,比如我们搞一个调查问卷。this方式就好像是我们发纸质版的,发100份,就得打印100份纸质版。而prototype方式就好像是网上调查问卷,我只要给100个人网址就好,他们上来都能访问调查问卷,而这个调查问卷在服务器只有一份。

说了这么多,prototype比this好很多,那为什么不直接用prototype呢?this的存在岂不是没有意义了?非也非也!prototype也有不如this的时候,请看例子:

html:

<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>原型链初步</title>
</head>
<body>
  <script src="script.js"></script>
</body>	
check the result

javascript:

var Person = function(name, sex) {
  var age = 0;
  this.hello = function() {
    document.write("hello, i am " + name + ", i am " + age + " years old<br/>");
  }
  this.innergrow = function() {
    age++;
  }
}
Person.prototype.grow = function() {
  //age++;   Error : age is not defined
  this.age++;
}
var xinxin = new Person('xinxin', 'male');
xinxin.hello();
xinxin.grow();
xinxin.hello();
xinxin.innergrow();
xinxin.hello();	

在这个例子中,我们的age变量变成了function中的一个var,这时候我们在prototype中就无法去操作这个age了,只有通过this定义的方法才能操作。这里的var变量可以说是私有变量,只有Person这个function里面的元素能够操作,外面的元素无法操作,prototype也不行。

好了,这节详细分析了prototype的一些基础知识点,要成为javascript高手,prototype一定要搞定。

如果您觉得此教程不错,想支持一下,您可以通过支付宝扫码给我们一点,不要超过100元哦!
评论请先登录