zoukankan      html  css  js  c++  java
  • JavaScript中为什么使用立即执行函数来封装模块?

    最近在学习JavaScript基础,在学习到面向对象编程时,学习到在JavaScript中实现模块化的方法,其中一个重要的点是如何封装私有变量。

    实现封装私有变量的方法主要是:

    使用构造函数

    function StringBuilder() {

    var buffer = [];

    this.add = function (str) {

      buffer.push(str);

    };

    this.toString = function () {

       return buffer.join('');

    };

    }

    // 上面这种做法有个缺点,就是每生成一个新的实例,其中的方法就会生成一个新的实例,造成内存浪费,因此做如下改进

    function StringBuilder() {

    this._buffer = [];

    }

    StringBuilder.prototype = {

    constructor: StringBuilder,

    add: function (str) {

    this._buffer.push(str);

    },

    toString: function () {

    return this._buffer.join('');

    }

    };

    // 此时所有实例会共享这两个方法,不会重复生成

    // 但是问题又来了,我们封装的私有变量变得不私有了,在外部可以直接修改_buffer,如

    var sb = new StringBuilder();

    sb._buffer = 'hello, sb';

    使用立即执行函数

    var module = (function() {

    function StringBuilder() {

    this._buffer = [];

    }

    StringBuilder.prototype = {

    constructor: StringBuilder,

    add: function (str) {

    this._buffer.push(str);

    },

    toString: function () {

    return this._buffer.join('');

    }

    };

    function createStringBuilder() {

    var _sb = new StringBuilder();

    return {

    add: StringBuilder.prototype.add.bind(_sb),

    toString: StringBuilder.prototype.toString.bind(_sb)

    };

    }

    return {

    createStringBuilder: createStringBuilder

    };

    })();

    console.log(module); // { createStringBuilder: [Function: createStringBuilder] }

    var sb = module.createStringBuilder();

    sb.add('hello');

    sb.add('爱编程的小菜鸟');

    console.log(sb.toString()); // hello爱编程的小菜鸟

    在立即执行函数中,重点在于createStringBuilder这个函数,这个函数实现了内外对接的接口,对内保护了StringBuilder的私有成员,对外又能提供需要访问的接口,实现了真正的私有变量封装。下面我们用一个简单的例子对上面的三种方式进行对比:

    // 构造函数,var1无法被外界修改,但是每生成一个实例,fn都会被拷贝

    function Class1() {

    var var1 = 10;

    this.fn = function() {

    console.log(var1);

    var1 += 1;

    };

    }

    var c10 = new Class1();

    var c11 = new Class1();

    console.log(c10.var1); // undefined,变量不可被访问

    console.log(c10 === c11); // false

    c10.fn(); // 10

    c11.fn(); // 10

    c10.fn(); // 11

    c11.fn(); // 11

    // 改进一下

    function Class2() {

    this._var1 = 10;

    }

    Class2.prototype = {

    constructor: Class2,

    fn: function() {

    console.log(this._var1);

    this._var1 += 1;

    }

    };

    var c20 = new Class2();

    var c21 = new Class2();

    c20.fn(); // 10

    c20.fn(); // 11

    c21.fn(); // 10

    c21.fn(); // 11

    console.log(c20._var1); // 11,变量可被访问

    console.log(c20.fn === c21.fn); // true

    // 为了解决上述问题

    var m = (function() {

    function Class3() {

    this.var1 = 10

    }

    Class3.prototype = {

    constructor: Class3,

    fn: function() {

    console.log(this.var1);

    this.var1 += 1;

    }

    };

    function createClass3() {

    var c3 = new Class3();

    return {

    fn: Class3.prototype.fn.bind(c3)

    };

    }

    return {

    createClass3: createClass3

    }

    })();

    var c30 = new m.createClass3();

    var c31 = new m.createClass3();

    c30.fn(); // 10

    c30.fn(); // 11

    c31.fn(); // 10

    c31.fn(); // 11

    转自 https://www.2cto.com/kf/201812/789598.html   来源:学习编程的小菜鸟  

  • 相关阅读:
    Nginx 本地建立负载均衡(Windows环境)
    Nginx 代理本地文件夹(Windows环境)
    PostGIS 使用Mysql_fdw同步ArcGIS填坑记录
    PostGIS mysql_fdw操作日志(留观)
    PostGIS mysql_fdw使用(Linux)
    PostGIS mysql_fdw安装(Linux)
    PostGIS 安装教程(Linux)(二)
    PostGIS 安装教程(Linux)(一)
    Linux 命令记录
    PostGIS 查看表属性(字段、类型、是否为空)
  • 原文地址:https://www.cnblogs.com/gs456/p/10998660.html
Copyright © 2011-2022 走看看