JS 模块 p6

利用了闭包的模块:

简单模块例子:

function fn(){
   var x = 1;
   function y(){
       console.log(x);
    }   

    return {  y:y}
}var do1 = fn()

do1.y();   // 1

我们可以将这个“对象类型”的返回值看做是 模块的公共API 
这个例子中返回的实例中 y() 等于是拥有了函数fn的内部作用域的闭包。

模块模式条件(书):

1.必须由外部的封闭函数,且被调用。

2.封闭函数必须返回至少一个内部函数。

单例模式(平时使用的比较多):

var single = (function(){
    var x = 1;
    function fn(){
        console.log(1);
    };
    return {  fn:fn  }
})();

single.fn();//1

将模块函数使用IIFE 表达出来,因为是立即调用,所以此实例的标识foo为单例。??

还有一种在初始化html的时候使用的也比较多,如下:

(function(){
  var u = {};
  u.x = function(a){
       console.log(a);
  }

  window.$custom = u;

})();

$custom.x(1);//1

使用IIFE 立即给window动态增加一个属性,$custom,因为window的变量和方法是可以隐去的,我们可以直接调用$custom实例引用的方法x,最终打印1。

动态修改(返回实例引用中fn与fn2都用于内部作用的闭包,所以可以在外部通过调用fn2,动态修改内部id的值):

var foo = (function(){
      var id = "hhh";

      function fn(){
           console.log(id);
      } 

      function fn2(){
           id = "MM"
      } 

      return {  fn:fn ,fn2:fn2  }
})();

foo.fn();//hh
foo.fn2();
foo.fn();//MM

