首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > JavaScript >

容易实现JavaScript继承

2012-11-23 
简单实现JavaScript继承? ? 看John Resig 的JavaScript实现继承的文章,对大神的实现代码拿来跟大家一起读

简单实现JavaScript继承

? ? 看John Resig 的JavaScript实现继承的文章,对大神的实现代码拿来跟大家一起读下源码,因为英语太菜就不翻译了,直接根据源码来分析了。原文地址:http://ejohn.org/blog/simple-javascript-inheritance/

?

首先来看本继承所要达到的效果,知道效果来看源码更能容易理解。(先要知其然,然后知其所以然)。

?

var Person = Class.extend({  init: function(isDancing){    this.dancing = isDancing;  },  dance: function(){    return this.dancing;  }});var Ninja = Person.extend({  init: function(){    this._super( false );  },  dance: function(){    // Call the inherited version of dance()    return this._super();  },  swingSword: function(){    return true;  }});var p = new Person(true);p.dance(); // => truevar n = new Ninja();n.dance(); // => falsen.swingSword(); // => true

?

?继承需要做到以下几点:

1.定义一个简单的结构,有一个初始化方法(生成对象时调用的函数,类似Java的构造方法)

2.子类的生成,必须要继承一个父类。

3.所有类的原型都是派生自Class.(就像Java类最终都派生自Object一样)

4.在子类中提供一种方法能访问到父类中被覆盖的方法。通过this._super().(如:在类Ninja的init方法中调用this._super()就是调用父类Person的init方法)

?

下面来看看代码是怎么实现继承的:

/* Simple JavaScript Inheritance * By John Resig http://ejohn.org/ * MIT Licensed. */// Inspired by base2 and Prototype(function(){  var initializing = false,       fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;      //fnTest是一正则表达式,匹配函数里是否有调_super方法。  // The base Class implementation (does nothing)  this.Class = function(){}; // 定义一个全局变量Class类/函数。    // Create a new Class that inherits from this class  Class.extend = function(prop) {    /** 保存当前对象的原型(也就父类的原型),     *  Class.extend()调用时this是Class,Person.extend调用时this是Person     *  js里一切都是对象,Class函数也是对象,所以this这里是一个函数。     */    var _super = this.prototype;            // Instantiate a base class (but only create the instance,    // don't run the init constructor)    initializing = true;    /**父类的实例作为子类的原型(典型的原型继承)     * 但是这里实例化跟普通的生成对象不一样,这里不调用父类的init方法。     * 类就是一模板,所以子类在以父类对象为原型的时候,不应调用初始化方法,仅仅是生成一个模板     * 这边就是用initializing变量来标识实例父类是否是赋值给子类的原型。     * 用闭包来隐藏了initializing 作为全局变量的污染     */    var prototype = new this();    initializing = false;        // Copy the properties over onto the new prototype    for (var name in prop) {      // Check if we're overwriting an existing function      /** 当子类新方法父类中有同名函数,而且子类中调用了父类方法(函数中有_super的调用)       *  这里使用了代理模式,在调用函数前先将this._super用tmp保存起来(也可能没有_super方法)       *  在将this._super 赋值为父类中同名函数。调用结束再将原来的this._super还原       */      prototype[name] = typeof prop[name] == "function" &&         typeof _super[name] == "function" && fnTest.test(prop[name]) ?        (function(name, fn){          return function() {            var tmp = this._super;                        // Add a new ._super() method that is the same method            // but on the super-class            this._super = _super[name];                        // The method only need to be bound temporarily, so we            // remove it when we're done executing            var ret = fn.apply(this, arguments);                    this._super = tmp;                        return ret;          };        })(name, prop[name]) :        prop[name];    }        // The dummy class constructor    function Class() {      // All construction is actually done in the init method      /**如果定义了初始化方法init,则调用init初始化       * 注意:这里的this不是Class或者Person等类/函数对象       * 而是实例化后的对象var p = new Person() 这里的this 是p       */      if ( !initializing && this.init )        this.init.apply(this, arguments);    }        // Populate our constructed prototype object    Class.prototype = prototype; //子类原型复制        // Enforce the constructor to be what we expect    Class.prototype.constructor = Class; //子类构造函数定义    // And make this class extendable    //定义类的继承方法,保证每个新类也都有extend.    //这里也可写成 Class.extend = this.extend;    Class.extend = arguments.callee;        return Class;  };})();

?看这些代码最重要的一点是时刻要清楚this是哪个对象。

?

好了,上面就是文章的全部了,希望对大家有帮助,有疑问请留言,有什么解释不对和不清楚的地方也望大家指正。

?

热点排行