[关闭]
@hotjp 2016-11-25T14:46:02.000000Z 字数 2114 阅读 1293

prototype

培训


    Javascript诞生于面向对象编程的火爆时期(1994年),Javascript的开发者也受C++和java的影响。所以Javascript成为一种一切皆对象的语言。

    但是,作者认为不需要把一个浏览器端的小型脚本语言写的很复杂,不想写一个带“继承”的语言,但是需要有一个方式把各种对象联系起来。于是,Brendan Eich定义了Javascript的“继承”模式。
    接着就是“类”的抉择,有了“继承”和“类”就是一个标准的面向对象的语言,会增加初学者的学习门槛,并且过于正式,所以,Javascript没有“类”的概念。

没有类,如何定义对象?

    C++和Java语言都使用new命令,生成实例。
    因此,把new命令引入了Javascript,用来从原型对象生成一个实例对象。但是,Javascript没有"类",如何表示原型对象呢?
    C++和Java使用new命令时,都会调用"类"的构造函数(constructor)。于是便做了一个简化的设计,在Javascript语言中,new命令后面跟的不是类,而是构造函数。

所以声明一个对象时我们可这样写:

  1. //内置构造函数声明数组对象
  2. var arr = new Array();
  3. //自定义构造函数声明忍者对象
  4. function Ninjia(name,sex){
  5. this.name = name;
  6. this.weapon = 'knife';
  7. this.sex = sex;
  8. }
  9. var ninjia0 = new Ninjia("mike",'boy');
  10. var ninjia1 = new Ninjia("lily",'girl');

通过关键字new的构造函数中的this指向实例化之后的对象本身。

但是new出来的对象无法共享属性和方法。

比如我们的忍者村批量更换了一种制式武器

  1. //我们给mike装备
  2. ninjia0.weapon='sword';
  3. //检查装备
  4. ninjia0.weapon;
  5. ninjia1.weapon;

修改某个实例对象的通用属性不会影响其他实例对象。
批量的修改相同的属性会浪费很多资源对吧?

    于是,我们的Javascript作者添加了另一个玩意'prototype'

实例对象一旦创建,将自动引用prototype对象的属性和方法。也就是说,实例对象的属性和方法,分成两种,一种是本地的,另一种是引用的。

  1. //重新定义构造函数
  2. function Ninjia(name,sex){
  3. this.name = name;
  4. this.sex = sex;
  5. }
  6. //定义原型
  7. Ninjia.prototype.weapon = 'knife';
  8. //实例对象
  9. var ninjia0 = new Ninjia("mike",'boy');
  10. var ninjia1 = new Ninjia("lily",'girl');
  11. Ninjia.prototype.weapon = 'sword';
  12. //检查装备
  13. ninjia0.weapon;
  14. ninjia1.weapon;

由于所有的实例对象共享同一个prototype对象,那么看起来,prototype对象就好像是实例对象的原型,而实例对象则好像"继承"了prototype对象一样。

Jacascript支持的链式写法‘原型链’是怎么实现的呢?

我们扩展一下刚才那个Ninjia。

  1. //定义一个主函数
  2. function Ninjia(name,sex){
  3. this.name = name;
  4. this.sex = sex;
  5. }
  6. Ninjia.prototype.hello = function(){
  7. return '你好,我是' + this.name
  8. }
  9. //实例化,让ninjia0继承Ninjia函数的原型
  10. var ninjia0 = new Ninjia("mike",'boy');
  11. //调用原型函数
  12. ninjia0.hello();

现在我们的小忍者会说话打招呼了,那么如何继续把链式结构延续下去?

  1. Ninjia.prototype.weapon = 'knife';
  2. Ninjia.prototype.attack = function(){
  3. return this.name + '向在座的各位发射了一把' + this.weapon
  4. }
  5. //会出错
  6. ninjia0.hello().attack();
  7. //正常
  8. ninjia0.attack();

上面的代码并不能形成链式调用,肿么办

  1. //定义一个主函数
  2. function Ninjia(name,sex){
  3. this.name = name;
  4. this.sex = sex;
  5. }
  6. Ninjia.prototype.hello = function(){
  7. return '你好,我是' + this.name
  8. }
  9. Ninjia.prototype.getWeapon = function(){
  10. this.weapon = 'knife';
  11. return this;
  12. }
  13. Ninjia.prototype.attack = function(){
  14. console.log(this.name + '向在座的各位发射了一把' + this.weapon)
  15. return this;
  16. }
  17. var ninjia0 = new Ninjia("mike",'boy');
  18. ninjia0.getWeapon().attack().hello();
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注