解析John Resig Simple JavaScript Inheritance代码

yizhihongxing

解析 John Resig 在 Simple JavaScript Inheritance 代码的思路可以分为以下几个部分:

简介

这是 John Resig 在 2008 年发布的一个 JavaScript 类继承的库,用来实现类的继承。

源代码及解析

下面我们来逐行分析源代码实现:

首先,定义了一个匿名函数,并将其赋值给 Class 变量。

var Class = (function() {
    // ...
})();

这里利用了函数声明的特性,定义了一个 IIFE,返回一个对象。

1. Fn.prototype.extend

接下来就是对象的方法,其中,最重要的就是 extend 方法,这个方法有两个参数,第一个是一个对象,表示新的类的原型对象,第二个是一个对象,表示新的类的静态属性和方法。

// 添加方法和静态属性
Function.prototype.extend = function(prop) {
  var _super = this.prototype;

  function F() {};
  F.prototype = _super;

  var prototype = new F();

  for(var name in prop) {
    if(typeof prop[name] === "function" &&
       typeof _super[name] === "function" &&
       fnTest.test(prop[name])) {

      prototype[name] = (function(name, fn) {
        return function() {
          var tmp = this._super;
          this._super = _super[name];
          var ret = fn.apply(this, arguments);
          this._super = tmp;
          return ret;
        };
      })(name, prop[name]);

    } else {
      prototype[name] = prop[name];
    }
  }

  function Class() {
    if (this.init) {
      this.init.apply(this, arguments);
    }
  }

  Class.prototype = prototype;
  Class.constructor = Class;
  Class.extend = arguments.callee;

  return Class;
};

在这个方法的内部中,核心部分就是以下这段代码:

var _super = this.prototype;
function F() {};
F.prototype = _super;
var prototype = new F();

这里定义了一个代理函数 F,这个函数的作用是一个中间代理层,可以用来保存原型对象 _super 的引用,从而避免对父类对象的修改。

接下来,将代理函数 F 的原型属性指向当前对象的原型属性,这样代理函数 F 就成为了一个新的对象,这个新的对象有原型属性继承自当前对象。

接着定义一个 for 循环,遍历新的类的原型对象上的属性,将方法保存至新的原型对象上。

其中,最重要的部分在于这样的一个条件判断:

typeof prop[name] === "function" &&
typeof _super[name] === "function" &&
fnTest.test(prop[name])

如果当前对象和父类对象上都拥有相同名称的方法,并且这个方法符合正则表达式 fnTest 规定的格式,则使用 closure 的思想实现闭包函数。

这里 closure 函数在 arguments 对象中做了一个小的修改,简单来说就是是利用 arguments 对象保存 this 的引用,并在函数返回的时候计算出方法的返回值。

对于非方法的属性,直接将属性保存到新的原型对象上。

最后,定义并返回一个改写过的函数 Class,用来定义新的类。

在 Class 中,还增加了一个新的方法 init,用来在对象创建时初始化对象的属性。

2. _super 属性

另外一个重要的功能就是函数中的 _super 属性,这个属性用来在子类中调用父类中相同名称的方法。

var _super = this._super || function() {};

这个属性也是利用了 closure 函数的思想,每一次将 _super 模拟为当前方法的上一个版本,避免对父类对象进行操作。

3. 对象的创建

Class 这个对象是通过原型属性来定义的,因此可以用 new 关键字来创建新的对象。在对象创建的时候,可以传递参数给 init 方法初始化对象的属性。

示例说明

示例 1:

// 父类
var Person = Class.extend({
  init: function(name, age) {
    this.name = name;
    this.age = age;
  },
  sayName: function() {
    console.log("name: " + this.name);
  },
  sayAge: function() {
    console.log("age: " + this.age);
  }
});

// 子类
var Student = Person.extend({
  init: function(name, age, stuNo) {
    this._super(name, age);
    this.stuNo = stuNo;
  },
  sayStuNo: function() {
    console.log("student number: " + this.stuNo);
  }
});

// 创建父类对象
var p = new Person("Tom", 20);
console.log(p); // Person {name: "Tom", age: 20}

// 创建子类对象
var s = new Student("Jhon", 18, 20210001);
console.log(s); // Student {name: "Jhon", age: 18, stuNo: 20210001}

s.sayName(); // name: Jhon
s.sayAge(); // age: 18
s.sayStuNo(); // student number: 20210001

