解析John Resig Simple JavaScript Inheritance代码

解析 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日

相关文章

  • 国庆节到了,利用JS实现一个生成国庆风头像的小工具 详解实现过程

    下面提供一份详细的攻略,分为以下几个部分。 实现效果 实现一个生成国庆风头像的小工具,将用户输入的头像图片加上国旗和五角星等元素,并生成新的头像图片。 实现过程 准备工作 首先,我们需要准备一些素材,如国旗图片和五角星图片,用于后面合成头像。可以在网络上下载这些图片进行使用。然后,我们需要引入canvas标签,因为我们要使用canvas来进行头像的合成。这里…

    JavaScript 2023年6月11日
    00
  • js实现计时器秒表功能

    如果要使用 JavaScript 实现计时器秒表功能,需要遵循以下步骤: HTML 布局 首先,在 HTML 中创建一个容器用于显示计时器。这可以通过使用<div>元素创建。 <div id="timer">00:00:00</div> CSS 样式 为计时器设置样式,例如对齐方式、字体大小等。以下是一…

    JavaScript 2023年5月27日
    00
  • JS加密插件CryptoJS实现的DES加密示例

    下面我将为您详细讲解使用JS加密插件CryptoJS实现的DES加密示例的攻略。 1. 安装CryptoJS 可以通过以下方式安装CryptoJS: 使用npm安装 打开终端窗口,输入以下命令: npm install crypto-js 使用CDN引入 在HTML文件头部引入CryptoJS库: <script src="https://c…

    JavaScript 2023年5月19日
    00
  • 简单漂亮的js弹窗可自由拖拽且兼容大部分浏览器

    实现一个简单漂亮的 js 弹窗并让其可自由拖拽需要以下步骤: 确定弹窗的外观和属性,如弹窗大小、标题、内容等。可以使用 HTML 和 CSS 来实现。 示例代码: <div id="popup"> <h3 class="title">弹窗标题</h3> <p class=&qu…

    JavaScript 2023年6月11日
    00
  • JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】

    下面就给大家讲解一下“JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】”的完整攻略。 1. 集合的定义和常用运算 1.1 集合的定义 集合(Set)是一种专门存储不重复值的数据结构。它可以存储各种类型的原始值和对象引用。与数组不同的是,集合没有顺序概念,因此不能通过索引访问元素。集合中的数据也没有重复,每个元素的位置都是唯一的。 1.2 集…

    JavaScript 2023年5月28日
    00
  • JS小球抛物线轨迹运动的两种实现方法详解

    JS小球抛物线轨迹运动的两种实现方法详解 抛物线是物理学中比较重要的概念,它被广泛应用于不同领域,例如火箭的轨迹控制,弹道导弹的飞行轨迹等。在Web开发中,利用抛物线动画效果能够使页面更加生动有趣。下面我们将介绍两种不同的实现方法,详细讲解如何实现JS小球抛物线轨迹运动。 方法1:利用定时器 要实现小球的抛物线轨迹运动,我们可以利用数学公式来实现小球的位置计…

    JavaScript 2023年5月28日
    00
  • 常见的原始JS选择器使用方法总结

    常见的原始JS选择器使用方法总结 选择器是 JavaScript 编程中非常重要的一部分。选择器是用于访问和操作文档中的 HTML 元素的方法。 在 JavaScript 中,有多种类型的选择器,其中包含了基础选择器、层级选择器、伪选择器等。本文将总结常见的原始 JavaScript 选择器使用方法。 基础选择器 基础选择器是 JavaScript 中最常用…

    JavaScript 2023年6月10日
    00
  • three.js-结合dat.gui实现界面可视化修改及调试详解

    “three.js-结合dat.gui实现界面可视化修改及调试详解”是一个用于在three.js中实现界面可视化修改及调试的攻略。本攻略主要是基于three.js和dat.gui两个JavaScript库,可以让开发者通过修改dat.gui的界面来实现对three.js中的场景、摄像机、光源等元素的实时修改及调试。 步骤一:引入three.js和dat.gu…

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