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

相关文章

  • javascript使用中为什么10..toString()正常而10.toString()出错呢

    这是一个有趣的问题,事实上,10..toString() 和 10.toString() 演示的两种方法是不同的。 在 JavaScript 中,要调用对象的方法,我们通常使用点符号将对象与方法名称连接,例如 object.method()。然而,数字直接量(例如 10)之后的点符号(”.”) 会被 JavaScript 解释为带有小数的数字,因此解释器会尝…

    JavaScript 2023年5月18日
    00
  • Javascript中的var_dump函数实现代码

    对于Javascript而言,并没有var_dump这个函数。通常情况下,我们可以使用console.log来输出变量的值和类型。 如果想要模拟PHP的var_dump函数,可以参照以下代码: function var_dump(obj) { var result = ”; for (var i in obj) { result += i + ‘: ‘ +…

    JavaScript 2023年6月11日
    00
  • HTML+JS实现爱心动画效果的源码分享

    下面我将详细讲解HTML+JS实现爱心动画效果的源码分享的完整攻略。 内容概述 本攻略将介绍如何使用HTML和JS实现一个基本的爱心动画,包括动画创建和动画运行两个阶段。具体内容包括: 动画的基本原理 动画的创建过程 动画的运行过程 源码分享 动画的基本原理 实现爱心动画的基本思路是:通过JavaScript实现爱心的绘制并处理动画,然后将动画效果通过CSS…

    JavaScript 2023年6月10日
    00
  • JS操作xml对象转换为Json对象示例

    下面是JS操作XML对象转换为JSON对象示例的完整攻略。 什么是XML对象和JSON对象? XML(Extensible Markup Language) 是一种文本格式的标记语言,用于存储和传输数据。XML 文件可作为 Web 文档来读取和呈现。 JSON(JavaScript Object Notation) 是一种轻量级的数据格式,它是一种文本格式的…

    JavaScript 2023年5月27日
    00
  • Nuxt项目支持eslint+pritter+typescript的实现

    首先,需要明确一下Nuxt.js是一个基于Vue.js的框架,它提供了一些有用的工具和约定,使得我们可以快速地进行服务端渲染的开发,因此Nuxt.js的项目开发需要支持ESLint+Prettier+TypeScript的实现。下面给出如何在Nuxt项目中实现支持这三个工具的流程: 第一步:初始化Nuxt项目 npx create-nuxt-app my-p…

    JavaScript 2023年6月11日
    00
  • JS实现添加缓动画的方法

    下面是JS实现添加缓动动画的方法的完整攻略: 什么是缓动动画? 缓动动画指的是在动画过程中,物体的速度从快到慢,或者从慢到快,而不是始终以相同的速度运动。缓动动画通常可以提高用户体验,使动画看起来更平滑、自然。 实现缓动动画的方法 使用JS实现缓动动画可以有多种方法,下面介绍其中两种。 方法一:简单的缓动动画实现 简单的缓动动画实现方法比较容易理解,下面的代…

    JavaScript 2023年6月10日
    00
  • JavaScript实现文件下载并重命名代码实例

    接下来我会详细讲解如何使用JavaScript实现文件下载并重命名的完整攻略。 1. 使用XMLHttpRequest下载文件 使用XMLHttpRequest可以更加灵活地控制文件下载过程,并且可以同时下载多个文件。 function downloadFile(url, filename) { return new Promise((resolve, re…

    JavaScript 2023年5月27日
    00
  • Javascript实现元素选择器功能

    实现元素选择器的功能,需要使用JavaScript中的DOM操作方法。以下是实现此功能的攻略: 1. getElementById()方法 使用 getElementById() 方法可以通过指定元素的 ID 获取该元素的引用。 例如: var element = document.getElementById("myId"); // 获…

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