作者:石川
文末彩蛋等你来揭晓。
前言
在实际开发过程中,我积累了一些常用的、超级好用的Jascript技巧和代码片段,包括其他大神的JS使用技巧。今天我挑选了9个,供大家参考。
1、动态加载 JS 文件
在一些特殊的场景下,尤其是在一些库和框架的开发中,我们有时会动态加载JS文件并执行。下面是一个简单的有承诺的包。
函数loadJS(files,done) {//获取头部标签consthead = document。getelementytagname(& # 39;头& # 39;)[0];promise . all(files . map(file = & gt;{返回新承诺(resolve = & gt{//创建一个脚本标记,并将其添加到head consts = document . createelement(& # 39;脚本& # 39;);s.type = & # 34文本/JaScript & # 34;;s.async = trues.src = file//侦听加载事件,如果加载完成,解析s . addevent listener(& # 39;负载& # 39;,(e)= & gt;resolve(),false);head.appendChild});})).然后(搞定);//全部完成,执行user }loadJS的回调事件([& # 34;test1.js & # 34, "test 2 . js & # 34;],()= & gt{//用户的回调逻辑});上面的代码有两个核心点。一种是使用Promise处理异步逻辑,但是使用script标签加载和执行js。
2、实现模板引擎
下面的例子用很少的代码实现了一个动态模板渲染引擎,不仅支持普通动态变量的替换,还支持包括for循环和if判断在内的动态JS语法逻辑。具体的实现逻辑在作者的另一篇文章《面试官问:可以手工编写模板引擎吗?(https://juejin.cn/post/7207697872706486328)做了非常详细的解释,有兴趣的朋友可以自己看一下。
//这是一个动态模板var template = & # 39其中包含js代码。我最喜欢的运动:& # 39;+'& lt% if(this . show sports){ % & gt;'+ '& lt% for(var index in this . sports){ % & gt;'+ '& lta & gt& lt% this . sports[index]% & gt;& lt/a & gt;'+ '& lt% } % & gt'+'& lt% } else { % & gt'+ '& ltp & gt无& lt/p & gt;'+'& lt% } % & gt';//这是函数字符串const code = ` with(obj){ var r =[];r . push(& # 34;我最喜欢的运动:& # 34;);if(this . show sports){ for(this . sports中的var index){ r . push(& # 34;& lta & gt");r . push(this . sports[index]);r . push(& # 34;& lt/a & gt;");} } else { r . push(& # 34;& ltspan & gt无& lt/span>。");} return r . join(& # 34;");` `//动态渲染数据const options = { sports:[& # 34;游泳& # 34;, "篮球& # 34;, "足球& # 34;],showSports: true}//构建一个可行函数并传入参数,在函数执行时改变这个的点result = new Function(& # 34;obj & # 34,代码)。apply(选项,[选项]);console.log(结果);3.使用reduce转换数据结构。有时候前端需要对后端传来的数据进行转换,以适应前端的业务逻辑,或者对组件的数据格式进行转换后再传输到后端进行处理。reduce是一个非常强大的工具。
const arr =[{ classId:& # 34;1",名称:& # 34;张三& # 34;,年龄:16 },{ classId:& # 34;1",名称:& # 34;李四& # 34;,年龄:15 },{ classId:& # 34;2",名称:& # 34;王武& # 34;,年龄:16 },{ classId:& # 34;3",名称:& # 34;刘钊& # 34;,年龄:15 },{ classId:& # 34;2",名称:& # 34;孔琦& # 34;,年龄:16 }];groupArrayByKey(arr,& # 34;classId & # 34);函数groupArrayByKey(arr = [],key) { return arr.reduce((t,v)= & gt;(!T [v [key]]&&(t [v [key]] = []),T [v [key]]。Push (v),t),{}}很多复杂的逻辑,如果用reduce处理,都是非常简洁的。
4、添加默认值
有时一个方法需要用户传入一个参数。通常,我们有两种方法来处理它。如果用户不传入一个参数,我们一般会给一个默认值,或者用户必须传入一个参数,不传就扔错了。
function double(){ return value * 2 }//如果不传递,就给它一个默认值0 function double(value = 0){ return value * 2 }//用户必须传递一个参数,否则一个错误const required =()= & gt;{抛出新错误(& # 34;该函数需要一个参数。")} Function Double(value = required()){ return value * 2 } Double(3)//6 Double()/throw error listen方法用于创建NodeJS的原生http服务并监听端口,在服务的回调函数中创建上下文,然后调用用户注册的回调函数并传递生成的上下文。我们先来看看之前createContext和handleRequest的实现。
5、函数只执行一次
在某些情况下,我们有一些特殊的场景,一个函数只允许执行一次,或者一个绑定的方法只允许执行一次。
Export function once (fn) {//使用闭包来判断函数是否已经执行。Let called = false返回函数(){if(!Called) {called = truefn。应用(this,arguments)}} 6。实现CurringJaScript的cori化是指将一个接受多个参数的函数转化为一系列只接受一个参数的函数的过程。这样可以更灵活地使用函数,减少重复代码,增加代码的可读性。
函数curry(fn) {返回函数curried(…args){ if(args . length & gt;= fn . length){ return fn . apply(this,args);} else {返回函数(…args 2){ return curried . apply(this,args . concat(args 2));};} };}函数add(x,y){ return x+y;} const curriedAdd = curry(add);console . log(curried add(1)(2));//output 3 console . log(curried add(1,2));//Output 3通过some化,我们可以模块化一些常用的功能,比如认证,缓存等等。这可以提高代码的可维护性和可读性,并减少出错的机会。
7、实现单例模式
JaScript的Singleton模式是一种常用的设计模式,它可以确保一个类只有一个实例,并提供该实例的全局访问点。JS的应用场景非常广泛,比如购物车、缓存对象、全局状态管理等等。
让缓存;A级{ //…}函数getInstance() { if (cache)返回缓存;返回cache = new A();} const x = getInstance();const y = getInstance();console . log(x = = = y);// true8。实现CommonJs规范的核心思想是把每个文件当作一个模块,每个模块都有自己的作用域,其中的变量、函数和对象都是私有的,外部无法访问。要访问模块中的数据,您必须导出和导入。
// id:完整文件名const path = require(& # 39;路径& # 39;);const fs = require(& # 39;fs & # 39);函数模块(id){ //用于唯一标识模块this.id = id//用于导出模块的属性和方法。exports = { };} function my require(文件路径){//直接调用模块的静态方法加载文件,返回模块。_load(文件路径);}模块。_ cache = { };模块。_ load = function(file path){//首先通过用户传入的文件路径来寻址文件的绝对路径//因为在CommnJS中,模块的唯一标识是文件const realpath = module的绝对路径。_ resolvefilename(文件路径);//缓存优先。如果存在于缓存中,会直接返回模块的exports属性,让cache module = module。_ cache[real path];if(cacheModule)返回cacheModule.exports//如果是第一次加载,需要一个新的模块,参数是文件的绝对路径,let Module = new Module(realPath);//调用模块的load方法编译module . load(realPath);返回模块. exports;}//节点文件暂时不讨论模块。_ extensions = {//处理js文件& # 34;。js & # 34:handleJS,//处理json文件& # 34;。json & # 34:handlejson}函数handle json(module){//如果是JSON文件,直接用fs.readFileSync读取,//然后用JSON.parse转换,直接返回const JSON = fs . read file sync(module . id,& # 39;utf-8 & # 39;)module . exports = JSON . parse(JSON)}函数handle js(module){ const js = fs . read file sync(module . id,& # 39;utf-8 & # 39;)设fn =新函数(& # 39;出口& # 39;, '我的要求& # 39;, '模块& # 39;, '_ _ filename & # 39, '_ _ dirname & # 39,js)let exports = module . exports;//组装好的函数可以直接执行fn.call (exports,exports,myrequire,module,module.id,Path。dirname(模块。ID)}模块。_ resolve filename = function(file path){//拼接绝对路径,然后查找,如果存在,返回Let Abspath = path。Resolve (_ _ dirname,file path);let exists = fs . exists sync(absPath);如果(存在)返回absPath//如果不存在,尝试拼接。js,。json和。依次节点。让keys = object。钥匙(模块。_ extensions);for(设I = 0;我& ltkeys.lengthi++){ let current path = absPath+keys[I];if (fs.existsSync(currentPath))返回current path;}};模块。原型。load = function(realpath){//获取文件扩展名,让extname = path。extname (realpath)模块。_ extensions [extname] (this)}简单实现了CommonJs规范,核心解决了作用域的隔离,提供Myrequire方法加载方法和属性。对于上面的实现,笔者特意有一篇文章《38行代码带你实现CommonJS规范》(https://juejin.cn/post/7212503883263787064)进行详细讲解,感兴趣的朋友可以自己看一下。
9、递归获取对象属性
如果我必须选择最广泛使用的设计模式,我会选择观察者模式。如果非要选我遇到最多的算法思维,那肯定是递归。递归将原问题分解成结构相同的子问题,然后依次求解这些子问题,最后通过组合子问题的结果得到原问题的答案。
const user = { info:{ name:& # 34;张三& # 34;,地址:{家庭:& # 34;陕西& # 34;,公司:& # 34;西安& # 34;}, },};// obj是获取属性的对象,path是路径,fallback是functionget (obj,path,fallback){ const parts = path . split(& # 34;。");const key = parts . shift();if (typeof obj[key]!== "未定义& # 34;){ return parts.length & gt0 ?get(obj[key],parts . join(& # 34;。"),fallback):obj[key];}//如果键不是fallback,则返回fallback;}console.log(get(user,& # 34;info.name & # 34));//张三console.log(get(user,& # 34;info . address . home & # 34;));// Shaanxiconsole.log(get(user,& # 34;信息.地址.公司& # 34;));// Xianconsole.log(get(user,& # 34;info . address . ABC & # 34;, "后备& # 34;));// fallback挑选了9个我认为比较有用的JS技巧,希望能帮到大家。
正文结束蛋> & gt
码上掘金编程大赛火热进行中,同时为大家推出“报名仪式&终奖”活动~
报名就有机会瓜分百万掘金矿石奖池!投稿作品还可以参与精美奖品的抽奖!
抽奖攻略请戳这里> & gtHttps://juejin.cn/post/7223243191655088183 # heading-1
点击此处查看比赛的更多特别活动> & gthttps://juejin.cn/post/7219130999685840956#heading-8
关注“ByteFE at Byte Front”微信官方账号,不要迷路!
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。