前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript模块化写法解析

JavaScript模块化写法解析

作者头像
我是leon
发布2019-08-28 11:42:43
5310
发布2019-08-28 11:42:43
举报
文章被收录于专栏:leon的专栏leon的专栏

一、IIFE解释

全拼Imdiately Invoked Function Expression,立即执行的函数表达式。

像如下的代码所示,就是一个匿名立即执行函数:

代码语言:javascript
复制
(function(window, undefined){
  // 代码...	
})(window);

二、括号的意义

2.1 包住function(){}的括号的意义

这个括号的目的,是为了把function(){}转化为表达式。像一些库的源码,喜欢用如下方式代替:

代码语言:javascript
复制
~function(){
  // 代码...
}();

或者这种方式:

代码语言:javascript
复制
+function(){
  // 代码...
}();

其实,作用都一样,都是把function(){}转化成一个可执行的表达式,方便执行。  如果去掉该括号,则会报错。因为单纯的function(){}不是可执行的表达式,会直接报错。如下图:

2.1 第二个括号的意义

理解了第一个括号的意义,第二个括号就很简单了,就是执行表达式了。

三、参数的意义

以这段代码为例子,讲解参数

代码语言:javascript
复制
var wall = {};
(function(window, WALL, undefined){
	
})(window, wall);

参数分为形参和实参。 function(window, WALL, undefined)三个参数为形参,第二个括号(window, wall)的两个参数为实参。  也即可以理解为 window == windowwall == WALL

2.1 普通形参

普通形参是指由windowwall这样的实际变量传入指定,可以为任何类型的变量。一个形参就对应一个实参

2.2 特殊形参undefined

为什么形参要多写一个undefined,这是一个很有趣的话题。  可以知道这个示例,实参只有两个,而形参有三个。所以在函数执行的时候,形参undefined会默认赋值为undefined。

形参undefined的作用如下:

2.2.1 防止特殊值undefined被恶意代码篡改。  IE6等低版本浏览器,undefined是支持被修改的。而这个特殊值被修改后,像以下这种判断就失效了。

代码语言:javascript
复制
if(wall == undefined){
  // 代码...
}

所以,这里多加一个形参的目的就是为了防止这种情况发生。只要在这个IIFE作用域内,undefined就能够正常获取到。

2.2.2 压缩代码可以压缩undefined  因为undefined作为形参,像YUI compressor这种类型的代码压缩工具,可以将其相关的值进行压缩,减小文件的体积。

四、写法解析

4.1 普通写法

代码语言:javascript
复制
var wall = {}; // 声明定义一个命名空间wall

// 定义方法
(function(window, WALL, undefined){
	// 给wall命名空间绑定方法say
	WALL.say = function(){
		console.log('hello');
	};
})(window, wall);

(function(window, WALL, undefined){
	// 给wall命名空间绑定方法 whoIam
	WALL.whoIam = function(){
		console.log('wall');
	};
})(window, wall);

// 调用
wall.say();
wall.whoIam();

先定义一个命名空间,然后再给这个命名空间加东西。这是最普遍的写法,也是最好理解的。  不足的地方就是必须先声明一个命名空间,然后才能执行相关的绑定代码。存在顺序加载的问题。

4.2 放大模式

代码语言:javascript
复制
var wall = (function(window, WALL, undefined){
	if(typeof WALL == 'undefined'){
		WALL = {};
	}

	// 给wall命名空间绑定方法say
	WALL.say = function(){
		console.log('hello');
	}

	return WALL; // 返回引用
})(window, wall);

var wall = (function(window, WALL, undefined){
	if(typeof WALL == 'undefined'){
		WALL = {};
	}

	// 给wall命名空间绑定方法 whoIam
	WALL.whoIam = function(){
		console.log('wall');
	}

	return WALL; // 返回引用
})(window, wall);

// 调用
wall.say();
wall.whoIam();

放大模式的好处就是,可以不用考虑代码加载的先后顺序。  因为js允许wall变量进行重复var声明,所以这段代码是可以执行的。  我可以把IIFE函数拆分成多个文件进行加载,而不会出现普通写法需要注意的问题。

需要注意的点:  1.IIFE的头部,都要先进行检查命名空间是否已经实例化,如果还没实例化,则进行实例化。  2.IIFE的尾部,都要return命名空间的引用,使后续代码能够得到最新的wall命名空间内容。

4.3 宽放大模式

代码语言:javascript
复制
(function(window, WALL, undefined){
	// 给wall命名空间绑定方法say
	WALL.say = function(){
		console.log('hello');
	}
})(window, window.wall || (window.wall = {}));

(function(window, WALL, undefined){
	// 给wall命名空间绑定方法 whoIam
	WALL.whoIam = function(){
		console.log('wall');
	}
})(window, window.wall || (window.wall = {}));

// 调用
wall.say();
wall.whoIam();

**宽放大模式的重点注意的地方:**就是在实参部分的window.wall || (window.wall = {})。  用||运算符进行取巧。  如果window.wall是已经实例化的,非not defined。则直接返回window.wall的引用,赋值给形参WALL。不会执行||运算符后面的内容。  如果window.wall还未实例化,则进行实例化。这里要注意的点是实例化是一个赋值操作,需要用括号包起来,变成表达式去执行,才不会报错。  表达式(window.wall = {})执行完毕后,会返回新对象window.wall的引用。

**宽放大模式的好处:**是可以切割成多个文件进行加载,而不必考虑文件加载的先后顺序,不存在强耦合关系。  当然,如果IIFE里面的方法互相引用,还是存在加载依赖的问题。这个问题可以用加载器Require.js等工具解决,这里就不讨论了。

五、分文件加载IIFE要注意的点

代码语言:javascript
复制
;(function(window, WALL, undefined){
	// 给wall命名空间绑定方法say
	WALL.say = function(){
		console.log('hello');
	}
})(window, window.wall || (window.wall = {}));

眼尖的已经看出区别了,就是文件开始的地方,先写上分号;。  这样,多个文件合并的时候,才不会出现收尾相接,代码出现错乱的问题。比如下面这种情况:

代码语言:javascript
复制
// a.js 文件
wall.log()

// b.js 文件
(function(window, WALL, undefined){
	// 给wall命名空间绑定方法say
	WALL.say = function(){
		console.log('hello');
	}
})(window, window.wall || (window.wall = {}));

由于a.js文件的wall.log()少写了分号,跟b.js文件合并后,js就会认为‘wall.log()(…)’是需要这么执行的,结果代码就报错了。


本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-02-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、IIFE解释
  • 二、括号的意义
  • 三、参数的意义
  • 四、写法解析
  • 五、分文件加载IIFE要注意的点
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档