我的JS笔记 -- 模块

176 阅读3分钟

模块化可以使你的代码低耦合,功能模块直接不相互影响。

模仿块级作用域

JS中没有块级作用域,而是函数作用域,函数中声明的变量和函数不会泄露到外部作用域。那么就可以通过在函数中创建私有变量。

function f() {
	var a = 1;
}
a // ReferenceError: a is not defined

但是这样函数名也是一个全局变量,也有污染全局变量的危险。那么如果使用匿名函数呢?

// 这样会报错,函数声明必须要有标识符
function () {
	var a = 1; 
}

// 仍是会生成全局标识符 
var f = function () {
	var a = 1;
}

JS中可以利用立即执行函数模仿块级作用域,立即函数是一个函数表达式而不是函数声明,不会提升,解析到这行就会立即运行。这样既不会污染全局变量,函数也可以执行。

// 写法一
(function () {
    // 块级作用域
}());

// 写法二
(function () {
    // 块级作用域
})();

// 写法三
(function (fn) {
    fn();
})(function f() {
    // 块级作用域
});

私有变量

JS中函数的参数、局部变量和函数内部定义的函数都不能再函数的外部被访问,所以被称为私有变量。

那么有权访问私有变量和私有函数的公有方法称为特权方法。

特权方法是在对象上创建,一般有两种方式:构造函数定义特权方法和静态私有变量实现特权方法。这两种都是用于为自定义类型创建私有变量和特权方法的。

  • 构造函数定义特权方法;

      function F() {
      	var a = 1; // 私有变量
      	function sayA() { // 私有函数
      		console.log(a);
      	}
      	this.sayA = sayA; // 特权方法
      }
      var f = new F();
      f.sayA(); // 1
    

缺点是每个实例都会创建一组新方法,违反了构造函数与实例对象相分离的原则。并且,非常耗费内存。

  • 静态私有变量实现特权方法;

      (function () {
      	var a = 1; // 私有变量
      	function sayA()  { // 私有函数
      		console.log(a);
      	}
      	// 构造函数使用函数表达式,且不使用var,函数声明只能创建局部变量,不使用var的函数表达式可以创建全局变量,让其在私有作用域之外访问
      	F = function () {
      		//
      	};
      	F.prototype.sayA = sayA; // 特权方法
      })();
      var f = new F();
      f.sayA(); // 1
    

缺点是私有变量是公用的,所有实例使用的都是相同的私有变量。

模块模式

模块模式是为单例创建私有变量和特权方法。

在JS可以利用立即执行函数和闭包创建模块。

模块模式需要具备两个必要条件:

  1. 必须有外部的封闭函数, 该函数必须至少被调用一次( 每次调用都会创建一个新的模块实例);

  2. 封闭函数必须返回至少一个内部函数, 这样内部函数才能在私有作用域中形成闭包, 并且可以访问或者修改私有的状态;

    var f = function () { var a = 1; // 私有变量 return { // 函数调用后返回一个包含公开属性和方法的对象 sayA: function () { // 特权方法,通过闭包可以在外部调用时访问内部私有变量 console.log(a); } } }; f().sayA(); // 1

利用匿名函数自执行改写

var f = (function () {
	var a = 1; // 私有变量
	return { // 函数调用后返回一个包含公开属性和方法的对象
		sayA: function () {  // 特权方法,通过闭包可以在外部调用时访问内部私有变量
			console.log(a);
		}
	}
})();
f.sayA(); // 1

更多文章在 这里 ,觉得不错希望点个 star

写在最后:

我只是一个自学JS的初学者,笔记是学习时各处收集的,有一些是我自己的理解。但是不少知识来自分享到网络的大神们,因为实在不知道我在哪里使用了谁的文章,所以只能统一的表达一下我的感谢! 文章里边可能有的地方会有错误,如果发现,可以留言提醒我。