记录--九个超级好用的 Javascript 技巧
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
前言
在实际的开发工作过程中,积累了一些常见又超级好用的 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) { %>' +
'<a><%this.sports[index]%></a>' +
'<%}%>' +
'<%} else {%>' +
'<p>none</p>' +
'<%}%>';
// 这是我们要拼接的函数字符串
const code = `with(obj) {
var r=[];
r.push("My avorite sports:");
if(this.showSports) {
for(var index in this.sports) {
r.push("<a>");
r.push(this.sports[index]);
r.push("</a>");
}
} else {
r.push("<span>none</span>");
}
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
}
// 不传的话给一个默认值0
function 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) // 6
double() // 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)); // 输出 3
console.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")); // Shaanxi
console.log(get(user, "info.address.company")); // Xian
console.log(get(user, "info.address.abc", "fallback")); // fallback
本文转载于:
https://juejin.cn/post/7223938976158957624
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。

记录--九个超级好用的 Javascript 技巧的更多相关文章
- 记录下项目中常用到的JavaScript/JQuery代码二(大量实例)
记录下项目中常用到的JavaScript/JQuery代码一(大量实例) 1.input输入框监听变化 <input type="text" style="widt ...
- href超级链接里加上javascript代码的,还有target问题
href超级链接里加上javascript代码的,还有target问题 得把target="_blank"去掉才好用,在google浏览器有这个也没事,但是在Ie里有这个就不行了
- 12个非常有用的JavaScript技巧
在这篇文章中,我将分享12个非常有用的JavaScript技巧.这些技巧可以帮助你减少并优化代码. 1) 使用!!将变量转换成布尔类型 有时,我们需要检查一些变量是否存在,或者它是否具有有效值,从而将 ...
- Javascript技巧
Javascript数组转换为CSV格式 首先考虑如下的应用场景,有一个Javscript的字符型(或者数值型)数组,现在需要转换为以逗号分割的CSV格式文件.则我们可以使用如下的小技巧,代码如下: ...
- (译文)12个简单(但强大)的JavaScript技巧(二)
原文链接: 12 Simple (Yet Powerful) JavaScript Tips 其他链接: (译文)12个简单(但强大)的JavaScript技巧(一) 强大的立即调用函数表达式 (什么 ...
- (译文)12个简单(但强大)的JavaScript技巧(一)
原文连接: 12 Simple (Yet Powerful) JavaScript Tips 我将会介绍和解析12个简单但是强大的JavaScript技巧. 这些技巧所有的JavaScript程序员都 ...
- 21个值得收藏的Javascript技巧
1 Javascript数组转换为CSV格式 首先考虑如下的应用场景,有一个Javscript的字符型(或者数值型)数组,现在需要转换为以逗号分割的CSV格式文件.则我们可以使用如下的小技巧,代码如 ...
- JavaScript技巧&写法
原文:JavaScript技巧&写法 JavaScript技巧篇: 1>状态机 var state = function () { this.count = 0; this.fun = ...
- 原生JavaScript技巧大收集
原生JavaScript技巧大收集 地址:http://itindex.net/detail/47244-javascript
- 原生JavaScript技巧大收集100个
原生JavaScript技巧大收集 1.原生JavaScript实现字符串长度截取function cutstr(str, len) { var temp; var icount = 0; var p ...
随机推荐
- FreeSWITCH在session上执行特定dialplan
操作系统 :CentOS 7.6_x64 FreeSWITCH版本 :1.10.9 日常开发中,会遇到需要在已存在的session上执行特定拨号方案的情况,今天整理下这方面的内容,我将从以下几个方面进 ...
- 跨界协作:借助gRPC实现Python数据分析能力的共享
gRPC是一个高性能.开源.通用的远程过程调用(RPC)框架,由Google推出.它基于HTTP/2协议标准设计开发,默认采用Protocol Buffers数据序列化协议,支持多种开发语言. 在gR ...
- 从零开始的微信小程序入门教程(四),理解小程序事件与冒泡机制
壹 ❀ 引 我在之前初识WXML与数据绑定两篇文章中,介绍了小程序静态模板与样式相关概念,以及小程序几种常用数据绑定方式,在知道这些知识后,我们可以写一些不算复杂的小程序页面,并能将一些自定义的数据渲 ...
- NC201985 立方数
题目链接 题目 题目描述 对于给定的正整数 N,求最大的正整数 A,使得存在正整数 B,满足 \(A^3B=N\) 输入包含 T 组数据,1≤T≤10,000:\(1≤N≤10^{18}\) 输入描述 ...
- 斐讯K3C改散热
斐讯K3C改散热 斐讯K3C日常使用还是不错的,就是日常的温度还是比较高的,不过冬天用来当暖手宝还是不错的. 这个改散热的方法是跟贴吧老哥学的,不得不说贴吧老哥还是牛皮,原贴在这,我当时拍的照片不够, ...
- java+文件实现的超市管理系统
一.需求 1.使用java语言实现系统 2.数据存储使用io读写文件 3.超市的商品管理+销售功能 二.效果 商品列表 商品增删改查 购买 三.说明 1.开发工具/技术 java eclipse 2 ...
- 03-Redis系列之-高级用法详解
慢查询 生命周期 我们配置一个时间,如果查询时间超过了我们设置的时间,我们就认为这是一个慢查询. 慢查询发生在第三阶段 客户端超时不一定慢查询,但慢查询是客户端超时的一个可能因素 两个配置 slowl ...
- 2.Go 的指针
Go的指针 1. 变量内存地址 var age = 18 // & + 变量 = 变量内存地址 fmt.Println("age:",&age) 2. 指针变量 / ...
- 【LeetCode字符串#01】反转字符串I+II
反转字符串 力扣题目链接(opens new window) 编写一个函数,其作用是将输入的字符串反转过来.输入字符串以字符数组 char[] 的形式给出. 不要给另外的数组分配额外的空间,你必须原地 ...
- macOS Monterey 与以下电脑兼容下载操作流程解析
有时在开发iOS应用时我们时常遇到各种情况,比如手机升级了Xcode不支持这时候需要安装xcode但是xcode需要依奈相应系统本人小编整理了这种情况无法解决问题. 首相打开苹果标志进入到下面界面 进 ...
