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   来源:学习编程的小菜鸟  

原文地址:https://www.cnblogs.com/gs456/p/10998660.html