以上是一个简单 class 继承的示例,通过相同的名称的方法实现了类的继承。

示例 2:

var Animal = Class.extend({
  makeSound: function() {
    console.log("Animal sound...");
  }
});

var Cat = Animal.extend({
  makeSound: function() {
    console.log("Mew...");
    this._super();
  }
});

var cat = new Cat();
cat.makeSound(); // Mew... \n Animal sound...

这是一个更加直观的 _super 方法的使用示例。通过先在子类中重写方法,再显示调用父类的方法实现了在子类方法中调用父类方法的使用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:解析John Resig Simple JavaScript Inheritance代码 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • JavaScript RegExp 对象

    JavaScript中的RegExp对象是用于处理正则表达式的内置对象。正则表达式是一种用于匹配字符串模式的工具,可以用于搜索、替换和验证字符串。下面是关于RegExp对象的完整攻略,包括语法、属性、方法和示例。 RegExp对象的语法 JavaScript的RegExp有两种创建方式: 字面方式:使用正则表达式字面量创建RegExp对象,语法如下: /pa…

    JavaScript 2023年5月11日
    00
  • JS中map和parseInt的用法详解

    下面为大家详细讲解“JS中map和parseInt的用法详解”攻略: JS中map和parseInt的用法详解 map()方法 map()方法是JS中数组原型的一种方法,可用于对数组中每个元素进行操作,返回操作后的新数组,实现方式如下: const arr = [1, 2, 3]; const newArr = arr.map((item, index) =…

    JavaScript 2023年5月27日
    00
  • Javascript MVC框架Backbone.js详解

    Javascript MVC框架Backbone.js是一个轻量级的框架,它可以帮助我们快速构建单页应用程序(SPA)。它提供了一系列功能强大且灵活的工具,使得我们可以轻松管理前端应用程序中的模型(model)、视图(view)和集合(collection)。在这篇文章中,我们将详细讲解Backbone.js的完整攻略,并附带两个例子说明它的具体应用。 安装…

    JavaScript 2023年5月27日
    00
  • js中时间格式化的几种方法

    讲解js中时间格式化的几种方法的攻略如下: 一、JavaScript中的时间表示 在JavaScript中,时间是用毫秒数来表示的。毫秒数是从1970年1月1日00:00:00 UTC开始计算的,也被称为1970年纪元。这个时间点被称为UNIX时间。UNIX时间是一个标准时间,所有的计算机系统都使用它来存储时间数据。 二、格式化时间的方法 在JavaScri…

    JavaScript 2023年5月27日
    00
  • 详解用函数式编程对JavaScript进行断舍离

    详解用函数式编程对JavaScript进行断舍离 函数式编程作为一种编程范式,正变得越来越受JavaScript开发者欢迎。它与传统的面向对象编程就像是石头和剪刀一样。让我们来详细了解一下,如何用函数式编程对JavaScript进行“断舍离”。 什么是函数式编程 函数式编程是一种编程模式,它的核心思想是将计算过程视为数学运算,每个函数都是输入一些参数,返回一…

    JavaScript 2023年6月10日
    00
  • JS中实现简单Formatter函数示例代码

    下面就JS中实现简单Formatter函数示例代码的完整攻略进行讲解。 1. 简单Formatter函数实现 Formatter函数的作用是将一个字符串中的指定位置的字符换成其他字符,函数的参数包含原字符串,需要替换的字符的位置,原来的字符和替换的字符。下面是一个示例代码: function formatter(str, idx, oldChar, newC…

    JavaScript 2023年5月28日
    00
  • Javascript实现表单检验

    下面是Javascript实现表单检验的完整攻略。 什么是表单检验 表单检验是指在前端页面中对用户输入的数据进行验证的一种技术手段。它可以用来保证提交给后端的数据的正确性和完整性,从而提高数据的质量和可靠性。 Javascript实现表单检验的步骤 下面是Javascript实现表单检验的一般步骤: 获取表单元素及其值 根据指定的规则进行数据验证 根据验证结…

    JavaScript 2023年6月10日
    00
  • Javascript Date constructor 属性

    以下是关于JavaScript Date对象的constructor属性的完整攻略。 JavaScript Date对象的constructor属性 JavaScript Date对象的constructor属性返回对创建该对象的构造函数的引用。该属性可用于检查对象是否为Date类型。 下面是使用Date对象的constructor属性的示例: var da…

    JavaScript 2023年5月11日
    00
合作推广
合作推广
分享本页
返回顶部