当然了,你可以更改函数或者增加新的实例方法(之前的文章中有写 JS 创建自定义对象的方式方法

再来一个(引用书中的例子):

var foo = (function x(){
    var module = {};

    function def(name,arr,impl){
         for(let i = 0;i<arr.length;i++){
               // 重新定义数组中的对象
               arr[i] = module[arr[i]];
         }
         module[name] = impl.apply(impl,arr);
    }

    function get(n){
        return module[n];
    }

    return {def:def,get:get}
})()    

定义一个先:

// 返回一个模块对象实例
foo.def(‘test‘,[],function(){   
    function h(n){return ‘我是test内部的h函数‘+n}
    return { h : h };
});

foo.get(‘test‘).h(‘hi‘); // 我是test内部的h函数hi

// 返回方法函数本身
foo.def(‘test‘,[],function(){
    function h(n){return ‘我是test内部的h函数‘+n}
    return { h : h };
});

foo.get(‘test‘)(‘hi‘);  //  我是test内部的h函数hi

两种方式,第一种内部module的get 返回一个对象实例,含有h内部函数,可以调用;

第二种返回h函数本身,通过  ‘()‘ 直接调用即可。

再来一个,多重调用(在上面给module定义了test后,再来一个并且利用回调函数调用test)

foo.def(‘test2‘,[‘test‘],function(callback){
     function j(){
         console.log(callback.h(‘hihihihi‘)+‘其实我是test2‘);
     }    

     return { j:j }
});

foo.get(‘test2‘).j();//我是test内部的h函数hihihihi其实我是test2

我们来分析一下,在foo.def 方法中核心的时候这句 apply(有关apply 、call和blind方面以后再表),简单说一下,apply方法把作用域第一个参数的作用域绑定或追加到调用的对象中,从何绑定this,并执行改方法,第二个参数就是执行这个方法需要的参数。

那么我们在调用def时,就是给foo中的内部对象module增加了一对键值对,module.name = impl()    这里得到impl函数执行后返回值

在调用get的时候,得到这个值,在第一个def中是test返回是 {h:h} 对象实例(调用foo.get()),所以我们使用 foo.get(‘test‘).h() 就调用了返回实例中的h函数,而h函数拥有访问h所在的作用域的闭包。

再来看第二个def,test2:

第二个def时我们给到3个参数,test,[test2]和一个匿名函数

foo在执行def方法时,首先循环数组,并重新对数组中的值进行重新赋值,这个例子中是 module[test],等于是得到了def1中的{h:h} 对象实例,然后调用apply方法,执行定义的匿名函数,返回值为 {j:j}

并且j方法中的callback 其实就是{h,h} ,(是这样的  module[test2] = impl.apply(impl,{h:h}) ),明白没?

所以foo中的内部对象 module又获得了一对简直,module.test2 = { j:j }  ,并且j中的callback 是 {h:h}

最后我们通过  foo.get(‘test2‘) 获得了{j:j} 然后执行 j() 方法,并成功打印  “我是test内部的h函数hihihihi其实我是test2”。

此处在test2中,j()方法拥有作用域的闭包,也就是说可以访问到callback,而callback实际上在此事{h:h},而h也拥有其作用域的闭包。

可以说,这就是一种模块的表现方式或者说闭包的应用。

关于es6对模块有了重新的定义,再次我简单记录一下:

// test.js
function h(){
  return ‘ggggg‘
}

export h;

// test2.js
import h from ‘test‘;

function j(){
   console.log(
      h();
   )
}

export j;

// foo.js
module test from ‘test‘;
module test2 from ‘test2‘;

console.log(
    test2.h();
)

test2.j();

关键字:

import: 将一个模块的一个或者多个API 导入到当前作用域

export: 将当前的一个标识符导出为API

module: 将模块的API 导入并绑定到一个变量。

原文地址:https://www.cnblogs.com/jony-it/p/10337709.html

时间: 01-29

JS 模块 p6的相关文章

js模块开发(一)

现在嵌入页面里面的javascript代码越来越复杂,于是可能依赖也越来越严重,使用别人开发的js也越来越多,于是在理想情况下,我们只需要实现核心的业务逻辑,其他都可以加载别人已经写好的模块. 于是js模块化开发就显的越来越重要了,但是,Javascript不是一种模块化编程语言,它不支持"类"(class),更遑论"模块"(module)了.(正在制定中的ECMAScript标准第六版,将正式支持"类"和"模块",但还需要很

使用seajs封装js模块

//方法一:将函数绑定到原型上 define(function(require, exports, module) { $.fn.tab = function(option, callback) { function bootstrap() { console.log('djsakhdkj'); } bootstrap(); } $(function(){ $().tab();//因为将tab绑定到$原型上,所以要使用$().tab()去调用 }) }) //方法一(2):将函数绑定到jquer

Node JS 模块

require('./test'); 和require('./test.js');是一样的,系统会自动加上后缀引入test.js功能模块 如下是require.js文件 var sum=require('./sum.js');//引入sum.js模块 console.log(sum.sum());//sum(可以传递参数) 如下是sum.js文件 function sum(){//可传递参数 var sum=0;console.time('runTime');for(var i =0;i<=10

2015.3.12(遮罩层JS模块)

这两天了解了一些前端开发常用的工具和库和框架,有一个疑问,如果大量使用这些现成的框架,会不会导致大材小用呢?就是每一个页面都要加载一遍可能要用的框架和库,但实际上这个页面的实现只会用到一小部分,这样无形中就会拖慢速度或者是造成用户的流量浪费.这种问题要怎么解决呢?  没有开发经验啊,这种优化问题有点想不明白. 今天的练习需要一个可以用于点击图片放大图片以及用于替代系统自带的alert的遮罩层写了如下的js模块.方便在项目中直接调用. 下面是html部分的代码.只是在button的onclick事

Node.js模块封装及使用

Node.js中也有一些功能的封装,类似C#的类库,封装成模块这样方便使用,安装之后用require()就能引入调用. 一.Node.js模块封装 1.创建一个名为censorify的文件夹 2.在censorify下创建3个文件censortext.js.package.json.README.md文件 1).在censortext.js下输入一个过滤特定单词并用星号代替的函数. var censoredWorlds=["sad","bad","mad&

Node.js 模块和 NPM

1.模块概念 原生模块:Node.js API 提供的原生模块,原生模块在启动时已经被加载. 文件模块:动态加载模块,由原生模块 module 来实现和完成. 文件模块需要通过调用 require 方法来实现加载. Node.js 对两种模块都有缓存,不会重复开销去加载模块,只读取相应数据. 原生模块的调用 Node.js 的 API require 加载相应的 Node.js 模块,加载成功后返回一个 Node.js 模块对象. 该对象拥有该模块的所有方法和属性. var httpModule

浅析JS模块规范:AMD,CMD,CommonJS

随着JS模块化编程的发展,处理模块之间的依赖关系成为了维护的关键. 模块化 AMD,CMD,CommonJS是目前最常用的三种模块化书写规范. CommonJS CommonJS规范是诞生比较早的.NodeJS就采用了CommonJS.是这样加载模块: var clock = require('clock'); clock.start(); 这种写法适合服务端,因为在服务器读取模块都是在本地磁盘,加载速度很快.但是如果在客户端,加载模块的时候有可能出现"假死"状况.比如上面的例子中cl

node.js模块之fs文件系统

fs 模块是文件操作的封装,它提供了文件的读取.写入.更名.删除.遍历目录.链接等 POSIX 文件系统操作.与其他模块不同的是,fs 模块中所有的操作都提供了异步的和同步的两个版本, 例如读取文件内容的函数有异步的 fs.readFile() 和同步的fs.readFileSync().我们以几个函数为代表,介绍 fs 常用的功能,并列出 fs 所有函数的定义和功能. fs.readFile(filename,[encoding],[callback(err,data)])是最简单的读取文件的

Node.js模块

通常在创建Node.js程序时,我们需要按照一定的逻辑相关性对代码进行划分,组织成多个模块,而不是将代码都在放单个文件中.这必然像其他语言一样,有类似包或者模块的机制可以使用.我们看在Node.js中如何创建和使用模块. 1.单个文件模块 --module.js exports.add = function(a, b) { return a + b; }; var sub = function(a, b) { return a - b; }; --main.js var module = req

node.js 模块和包

Node.js 的模块和包机制的实现参照了 CommonJS 的标准,但并未完全遵循.不过两者的区别并不大,一般来说你大可不必担心,只有当你试图制作一个除了支持 Node.js之外还要支持其他平台的模块或包的时候才需要仔细研究.通常,两者没有直接冲突的地方. 模块是 Node.js 应用程序的基本组成部分,文件和模块是一一对应的.换言之,一个Node.js 文件就是一个模块,这个文件可能是 JavaScript 代码.JSON 或者编译过的 C/C++ 扩展.在前面章节的例子中,我们曾经用到了