`

JavaScript 模拟类机制及私有变量

    博客分类:
  • js
阅读更多
在使用一些 Java script 框架时,或许会看到类似的代码


  var MyClass = new Class({
    initialize: function(param, ...) {
      this.param = param;
      ...
    },
    func1: function(...) {
      ...
    }
  });

  var myObj = new MyClass(param);
  myObj.func1(...);


  这是一种典型的面向对象的类机制应用,与原生的 Javascript 类机制相比,显得更为清晰和自然。并且,在此基础上,实现类的继承也较为方便。那么,这是如何实现的呢?
  众所周知,在 Javascript 中,将一个函数作为构造器,可以创建出一个对象,上面的代码可以简单的写成:


  function MyClass(param) {
    this.param = param;
    this.func1 = function(..) {
      ...
    };
  }

  var myObj = new MyClass(param);
  myObj.func1();


  其实还是蛮简单的,也不难理解。不过如果要构建一套大型的 Javascript 类库,可能就会比较混乱,从一堆代码中,要找出哪些是类,哪些是函数,哪些是类方法,哪些是类属性,是一件痛苦的事。
  当然,这里并不是要比较它们的优劣,只是好奇 new Class 的实现方式而已。
  在上面的代码中,使用 new MyClass() 这样的语句,意味着 MyClass 必须是一个函数,同时也就意味着 new Class 需要返回一个函数对象,从字面的意思上可以看出,函数 initialize 是当做构造函数来使用的,所以,new Class 返回的函数中,必须使用 initialize 来对对象进行初始化。基于这样的分析,可以得出以下代码:


  function Class(argu) {
    return function() {
      var init = argu['initialize'] || function() {}; //如果没有构造函数 initialize,使用一个空函数作为默认构造函数
      for(var p in argu) {
        this[p] = argu[p];
      }
      init.apply(this, arguments); //使用当前函数的 this 来代替函数 initialize 原有的 this
    }
  }


  上面的代码并不够严谨,但用来说明问题 已经足够了。需要注意 init.apply(this, arguments) 这一句,这里有几个变量的指代,一个是 this,原本 initialize 中默认的 this,现在已被替代为返回的这个匿名函数的 this,而这个匿名函数,是通过 new Class 新建的自定义类的构造器。另外一个是 arguments,它指代的是匿名函数的参数,也就是上面的 new MyClass(param) 中的 param。
  this 的转换有些让人头晕,那么有没有更为简单的方法呢?请看下面的代码:


  function Class(argu) {
    var obj = argu['initialize'] || function() {};
    for(var p in argu) {
      obj.prototype[p] = argu[p]; //注意,这里用的是 prototype
    }
    return obj; // 其實还是返回一個函數
  }


  呵呵,感觉直白了许多。
  这就完成了一个简单的类机制的构建。通过这种机制,可以创建类的构造函数、方法及属性,但这些显然都是公有的,那么,如何实现私有变量及方法呢?
  我们知道,Javascript 类的私有变量可以通过闭包的机制来完成。但使用 new Class({...}) 的方式转换后,显然很难形成有效的闭包。如何绕过这个问题呢?
  Javascript 提供了两个方法:eval() 及函数对象的 toString() 方法,前者较为常见,而后者,可用于获取函数的具体代码。通过这两个方法,可以简单的模拟类的私有变量:


  function Class(argu) {
    var _ = argu['private'] || {};
    eval('var obj = ' + (argu['initialize'] || function() {}).toString());
    for(var p in argu) {
      if(p == 'initialize' || p == 'private')
        continue;
      if(typeof argu[p] == 'function')
        eval('obj.prototype[p] = ' + argu[p].toString());
      else
        obj.prototype[p] = argu[p];
    }
    return obj;
  }


  通过函数对象的 toString() 方法提取出函数的代码,并使用 eval 方法执行这些代码,这样就可以构造出一个有效的闭包范围,从而实现私有机制。我们可以如下应用:


  var Person = new Class({
    private: {
      height: 160,
      weight: 50
    },
    initialize: function(name, height, weight) {
      this.name = name;
      _.height = height || _.height;
      _.weight = weight || _.weight;
    },
    show: function() {
      alert('Name:' + this.name + '\nheight:' + _.height + '\nweight:' + _.weight);
    }
  });

  var my = new Person("Zh");
  my.show();


  看起来不不错,不过在实际应用中,其实并没有太大的用途。主要是效率上,相比通常的实现方式,大概需要多花四倍的时间。在大型类库的构建上,这是不可容忍的,而小型的应用中,实现下面的代码更为简单直接:


  function MyClass(param) {
    var privateVar = ...;
    this.param = param;

    this.func = function() {
      alert(privateVar);
    };
  }
分享到:
评论

相关推荐

    JavaScript 模拟类机制及私有变量的方法及思路

    JavaScript模拟类机制及私有变量方法思路 在JavaScript中,原生并不支持传统的类继承和私有成员,而开发中有时需要类似的功能。于是,开发者们就发明了各种方法来模拟类机制,以及实现类似私有变量的功能。本文将...

    js类中的公有变量和私有变量

    在JavaScript中,通常使用构造函数来模拟类的行为。构造函数内部定义的变量可以分为两种类型:公有变量(Public Variable)和私有变量(Private Variable)。 - **公有变量**:可以在构造函数外部被访问和修改的...

    【JavaScript源代码】详解ES6实现类的私有变量的几种写法.docx

    ### JavaScript ES6 实现类的私有变量方法详解 #### 一、背景介绍 随着ECMAScript 2015(通常称为ES6)的引入,JavaScript语言经历了一次重大更新,提供了许多新特性和改进,其中包括对面向对象编程的支持增强。...

    JavaScript之私有属性,私有函数,函数实现对外不可见

    在JavaScript中,虽然没有像Java或C++那样的内置关键字来直接声明私有变量或方法,但我们可以通过一些技巧来模拟这种行为。 1. **闭包**:这是JavaScript中实现私有变量和私有函数最常见的方法。闭包是一种特殊的...

    JavaScript私有变量实例详解

    在JavaScript中,由于没有真正的私有变量(不像Java或C#等语言),我们可以利用闭包特性来模拟私有变量。闭包可以让内部函数访问其外部函数的变量,即使外部函数已经执行完毕,闭包仍然能保留对外部变量的引用。 ...

    JavaScript面向对象之私有静态变量实例分析

    了解并熟练掌握JavaScript中的面向对象和私有变量的概念,能够帮助开发者编写更加安全、模块化的代码,提高软件的可维护性和可扩展性。同时,这也涉及到JavaScript的其他高级特性,如闭包、作用域以及函数作为一等...

    ProtectJSJavaScript中真正私有的属性和方法

    综上所述,ProtectJS库通过JavaScript的闭包机制实现了模拟私有属性和方法的功能,为开发者提供了更安全、更模块化的代码组织方式。它在浏览器和Node.js环境下均适用,使得私有化编程在JavaScript世界中成为可能。...

    javascript使用闭包模拟对象的私有属性和方法

    需要注意的是,虽然闭包可以保护变量不被外部直接访问,但并非所有的 JavaScript 开发者都推荐使用闭包来模拟私有变量和方法。这是因为闭包会阻止变量所占用的内存被垃圾回收,这可能会导致内存泄漏,尤其是在闭包...

    如何在JavaScript对象中嵌入私有成员.doc

    - **执行效率**:访问闭包中的私有变量可能比直接访问对象属性稍慢,因为需要额外的函数调用和作用域查找。 在实际应用中,这些影响通常是微不足道的,除非在性能至关重要的场景下。对于大多数JavaScript应用程序来...

    JavaScript中的私有成员

    JavaScript中的私有成员是通过巧妙地利用闭包和作用域规则来实现的,因为JavaScript本身并不直接支持传统的类和私有变量。以下我们将详细探讨如何创建和使用私有成员。 首先,JavaScript对象是由一系列键值对组成的...

    JavaScript 面向对象的 私有成员和公开成员

    在给定的代码示例中,aa是一个私有变量,fun1和fun2是私有方法,它们都只能在类的内部访问。 另一方面,公开成员是指通过this关键字声明的变量和方法,它们可以被外部访问。例如,在类的外部,bb是一个公开变量,...

    基于闭包的JavaScript面向对象编程框架.pdf

    在JavaScript中,闭包可以用来模拟类的机制,并实现基于类的面向对象编程。 在本文中,我们首先介绍了闭包的概念和特征,然后介绍了基于闭包的JavaScript面向对象编程框架的设计和实现。该框架包括三个主要部分:类...

    Javascript类定义语法,私有成员、受保护成员、静态成员等介绍

    现在,我们通过一个具体的例子来说明如何在JavaScript中使用JSON对象来模拟类定义语法,并实现私有成员、受保护成员和静态成员。 示例代码中,首先定义了一个自定义函数Class,该函数接收两个参数:第一个是类名字...

    深入了解JavaScript 私有化

    在JavaScript中,虽然没有内置的私有变量或方法,但可以通过一些技巧来模拟实现。本文将深入探讨如何在JavaScript中实现私有化。 首先,我们可以利用闭包来实现私有变量。闭包是一种特殊的作用域,它可以访问并操作...

    JavaScript面向对象的支持

    闭包允许函数访问和修改外部环境的状态,为实现私有变量和模拟类的封装提供了可能。 6. **原型扩展与自定义**: 通过`Object.create()`方法或者直接修改`__proto__`属性,可以为对象添加新的方法或属性,实现对...

    JAVASCRIPT-使用面向对象的技术创建高级 Web 应用程序

    JavaScript中的原型机制是实现继承的基础。每个JavaScript对象都有一个内部链接指向另一个对象——它的原型。当尝试访问一个对象的属性时,如果找不到该属性,JavaScript引擎会沿着原型链查找。 **静态属性和方法**...

    Javascript 面向对象的JavaScript进阶

    虽然JavaScript没有提供严格的封装机制,但我们可以通过设置私有变量和公共方法来实现类似的功能。通常,开发者会使用闭包或者ES6的类来模拟封装。 **示例代码:** ```javascript function Person(name, age) { ...

    The Principles of Object Oriented.JavaScript

    - **构造函数**:虽然JavaScript不支持类的概念,但可以通过构造函数来模拟类的行为,创建具有相同属性和方法的对象实例。 - **闭包**:JavaScript中的闭包特性使得私有成员的实现成为可能,通过闭包可以实现封装,...

Global site tag (gtag.js) - Google Analytics