首页 > 编程知识 正文

js模块规范cjs,js模块规范esm

时间:2023-12-27 22:28:03 阅读:327187 作者:VFCP

本文目录一览:

在node环境下怎么使用commonjs模块去使用require方法

最初的 CommonJS 小组 的参与者们决定弄一份于时下的 JavaScript 编程语言有效,但不必束缚于浏览器 JS 环境的限制,的模块规范。开始的愿景是在浏览器里使用一些权宜之计, 并希望能借此影响浏览器厂商,促使它们为这种模块规范的原生支持提供解决方案。权宜之计有:

要么使用一个服务来转译 CJS 模块成浏览器中可用的代码

要么使用 XMLHttpRequest(XHR)以文本形式加载模块,再在浏览器中做文本变换、解析的工作

CJS 模块规范仅允许每文件一个模块,所以为优化、打包,可使用某种“转换格式”将多个模块合并到单个文件。

通过这种方式,CommonJS 小组搞定了依赖引用、如何处理循环依赖,以及如何获得当前模块的某些属性等问题。 但是,他们并没能接纳浏览器环境里不可改变、并且仍将影响模块设计的某些特性:

网络加载

异步继承 … 这也同时意味着他们为了实现这个规范,将负担更多地放到了 Web 开发者身上,而这些权宜之计也使调试变得更麻烦。 调试 eval 的代码,或者调试多个文件合并之后的单个文件,都有实际使用时的坏处。 这些缺点或许在未来某天会被浏览器调试工具解决掉,但结论仍然是:在最普遍的 JS 环境,浏览器中,使用 CommonJS 模块并不是最好的办法。

如何理解前端模块化

前端模块化

在JavaScript发展初期就是为了实现简单的页面交互逻辑,寥寥数语即可;如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等),随着web2.0时代的到来,Ajax技术得到广泛应用,jQuery等前端库层出不穷,前端代码日益膨胀

这时候JavaScript作为嵌入式的脚本语言的定位动摇了,JavaScript却没有为组织代码提供任何明显帮助,甚至没有类的概念,更不用说模块(module)了,JavaScript极其简单的代码组织规范不足以驾驭如此庞大规模的代码

模块

既然JavaScript不能handle如此大规模的代码,我们可以借鉴一下其它语言是怎么处理大规模程序设计的,在Java中有一个重要带概念——package,逻辑上相关的代码组织到同一个包内,包内是一个相对独立的王国,不用担心命名冲突什么的,那么外部如果使用呢?直接import对应的package即可

import java.util.ArrayList;

遗憾的是JavaScript在设计时定位原因,没有提供类似的功能,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化。

一个模块就是实现特定功能的文件,有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。模块开发需要遵循一定的规范,各行其是就都乱套了

规范形成的过程是痛苦的,前端的先驱在刀耕火种、茹毛饮血的阶段开始,发展到现在初具规模,简单了解一下这段不凡的历程

函数封装

我们在讲函数的时候提到,函数一个功能就是实现特定逻辑的一组语句打包,而且JavaScript的作用域就是基于函数的,所以把函数作为模块化的第一步是很自然的事情,在一个文件里面编写几个相关函数就是最开始的模块了

function fn1(){

statement

}

function fn2(){

statement

}

这样在需要的以后夹在函数所在文件,调用函数就可以了

这种做法的缺点很明显:污染了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间没什么关系。

对象

为了解决上面问题,对象的写法应运而生,可以把所有的模块成员封装在一个对象中

var myModule = {

var1: 1,

var2: 2,

fn1: function(){

},

fn2: function(){

}

}

这样我们在希望调用模块的时候引用对应文件,然后

myModule.fn2();

这样避免了变量污染,只要保证模块名唯一即可,同时同一模块内的成员也有了关系

看似不错的解决方案,但是也有缺陷,外部可以随意修改内部成员

myModel.var1 = 100;

这样就会产生意外的安全问题

立即执行函数

可以通过立即执行函数,来达到隐藏细节的目的

var myModule = (function(){

var var1 = 1;

var var2 = 2;

function fn1(){

}

function fn2(){

}

return {

fn1: fn1,

fn2: fn2

};

})();

这样在模块外部无法修改我们没有暴露出来的变量、函数

