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(); //
c11.fn(); //
c10.fn(); //
c11.fn(); // // 改进一下
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(); //
c20.fn(); //
c21.fn(); //
c21.fn(); //
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(); //
c30.fn(); //
c31.fn(); //
c31.fn(); //
JavaScript中为什么使用立即执行函数来封装模块?的更多相关文章
- JavaScript中的闭包与匿名函数
知识内容: 1.预备知识 - 函数表达式 2.匿名函数 3.闭包 一.函数表达式 1.定义函数的两种方式 函数声明: 1 function func(arg0, arg1, arg2){ 2 // 函 ...
- JavaScript中常见的数组操作函数及用法
JavaScript中常见的数组操作函数及用法 昨天写了个帖子,汇总了下常见的JavaScript中的字符串操作函数及用法.今天正好有时间,也去把JavaScript中常见的数组操作函数及用法总结一下 ...
- JavaScript中常见的字符串操作函数及用法
JavaScript中常见的字符串操作函数及用法 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信 ...
- 一篇文章把你带入到JavaScript中的闭包与高级函数
在JavaScript中,函数是一等公民.JavaScript是一门面向对象的编程语言,但是同时也有很多函数式编程的特性,如Lambda表达式,闭包,高阶函数等,函数式编程时一种编程范式. funct ...
- 使用 JavaScript 中的 window 对象执行计时操作,完成一个抽奖程序
查看本章节 查看作业目录 需求说明: 使用 JavaScript 中的 window 对象执行计时操作,完成一个抽奖程序 实现思路: 在 HTML 页面中放置背景图片.转盘和指针 3 张图片,并设置指 ...
- javascript中的两个定时函数setTimeOut()和setInterVal()的区别
js中经常性要用到间隔几秒或暂停几秒执行某个函数, 简单介绍我从网上收集到setTimeOut()和setInterVal()的区别1.setInterVal()介绍 1)定义 setInterval ...
- JavaScript中的闭包和匿名函数
JavaScript中的匿名函数及函数的闭包 1.匿名函数 2.闭包 3.举例 4.注意 1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没 ...
- javascript 中break、 continue、函数不能重载
在javascript中,break与continue有着显著的差别. 如果遇到break语句,会终止最内层循环,无论后面还有多少计算. 如果遇到continue,只会终止此次循环,后面的自循环依然执 ...
- 谈谈javascript中的变量提升还有函数提升
在很多面试题中,经常会看到关于变量提升,还有函数提升的题目,所以我就写一篇自己理解之后的随笔,方便之后的查阅和复习. 首先举个例子 foo();//undefined function foo(){ ...
随机推荐
- windows服务器安全管理工具——IISCrypto
官方网站地址:https://www.nartac.com/Products/IISCrypto/ 下载地址:https://www.nartac.com/Products/IISCrypto/Dow ...
- JVM常用配置参数说明
堆设置 -Xms256M:初始堆大小256M,默认为物理内存的1/64 -Xmx1024M:最大堆大小1024M,默认为物理内存的1/4,等于与-XX:MaxHeapSize=64M -Xmn64M: ...
- Python cv2库(人脸检测)
根据访问图片识别 # coding:utf-8 import sysimport math import cv2 # 待检测的图片路径 imagepath = r'l.png' face_cascad ...
- MSDN订户下载权限被屏蔽的办法
使用Chrome浏览器,在加载完成页面之后,按F12,在控制台选项卡当中输入下面代码,即可解除屏蔽. $("#SubMigratedMessageArea").remove(); ...
- Win10系列:C#应用控件进阶9
RectangleGeometry 在使用RectangleGeometry控件绘制矩形时,矩形的位置和尺寸由Rect属性定义,该属性指定矩形的相对位置.高度和宽度.Rect有四个参数,前两个参数表示 ...
- Spring———bean的创建方式,注入方式,复杂类型注入 概括
Spring相关概念和类 1.IOC inverse of control 控制反转 反转了创建对象的方式 以前:new 对象,管理和维护 ...
- C# [Win32] [API] WS_TABSTOP 無效的解決辦法
關鍵: IsDialogMessage function MSG msg; int bRet = 1; while (bRet != 0) { if (PeekMessageW(&msg, ( ...
- python笔记23-模块导入、安装
模块:import 模块的实质就是把要导入模块里面的代码,从上到下执行一遍,找模块的顺序是,先从当前目录下找,找不到的话,再环境变量里面找 一:导入模块 1.查找环境变量地址: import sysp ...
- Windows挂载NFS共享盘
Centos7添加NFS方法请见如下链接: https://www.cnblogs.com/jackyzm/p/10285845.html 一:添加NFS服务 1.1:此电脑-右键-管理-window ...
- Java NIO学习之Buffer
Bufer的capacity,position和limit: capacity: 表示buffer的容量. position: 写数据到Buffer中时: 表示当前的位置.初始的position值为0 ...