美娱国际娱乐:JavaScript基于原型链的继承

标签:公司介绍    日期:2019-01-29 11:34    录入:美娱国际平台注册    浏览:

  

[javascript原型链继承,js原型链继承]JavaScript基于原型链的继承

  

Javascript并不是一门面向对象的语言,没有提供传统的继承方式,但是它提供了一种原型继承的方式,利用自身提供的原型属性来实现继承。

  

  

原型链是JavaScript中继承的主要方法。

  

  

原型链的基本思想是:利用原型让一个引用类型继承另一个引用类型的属性和方法。

  

  

构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

  
  

  

如果让原型对象等于另一个对象的实例,这样原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。

  
  

  

实现原型链的基本模式:  

  
  
  function SuperType() {  this.property = true;  }  SuperType.prototype.getSuperValue = function () {  return this.property;  };  function SubType() {  this.subproperty = false;  }  // 继承SuperType  SubType.prototype = new SuperType();  SubType.prototype.getSubValue = function () {  return this.subproperty;  };  var instance = new SubType();  alert(instance.getSuperValue()); // true 
  
  

SubType继承了SuperType,继承是通过创建SuperType的实例,并将该实例赋给SubType.prototype实现的。实现的本质是重写原型对象,换成一个新类型的实例。这样,原来存在于SuperType的实例中的属性和方法,也存在与SubType.prototype中了。然后给SubType.prototype添加一个方法,这样就继承了SuperType的属性和方法的基础上又添加了一个方法。

  
  

  

上例中的实例关系表示如下:  
  

  

  

  

上面没有使用SubType默认提供的原型,而是给它换了一个新原型;这个新原型就是SuperType的实例。新原型内部还有一个执行SuperType的原型的指针。结果变成了instance指向SubType的原型,SubType的原型又指向SuperType的原型。getValue()方法仍然还在SuperType.prototype中,但prototype则位于SubType.prototype中。这是因为property是一个实例属性,而getSuperValue()则是一个原型方法。既然SubType.prototype现在是SuperType的实例,那么property自然位于该实例中。

  
  

  

注意:instance.constructor现在指向的是SuperType,因为SubType的原型指向了另一个对象——SuperType的原型,这个原型对象的constructor属性指向的是SuperType。

  
  

  

当以读取模式访问一个属性时,首先会在实例中搜索该属性。如果没有找到该属性。则会继续搜索实例的原型。通过原型链实现继承的情况下,搜索过程就得以沿着原型链继续向上。

  
  

  

默认的原型  
  

  

所有引用类型都默认继承了Object,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object的实例。因此默认原型都会包含一个内部指针,指向Object.prototype。这就是为什么自定义类型都会继承toString()、valueOf()等方法的原因。

  
  

  

完整的原型链:  
  

  

  

  

在上面的继承体系中,SubType继承了SuperType,SuperType继承了Object。当调用了instance.toString()时,实际调用的是保存在Object.prototype中的那个方法。

  
  

  

确定实例和原型的关系  
  

  

可以通过两种方式来确定原型和实例之间的关系:  
  

  

使用instanceof操作符  

  
  
  alert(instance instanceof Object);  alert(instance instanceof SuperType);  alert(instance instanceof SubType); 
  
  

由于原型链的关系,上面全部返回true。

  
  

  

使用isPrototypeOf()方法  

  
  
  alert(Object.prototype.isPrototypeOf(instance));  alert(SuperType.prototype.isPrototypeOf(instance));  alert(SubType.prototype.isPrototypeOf(instance)); 
  
  

谨慎定义方法  
  

  

给原型添加方法的代码一定要放在替换原型的语句之后。

  

  
  
  function SuperType() {  this.property = true;  }  SuperType.prototype.getSuperValue = function () {  return this.property;  };  function SubType() {  this.subproperty = false;  }  SuperType.prototype = new SuperType();  // 添加方法  SubType.prototype.getSubValue = function () {  return this.subproperty;  };  // 覆盖超类中的方法  SubType.prototype.getSuperValue = function () {  return false;  };  var instance = new SubType();  alert(instance.getSuperValue()); // false 
  
  

上面的例子必须注意的是,在用SuperType的实例替换原型之后,再定义那两个方法。

  
  

  

另外,在通过原型链实现继承时,不能使用该对象字面量创建原型方法。因为这样做会重写原型链:  

  
  
  function SuperType() {  this.property = true;  }  SuperType.prototype.getSuperValue = function () {  return this.property;  };  function SubType() {  this.subproperty = false;  }  // 继承SuperType  SubType.prototype = new SuperType();  // 使用字面量添加新方法,导致上一行代码无效  SubType.prototype = {  getSubValue :function() {  return this.subproperty;  },  someOtherMethod: function () {  return false;  }  };  var instance = new SubType();  alert(instance.getSuperValue()); // error 
  
  

上例将SuperType的实例赋值给原型,紧接着又将原美娱国际娱乐型替换成一个对象字面量而导致的问题。现在的原型包含一个Object的实例,而非SuperType的实例,SubType和SuperType之间已经没有关系了。

  
  

  

原型链的问题  
  

  

前面已经介绍过,包含引用类型值得原型属性会被所有实例共享;而这也正是为什么要在构造函数中,而不是在原型对象中定义属性的原因。

  

  
  
  function SuperType() {  this.colors = ["red", "blue", "green"];  }  function SubType() {  }  SubType.prototype = new SuperType();  var instance1 = new SubType();  instance1.colors.push("black");  alert(instance1.colors); // "red", "blue", "green", "black"  var instance2 = new SubType();  alert(instance2.colors); // "red", "blue", "green", "black" 
  
  

在上面的例子中,SuperType构造函数中定义了一个colors属性,该属性包含一个数组,SuperType的每个实例都会有各自包含自己数组的colors属性。当SubType通过原型链继承了SuperType之后,SubType.prototype就变成了SuperType的一个实例,所以它也拥有了一个它自己的colors属性。但是,SubType的所有实例都会共享这一个colors属性。

  
  

  

另一问题是,没有办法在不影响所有对象实例的情况下,给超类的构造函数传递参数。

  
  

  

  

★★★小编:美娱国际 整理文章,欢迎大家转载 ★★★
上一篇:JS正则表达式大全(整理详细且实用)
下一篇:没有了
相关文章阅读