上述做法就是我们模块化的基础,目前,通行的JavaScript模块规范主要有两种:CommonJS和AMD

CommonJS

我们先从CommonJS谈起,因为在网页端没有模块化编程只是页面JavaScript逻辑复杂,但也可以工作下去,在服务器端却一定要有模块,所以虽然JavaScript在web端发展这么多年,第一个流行的模块化规范却由服务器端的JavaScript应用带来,CommonJS规范是由NodeJS发扬光大,这标志着JavaScript模块化编程正式登上舞台。

定义模块

根据CommonJS规范,一个单独的文件就是一个模块。每一个模块都是一个单独的作用域,也就是说,在该模块内部定义的变量,无法被其他模块读取,除非定义为global对象的属性

模块输出:

模块只有一个出口,module.exports对象,我们需要把模块希望输出的内容放入该对象

加载模块:

加载模块使用require方法,该方法读取一个文件并执行,返回文件内部的module.exports对象

js代码规范问题 JavaScript判断语句规范

规范性要参考几个点:

1.是否影响效率

2.是否方便解读

3.是否便于以后维护

针对这三点去做分析就行了,如楼上所说,没有哪个人敢站出来说他写的就是规范的,但是可以通过研究一些js库去学习以形成习惯。

使用 MockJs — 实现真正的前后端分离

前言: 刚刚看了下的后台,发现我技术文章中,阅读留言最多的是关于移动端的文章,甚至还有人付费赞赏或咨询。关于 PC 端的技术文章就显得比较冷清了,唉,废了好大劲写的,没人看。 和我想的一样,移动端才是王道,下次找工作我也搞移动端? 。

背景: 去年我写了一篇 学习使用 json-server 和 mockjs 的文章,当时没有仔细研究,文章只提到了 MockJs 其中一个 Random 的用法,关于 MockJs 拦截器和另一个很常用的 Mock.mock 函数都没有提及。这次来搞一下。

唉!以前我也是经常会听到 前后端分离 这个名词,只模糊的知道它最重要的一个作用就是,大大的提升了 前端的地位。 但是平时在开发的时候,我也会想奶奶的,没有接口这前端不就写了一个破页面,后期还的和后端对接口,对接口的时候花费的时间,肯定是不比前端开发的时候短,工期上最起码一半一半吧, 这也就前后端分离 ,我这个小脑袋就不是太明白了。

不过我现在是终于搞明白这个问题了, 对于前端来讲,真正的前后端分离,标志是不依赖后端的前端工作开发完成,项目基本宣告结束。 后端开发完接口,只需要提换一个 URL 就行了,这也意味着前端需要去写一些接口。

除了带来开发任务稍微重点外,我至少看到了两个最大的优点:

我体会最深就是这两点。

插曲 :对了,今天中午我捡到一个手机,我必须要用一张动图来描述下:

这个经典的 GIF ,来自郑伊健的恐怖电影「第一诫」,清凉一冬,绝对值得一看,虽然剧情有很大的 bug ,但是港片就这点好,它有很抓人的地方,让你觉得特别好看。

正文由此开始:

待续~~~

上面三种方案都可以,但你要知道接口很多,需要支持批量引入,所以 使用 Axios 响应拦截器 就不太可取,只能在这简单的造些假数据。

著名开源项目 vue-element-admin 开发环境下模拟假接口使用的是 在 webpack-dev-server 的 before 处拦截。生产环境下是在项目入口文件( index,js )使用 Mock.mock 模拟的。

拦截请求的步骤如下,根据 devserverbefore 配置的栗子?:

可知道 before 接收一个函数,函数的第一个参数一般叫 app ,因为它的作用和 express 的 app 是等效的。也就是说这个 app 自带路由, 正好解决接口批量引入的问题。

在项目中,一般都是这么写,把逻辑提出去:

./mock/mock-server.js 文件的内容为:

./mock/index.js 文件的内容为:

mockXHR 不用看,因为这是给线上环境用的,所以可以简单的改写为:

随便找一个,例如 user 看下接口怎么写的:

完美,到此结束。

我想你一定对更改文件的时候,为什么要 清路由和清缓存感兴趣。

如果熟悉 express 框架,看到 app._router.stack 你就知道了。不知道也没关,我演示给你看,新建一个JS 文件,文件内容为:

