这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
前言
在实际的开发工作过程中,积累了一些常见又超级好用的 Javascript 技巧和代码片段,包括整理的其他大神的 JS 使用技巧,今天筛选了 9 个,以供大家参考。
【资料图】
1、动态加载 JS 文件
在一些特殊的场景下,特别是一些库和框架的开发中,我们有时会去动态的加载 JS 文件并执行,下面是利用 Promise 进行了简单的封装。
function loadJS(files, done) { // 获取head标签 const head = document.getElementsByTagName("head")[0]; Promise.all(files.map(file => { return new Promise(resolve => { // 创建script标签并添加到head const s = document.createElement("script"); s.type = "text/javascript"; s.async = true; s.src = file; // 监听load事件,如果加载完成则resolve s.addEventListener("load", (e) => resolve(), false); head.appendChild(s); }); })).then(done); // 所有均完成,执行用户的回调事件}loadJS(["test1.js", "test2.js"], () => { // 用户的回调逻辑});
上面代码核心有两点,一是利用 Promise 处理异步的逻辑,而是利用 script 标签进行 js 的加载并执行。
2、实现模板引擎
下面示例用了极少的代码实现了动态的模板渲染引擎,不仅支持普通的动态变量的替换,还支持包含 for 循环,if 判断等的动态的 JS 语法逻辑,具体实现逻辑在笔者另外一篇文章《面试官问:你能手写一个模版引擎吗?》做了非常详详尽的说明,感兴趣的小伙伴可自行阅读。
// 这是包含了js代码的动态模板var template ="My avorite sports:" +"<%if(this.showSports) {%>" + "<% for(var index in this.sports) { %>" + "<%this.sports[index]%>" + "<%}%>" +"<%} else {%>" + "none
" +"<%}%>";// 这是我们要拼接的函数字符串const code = `with(obj) { var r=[]; r.push("My avorite sports:"); if(this.showSports) { for(var index in this.sports) { r.push(""); r.push(this.sports[index]); r.push(""); } } else { r.push("none"); } return r.join("");}`// 动态渲染的数据const options = { sports: ["swimming", "basketball", "football"], showSports: true}// 构建可行的函数并传入参数,改变函数执行时this的指向result = new Function("obj", code).apply(options, [options]);console.log(result);
3、利用 reduce 进行数据结构的转换
有时候前端需要对后端传来的数据进行转换,以适配前端的业务逻辑,或者对组件的数据格式进行转换再传给后端进行处理,而 reduce 是一个非常强大的工具。
const arr = [ { classId: "1", name: "张三", age: 16 }, { classId: "1", name: "李四", age: 15 }, { classId: "2", name: "王五", age: 16 }, { classId: "3", name: "赵六", age: 15 }, { classId: "2", name: "孔七", age: 16 }];groupArrayByKey(arr, "classId");function groupArrayByKey(arr = [], key) { return arr.reduce((t, v) => (!t[v[key]] && (t[v[key]] = []), t[v[key]].push(v), t), {})}
很多很复杂的逻辑如果用 reduce 去处理,都非常的简洁。
4、添加默认值
有时候一个方法需要用户传入一个参数,通常情况下我们有两种处理方式,如果用户不传,我们通常会给一个默认值,亦或是用户必须要传一个参数,不传直接抛错。
function double() { return value *2}// 不传的话给一个默认值0function double(value = 0) { return value * 2}// 用户必须要传一个参数,不传参数就抛出一个错误const required = () => { throw new Error("This function requires one parameter.")}function double(value = required()) { return value * 2}double(3) // 6double() // throw Error
5、函数只执行一次
有些情况下我们有一些特殊的场景,某一个函数只允许执行一次,或者绑定的某一个方法只允许执行一次。
export function once (fn) { // 利用闭包判断函数是否执行过 let called = false return function () { if (!called) { called = true fn.apply(this, arguments) } }}
6、实现 Curring
JavaScript 的柯里化是指将接受多个参数的函数转换为一系列只接受一个参数的函数的过程。这样可以更加灵活地使用函数,减少重复代码,并增加代码的可读性。
function curry(fn) { return function curried(...args) { if (args.length >= fn.length) { return fn.apply(this, args); } else { return function(...args2) { return curried.apply(this, args.concat(args2)); }; } };}function add(x, y) { return x + y;}const curriedAdd = curry(add);console.log(curriedAdd(1)(2)); // 输出 3console.log(curriedAdd(1, 2)); // 输出 3
通过柯里化,我们可以将一些常见的功能模块化,例如验证、缓存等等。这样可以提高代码的可维护性和可读性,减少出错的机会。
7、实现单例模式
JavaScript 的单例模式是一种常用的设计模式,它可以确保一个类只有一个实例,并提供对该实例的全局访问点,在 JS 中有广泛的应用场景,如购物车,缓存对象,全局的状态管理等等。
let cache;class A { // ...}function getInstance() { if (cache) return cache; return cache = new A();}const x = getInstance();const y = getInstance();console.log(x === y); // true
8、实现 CommonJs 规范
CommonJS 规范的核心思想是将每个文件都看作一个模块,每个模块都有自己的作用域,其中的变量、函数和对象都是私有的,不能被外部访问。要访问模块中的数据,必须通过导出(exports)和导入(require)的方式。
// id:完整的文件名const path = require("path");const fs = require("fs");function Module(id){ // 用来唯一标识模块 this.id = id; // 用来导出模块的属性和方法 this.exports = {};}function myRequire(filePath) { // 直接调用Module的静态方法进行文件的加载 return Module._load(filePath);}Module._cache = {};Module._load = function(filePath) { // 首先通过用户传入的filePath寻址文件的绝对路径 // 因为再CommnJS中,模块的唯一标识是文件的绝对路径 const realPath = Module._resoleveFilename(filePath); // 缓存优先,如果缓存中存在即直接返回模块的exports属性 let cacheModule = Module._cache[realPath]; if(cacheModule) return cacheModule.exports; // 如果第一次加载,需要new一个模块,参数是文件的绝对路径 let module = new Module(realPath); // 调用模块的load方法去编译模块 module.load(realPath); return module.exports;}// node文件暂不讨论Module._extensions = { // 对js文件处理 ".js": handleJS, // 对json文件处理 ".json": handleJSON}function handleJSON(module) { // 如果是json文件,直接用fs.readFileSync进行读取, // 然后用JSON.parse进行转化,直接返回即可 const json = fs.readFileSync(module.id, "utf-8") module.exports = JSON.parse(json)}function handleJS(module) { const js = fs.readFileSync(module.id, "utf-8") let fn = new Function("exports", "myRequire", "module", "__filename", "__dirname", js) let exports = module.exports; // 组装后的函数直接执行即可 fn.call(exports, exports, myRequire, module,module.id,path.dirname(module.id))}Module._resolveFilename = function (filePath) { // 拼接绝对路径,然后去查找,存在即返回 let absPath = path.resolve(__dirname, filePath); let exists = fs.existsSync(absPath); if (exists) return absPath; // 如果不存在,依次拼接.js,.json,.node进行尝试 let keys = Object.keys(Module._extensions); for (let i = 0; i < keys.length; i++) { let currentPath = absPath + keys[i]; if (fs.existsSync(currentPath)) return currentPath; }};Module.prototype.load = function(realPath) { // 获取文件扩展名,交由相对应的方法进行处理 let extname = path.extname(realPath) Module._extensions[extname](this)}
上面对 CommonJs 规范进行了简单的实现,核心解决了作用域的隔离,并提供了 Myrequire 方法进行方法和属性的加载,对于上面的实现,笔者专门有一篇文章《38 行代码带你实现 CommonJS 规范》进行了详细的说明,感兴趣的小伙伴可自行阅读。
9、递归获取对象属性
如果让我挑选一个用的最广泛的设计模式,我会选观察者模式,如果让我挑一个我所遇到的最多的算法思维,那肯定是递归,递归通过将原始问题分割为结构相同的子问题,然后依次解决这些子问题,组合子问题的结果最终获得原问题的答案。
const user = { info: { name: "张三", address: { home: "Shaanxi", company: "Xian" }, },};// obj是获取属性的对象,path是路径,fallback是默认值function get(obj, path, fallback) { const parts = path.split("."); const key = parts.shift(); if (typeof obj[key] !== "undefined") { return parts.length > 0 ? get(obj[key], parts.join("."), fallback) : obj[key]; } // 如果没有找到key返回fallback return fallback;}console.log(get(user, "info.name")); // 张三console.log(get(user, "info.address.home")); // Shaanxiconsole.log(get(user, "info.address.company")); // Xianconsole.log(get(user, "info.address.abc", "fallback")); // fallback
本文转载于:
https://juejin.cn/post/7223938976158957624
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
-
记录--九个超级好用的 Javascript 技巧这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助前言在实际的开发工作过程中,积累了一些常
-
对面食情有独钟 陈奕天疯狂给粉丝安利【对面食情有独钟陈奕天疯狂给粉丝安利】男星们为了保持腹肌,要坚持锻炼,还要控制饮食,陈奕天却很喜欢面
-
杭州热电:目前公司无超超临界机组和虚拟电厂业务_微资讯杭州热电发布异动公告,公司未发现存在对公司股票交易价格可能产生重大影响的媒体报道及市场传闻,也未发现
-
“20宝龙04”盘中临时停牌 跌超22%深交所自5月22日15时15分00秒起对该债券实施临时停牌,于15时27分00秒复牌。截至发稿,“20宝龙04”报62 75
-
发邮件服务器连接超时(发邮件服务器)|环球最资讯1、什么是smtp服务器和pop3服务器?2、使用一些专业的邮件管理软件收发邮件时,需要对邮箱进行配置。最重要
-
华山医院的光子嫩肤怎么样可以用医保吗?医生推荐及挂科攻略一览一、华山医院的光子嫩肤怎么样是当地综合实力特别突出,在当地有着很大的影响力,院内开展了很多的科室,有
-
当前热议!2023中国生物医学工程大会:医工融合发展 创新引领未来2023中国生物医学工程大会:医工融合发展创新引领未来---
-
世界资讯:全聚德集团举办新品体验日为迎接“5·18国际博物馆日”和“5·20全聚德集团庆”,5月17日,全聚德集团特邀热心消费者在北京市爱国主
-
长盈房地产4.7亿元竞得东莞道滘镇蔡白南岛旧改地块地块总占地约11 89万平方米,其中拆除重建区域达5 11万平方米,拆除范围占比约43%。地块更新方向以居住功能
-
【环球新视野】大白菜系统下载官网_大白菜官网首页1、是winpe软件,是修复电脑的一种软件工具,可以做ghost。2、删除开机密码,检测硬件等功能!当电脑系统瘫
-
政府债券和国债有什么不同 区别是什么在金融市场上,债券的种类是很丰富的,其中包括政府债券和国债,两者是有不同的,那么政府债券和国债有什么
-
看热讯:影像无处不在,回忆如何“安”放时隔几年再逛P&E展,感叹日新月异的技术更迭之余,也唏嘘曾经稚嫩的面容渐渐老去。P&E展主题依旧是“影像无
-
钟南山:能覆盖XBB变异株的疫苗很快面世|今日最新据南方plus,5月22日上午,在2023大湾区科学论坛生物医药与健康分论坛上,共和国勋章获得者、中国科学院院
-
天天速看:贵州地质学院怎么样中外合作1、贵州地质学院每周二至周日(节假日不休)9:00—17:00,16:00停止入馆。2、贵州地质学院怎么样贵州省地质博
-
当前消息!夏邑县城关镇开展“5.12全国防灾减灾日”宣传活动河南县域经济网讯(黄波通讯员谢子风)5月12日上午,夏邑县城关镇新兴居委会居民进行了灭火器操作演练。这
-
全球看热讯:共叙乡情友谊 共话合作发展中国徐州网-徐州日报讯(记者季芳)5月21日上午,第三届彭城英才荟徐州经开区专场座谈交流会举行,市委常委
-
三点隐忧,继续演绎均衡!G7会议在半导体等关键行业并没有看到显著加码,好于原来市场预期。最新消息,美光公司在华销售的产品未通过
-
什么水果清火解毒最快关于什么水果清火解毒最快的内容,包含什么水果是去火解毒的吃什么水果降火最快什么水果去火效果最快什么水
-
新修订的《生态环境行政处罚办法》印发_天天速讯本报北京5月21日电(记者寇江泽)生态环境部近日印发新修订的《生态环境行政处罚办法》,在处罚种类、时限
-
领导单独找你谈话,这五种话不能说,否则你会吃大亏领导单独找你谈话,通常是对你在工作中的表现和工作成果提出一些问题或给予肯定,或对你的一些事务进行指导
-
银行卡或现金被吞怎么回事?这篇看完你就明白了,尽快告知家人!|世界球精选在我们生活当中经常会涉及到存取款的问题,为了方便,很多人都会就近去找一个自动提款机来进行相关业务的办
-
我们都活在这个城市里面却为何没有再见面_老婆自愿出轨情夫两次 后来一年多没有见面只是电话联系 是对情夫_最新1、爱和性的需要,也许在你这她没体会到,不离婚可能涉及到孩子!不然你老婆只是一时冲动被别人暂时的性所
-
世界最资讯丨坐着收腹对身体好吗_坐着收腹减肚子1、收腹永远都不会有减肥效果。2、因为减肥减的是脂肪。3、脂肪就是能量保存的一种形式。4、所以想减掉脂肪
-
重生明朝之铁血崇祯 小说(重生明末之我为崇祯)1、重生明末之我为崇祯txt全集小说附件已上传到百度网盘,点击免费下载:很抱歉,回答者上传的附件已失效内
-
(体育)自行车——2023年环四川穿越大凉山会理山地自行车公开赛举行 前沿资讯当日,2023年环四川穿越大凉山会理山地自行车公开赛在凉山彝族自治州会理市举行。300余名国内外选手参与角
-
杭州民生健康药业股份有限公司_关于杭州民生健康药业股份有限公司概略1、杭州民生健康药业股份有限公司于2009年12月14日成立。法定代表人张海军,公司经营范围包括:许可项目:
-
朱民对话瑞·达利欧:硅谷银行危机本身并不是系统性风险,但其本质却是系统性风险 世界快看上证报中国证券网讯在5月21日召开的2023清华五道口全球金融论坛上,国际货币基金组织原副总裁、中国人民银
-
“临时工”戏曲演员月薪仅1500元,为补家用送外卖!何赛飞嘶哑呼喊:戏呢?钱呢? 快报5月18日至24日,《戏聚高平·擂响中华——中国梆子大会》在山西高平喜镇苏庄举办,豫剧名家虎美玲,越剧、
-
C罗儿子马特奥穿巴萨球衣唱跳 梅西家马特奥曾为皇马欢呼 环球微速讯北京时间5月21日消息,近日C罗女友乔治娜在社媒更新了一段视频,在视频中,C罗的二儿子马特奥、大女儿伊娃
-
深圳东莞1对1原画课哪里有学1对1原画课有以下几个优点:1 高度定制化。1对1课程可以根据学员的具体需求和技能水平高度定制,focalpoint明