执行结束,看在 test.js 文件的内容:

发现没,重复被添加的路由,不是覆盖而是扩展。

这个涉及到 CJS 模块的运行机制, 记住 require 的文件会被加到 require.cache 里面,当文件改变读的是缓存,而不是最新更改的文件。

项目结构过大,如果只在 mock 文件夹里面管理有点麻烦,我就想在页面所在目录直接写接口,怎么办?没错使用 require.context 来批量引入。但是 NodeJs 是没有批量引入的 API 的。找遍了 npm 也没发现一个 package 和 require.context 长得像的。

难道没办法了吗?当然不是,自己动手丰衣足食。 依照 vue-cli 插件的命名规范,我给写的 package 取名 node-plugin-require-context ,简单讲下实现原理:

其实还有一个缺点,如果你看过 Antd-Pro 项目,你就会发现它模拟数据,模块化采用的是 ESModule ,而不是 CJS。保持编码模块化风格一致确实也是需要优化的一个地方,不管了,反正我不干。

官网本来就是中文的,我在使用中发现写的贼好,我就不用画蛇添足了。建议每次使用前:

如何在html和JS中包含Javascript JS文件终极解决方案

现在常用的一种javascript的方法是在当前的html文档中插入一个script标签,在标签中引入script脚本Js代码var__includes__=newArray;Array.prototype.indexOf=function(obj){for(vari=0;ithis.length;i++){if(this[i]==obj)returni;}return-1;}Array.prototype.add=function(obj){this[this.length]=obj;}functioninclude_js(js){if(__includes__.indexOf(js)-1)return;__includes__.add(js);varhead=document.getElementsByTagName('head')[0];script=document.createElement('script');script.src=js;script.type='text/javascript';head.appendChild(script);}当你只是在你的htmlw文档中使用这个方法的时候,一切OK,这其实是script的标签的一种快捷的写法而已。但是,如果你在一个javascript使用这个方法,问题就来了,比如我在test.js中使用include_js("test1.js"),在test1.js中有一个变量test1是在test.js中要使用的,在webkit中尽然出现了test1变量未定义的错误,我不知道ie和firefox是否有这种问题,我想可能是include_js本身不是同步执行导致的,所以我只好使用以下方法来完善inlcude_jsJs代码var__includes__=newArray;Array.prototype.indexOf=function(obj){for(vari=0;ithis.length;i++){if(this[i]==obj)returni;}return-1;}Array.prototype.add=function(obj){this[this.length]=obj;}functionxhttp(url,callback){varrequest=null;if(typeofXMLHttpRequest!='undefined'){request=newXMLHttpRequest();}elseif(typeofActiveXObject!='undefined'){request=newActiveXObject('Microsoft.XMLHTTP');}request.open('GET',url,true);request.onreadystatechange=function(){if(request.readyState==4){callback(request.responseText);}};request.send(null);}functionadd_scripts(jss,callback){varfunc=function(jss,idx,callback){if(idx==jss.length){callback();return};add_script(jss[idx],function(){func(jss,++idx,callback);});}func(jss,0,callback);}functionadd_script(js,callback){if(__includes__.indexOf(js)-1){callback();return;}__includes__.add(js);xhttp(js,function(js_content){varhead=document.getElementsByTagName('head')[0];script=document.createElement('script');head.appendChild(script);// script.innerHTML=js_content; //原帖是这个...本人测试这行..无效 必须用text属性赋值script.defer=true; script.type='text/javascript';script.language='javascript';//本人测试修正..添加script.text=js_content;//本人测试修正..添加//zfrong 09.5.20callback();});}functioninclude_js(js){if(__includes__.indexOf(js)-1)return;__includes__.add(js);varhead=document.getElementsByTagName('head')[0];script=document.createElement('script');script.src=js;script.type='text/javascript';head.appendChild(script);}当我在html文档中引入的时候,我用 include_js,当我在js文件中引入js时候,我使用add_scripts,add_scriptJs代码add_scripts(['test1.js','test2.js']),add_scripts方法使用了xmlhttp来读入js内容,并把读入的内容的写到一个新的script标签内,读入是异步执行的,当执行完毕后,会调用callback、

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。