Pendings

手写js高级知识点

实现原生的 AJAX 请求 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 const ajax = { get(url, fn) { const xhr = new XMLHttpRequest(); xhr.open("GET", url, true); // 第三个参数异步与否 xhr.onreadystatechange = function () { if (xhr.readyState === 4) { fn(xhr.responeText); } }; xhr.send(); }, post(url, data, fn) { const xhr = new XMLHttpRequest(); xhr.open("POST", url, true); xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { fn(xhr.responeText); } }; xhr.send(data); }, }; 手写 new 的过程 # js 复制 1 2 3 4 5 6 7 8 9 function myNew(fn, ...args) { const obj = {}; obj.__proto__ = fn.prototype; fn.apply(obj, args); return obj; } instanceof 关键字 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 function instanceOf(father, child) { const fp = father.prototype; var cp = child.__proto__; while (cp) { if (cp === fp) { return true; } cp = cp.__proto__; } return false; } 实现防抖函数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 function debounce(fn, delay = 500) { let timer; return function () { if (timer) { clearTimeout(timer); } const args = arguments; timer = setTimeout(() => { fn.apply(this, args); // 改变this指向为调用debounce所指的对象 }, delay); }; } 实现节流函数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 function throttle(fn, delay = 200) { let flag = true; return function () { if (!flag) return; flag = false; const args = arguments; setTimeout(() => { fn.apply(this, args); flag = true; }, delay); }; } 实现数组去重 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 // 第一种:Map记录 function quchong1(arr) { const newArr = []; arr.reduce((pre, next) => { if (!pre.has(next)) { pre.set(next, 1); newArr.push(next); } return pre; }, new Map()); return newArr; } // 第二种:Set去重 function quchong2(arr) { return [...new Set(arr)]; } 用 setTimeout 实现 setInterval # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function mySetTimout(fn, delay) { let timer = null; const interval = () => { fn(); timer = setTimeout(interval, delay); }; setTimeout(interval, delay); return { cancel: () => { clearTimeout(timer); }, }; } // 测试 const { cancel } = mySetTimout(() => console.log(888), 1000); setTimeout(() => { cancel(); }, 4000); 用 setInterval 实现 setTimeout # js 复制 1 2 3 4 5 6 7 8 9 function mySetInterval(fn, delay) { const timer = setInterval(() => { fn(); clearInterval(timer); }, delay); } // 测试 mySetInterval(() => console.log(888), 1000); 实现一个 compose 函数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 function fn1(x) { return x + 1; } function fn2(x) { return x + 2; } function fn3(x) { return x + 3; } function fn4(x) { return x + 4; } const a = compose(fn1, fn2, fn3, fn4); console.log(a); console.log(a(1)); // 1+2+3+4=11 // 实现如下: function compose(...fn) { if (fn.length === 0) return (num) => num; if (fn.length === 1) return fn[0]; return fn.reduce((pre, next) => { return (num) => { return next(pre(num)); }; }); } 实现一个科里化函数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 const add = (a, b, c) => a + b + c; const a = currying(add, 1); console.log(a(2, 3)); // + + 3=6 // 实现如下: function currying(fn, ...args1) { // 获取fn参数有几个 const length = fn.length; let allArgs = [...args1]; const res = (...arg2) => { allArgs = [...allArgs, ...arg2]; // 长度相等就返回执行结果 if (allArgs.length === length) { return fn(...allArgs); } else { // 不相等继续返回函数 return res; } }; return res; } // 测试: const add = (a, b, c) => a + b + c; const a = currying(add, 1); console.log(a(2, 3)); 实现一个 LRU 缓存函数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 // 实现如下: class LRUCache { constructor(size) { this.size = size; this.cache = new Map(); } get(key) { const hasKey = this.cache.has(key); if (hasKey) { const val = this.cache.get(key); this.cache.delete(key); this.cache.set(key, val); return val; } else { return -1; } } put(key, val) { const hasKey = this.cache.has(key); if (hasKey) { this.cache.delete(key); } this.cache.set(key, val); if (this.cache.size > this.size) { this.cache.delete(this.cache.keys().next().value); } } } 简单实现 发布订阅模式 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 class EventEmitter { constructor() { this.cache = {}; } on(name, fn) { const tasks = this.cache[name]; if (tasks) { this.cache[name].push(fn); } else { this.cache[name] = [fn]; } } off(name, fn) { const tasks = this.cache[name]; if (task) { const index = tasks.findIndex((item) => item === fn); if (index >= 0) { this.cache[name].splice(index, 1); } } } emit(name, ...args) { // 复制一份。防止回调里继续on,导致死循环 const tasks = this.cache[name].slice(); if (tasks) { for (let fn of tasks) { fn(...args); } } } once(name, cb) { function fn(...args) { cb(args); this.off(name, fn); } this.on(name, fn); } } 实现 JSON.parse # js 复制 1 2 3 function parse(json) { return eval("(" + json + ")"); } 将 DOM 转化成树结构对象 # html 复制 1 2 3 4 5 6 7 <div> <span></span> <ul> <li></li> <li></li> </ul> </div> js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 // 将上方的DOM转化为下面的树结构对象 { tag: 'DIV', children: [ { tag: 'SPAN', children: [] }, { tag: 'UL', children: [ { tag: 'LI', children: [] }, { tag: 'LI', children: [] } ] } ] } // 实现如下: function dom2tree(dom) { const obj = {} obj.tag = dom.tagName obj.children = [] dom.childNodes.forEach(child => obj.children.push(dom2tree(child))) return obj } 将树结构转换为 DOM # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 // 树结构 {tag: 'DIV', children: [ { tag: 'SPAN', children: [] }, { tag: 'UL', children: [ { tag: 'LI', children: [] }, { tag: 'LI', children: [] } ] } ] } // 实现如下: // 真正的渲染函数 function _render(vnode) { // 如果是数字类型转化为字符串 if (typeof vnode === "number") { vnode = String(vnode); } // 字符串类型直接就是文本节点 if (typeof vnode === "string") { return document.createTextNode(vnode); } // 普通DOM const dom = document.createElement(vnode.tag); if (vnode.attrs) { // 遍历属性 Object.keys(vnode.attrs).forEach((key) => { const value = vnode.attrs[key]; dom.setAttribute(key, value); }); } // 子数组进行递归操作 vnode.children.forEach((child) => dom.appendChild(_render(child))); return dom; } html 复制 1 2 3 4 5 6 7 8 <!-- 转换后的dom --> <div> <span></span> <ul> <li></li> <li></li> </ul> </div> 判断一个对象有环引用 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 var obj = { a: { c: [1, 2], }, b: 1, }; obj.a.c.d = obj; console.log(cycleDetector(obj)); // true // 实现思路:用一个数组存储每一个遍历过的对象,下次找到数组中存在,则说明环引用 function cycleDetector(obj) { const arr = [obj]; let flag = false; function cycle(o) { const keys = Object.keys(o); for (const key of keys) { const temp = o[key]; if (typeof temp === "object" && temp !== null) { if (arr.indexOf(temp) >= 0) { flag = true; return; } arr.push(temp); cycle(temp); } } } cycle(obj); return flag; } 计算一个对象的层数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 const obj = { a: { b: [1] }, c: { d: { e: { f: 1 } } }, }; console.log(loopGetLevel(obj)); // 4 // 实现如下: function loopGetLevel(obj) { var res = 1; function computedLevel(obj, level) { var level = level ? level : 0; if (typeof obj === "object") { for (var key in obj) { if (typeof obj[key] === "object") { computedLevel(obj[key], level + 1); } else { res = level + 1 > res ? level + 1 : res; } } } else { res = level > res ? level : res; } } computedLevel(obj); return res; } 对象的扁平化 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 const obj = { a: { b: 1, c: 2, d: { e: 5 }, }, b: [1, 3, { a: 2, b: 3 }], c: 3, }; flatten(obj); // 结果返回如下 // { // 'a.b': 1, // 'a.c': 2, // 'a.d.e': 5, // 'b[0]': 1, // 'b[1]': 3, // 'b[2].a': 2, // 'b[2].b': 3 // c: 3 // } // 实现如下: const isObject = (val) => typeof val === "object" && val !== null; function flatten(obj) { if (!isObject(obj)) return; const res = {}; const dfs = (cur, prefix) => { if (isObject(cur)) { if (Array.isArray(cur)) { cur.forEach((item, index) => { dfs(item, `${prefix}[${index}]`); }); } else { for (let key in cur) { dfs(cur[key], `${prefix}${prefix ? "." : ""}${key}`); } } } else { res[prefix] = cur; } }; dfs(obj, ""); return res; } // 测试 console.log(flatten(obj)); 实现(a == && a == && a == 3)为 true # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 // 第一种方法 var a = { i: 1, toString: function () { return a.i++; }, }; console.log(a == 1 && a == 2 && a == 3); // true // 第二种方法 var a = [1, 2, 3]; a.join = a.shift; console.log(a == 1 && a == 2 && a == 3); // true // 第三种方法 var val = 0; Object.defineProperty(window, "a", { get: function () { return ++val; }, }); console.log(a == 1 && a == 2 && a == 3); // true 实现限制并发的 Promise 调度器 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 addTask(1000, "1"); addTask(500, "2"); addTask(300, "3"); addTask(400, "4"); // 的输出顺序是:4 // 整个的完整执行流程: // 一开始1,2两个任务开始执行 // 500ms时,2任务执行完毕,输出2,任务3开始执行 // 800ms时,3任务执行完毕,输出3,任务4开始执行 // 1000ms时,1任务执行完毕,输出1,此时只剩下4任务在执行 // 1200ms时,4任务执行完毕,输出4 // 实现如下: class Scheduler { constructor(limit) { this.queue = []; this.limit = limit; this.count = 0; } add(time, order) { const promiseCreator = () => { return new Promise((resolve, reject) => { setTimeout(() => { console.log(order); resolve(); }, time); }); }; this.queue.push(promiseCreator); } taskStart() { for (let i = 0; i < this.limit; i++) { this.request(); } } request() { if (!this.queue.length || this.count >= this.limit) return; this.count++; this.queue .shift()() .then(() => { this.count--; this.request(); }); } } // 测试 const scheduler = new Scheduler(2); const addTask = (time, order) => { scheduler.add(time, order); }; addTask(1000, "1"); addTask(500, "2"); addTask(300, "3"); addTask(400, "4"); scheduler.taskStart(); 实现 lazyMan 函数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 // 实现一个LazyMan,可以按照以下方式调用: LazyMan(“Hank”) /** 输出: * Hi! This is Hank! */ LazyMan(“Hank”).sleep(10).eat(“dinner”) /** 输出: * Hi! This is Hank! * //等待10秒.. * Wake up after 10 * Eat dinner~ */ LazyMan(“Hank”).eat(“dinner”).eat(“supper”) /** 输出: * Hi This is Hank! * Eat dinner~ * Eat supper~ */ LazyMan(“Hank”).eat(“supper”).sleepFirst(5) /** 输出: * //等待5秒 * Wake up after 5 * Hi This is Hank! * Eat supper */ // 实现如下: class _LazyMan { constructor(name) { this.tasks = [] const task = () => { console.log(`Hi! This is ${name}`) this.next() } this.tasks.push(task) setTimeout(() => { this.next() }, 0) } next() { const task = this.tasks.shift() task && task() } sleep(time) { this.sleepWrapper(time, false) return this } sleepFirst(time) { this.sleepWrapper(time, true) return this } sleepWrapper(time, first) { const task = () => { setTimeout(() => { console.log(`Wake up after ${time}`) this.next() }, time * 1000) } if (first) { this.tasks.unshift(task) } else { this.tasks.push(task) } } eat(food) { const task = () => { console.log(`Eat ${food}`); this.next(); }; this.tasks.push(task); return this; } } // 测试 const lazyMan = (name) => new _LazyMan(name) lazyMan('Hank').sleep(1).eat('dinner') lazyMan('Hank').eat('dinner').eat('supper') lazyMan('Hank').eat('supper').sleepFirst(5) 实现 add 函数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 add(1)(2)(3)()=6 add(1,2,3)(4)()=10 function add(...args1) { let allArgs = [...args1] function fn(...args2) { if (!args2.length) return fn.toString() allArgs = [...allArgs, ...args2] return fn } fn.toString = function () { return allArgs.reduce((pre, next) => pre + next) } return fn } // 测试 console.log(add(1)(2)(3)()) console.log(add(1, 2)(3)()) 实现一个合格的深拷贝 # 深拷贝有这 个段位? ...

2024-06-16 · 15 分钟 · 7332 字 · Linlccc

ES6 常用代码块

ES个经常使用的技巧 # 打乱数组顺序 # js 复制 1 2 3 4 let arr = ["😄", 67, true, false, "55"]; arr = arr.sort(() => 0.5 - Math.random()); console.log(arr); // [ '😄', '55', 67, false, true ] 删除数字之外的所有字符 # js 复制 1 2 3 4 const str = "xieyezi is so hansome 223333"; const numbers = str.replace(/\D/g, ""); console.log(numbers); // 2321395994223333 反转字符串或者单词 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 const sentence = "xieyezi js so handsome, lol."; const reverseSentence = reverseBySeparator(sentence, ""); console.log(reverseSentence); // .lol ,emosdnah os sj izeyeix const reverseEachWord = reverseBySeparator(reverseSentence, " "); console.log(reverseEachWord); // izeyeix sj os ,emosdnah .lol function reverseBySeparator(string, separator) { return string.split(separator).reverse().join(separator); } 将十进制转换为二进制文件或十六进制数 # js 复制 1 2 3 const num = 45; num.toString(2); num.tostring(16); 合并多个对象 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 const city = { name: "Chongqing", population: "1,234,567,890", }; const location = { longitude: "116.4", latitude: "39.9", }; const fullCity = { ...city, ...location }; console.log(fullCity); // { // name: 'Chongqing', // population: '1,234,567,890', // longitude: '116.4', // latitude: '39.9' // } === 和 == 的区别 # js 复制 1 2 3 4 5 6 7 8 9 // == -> 类型转换 (浅比较) // === -> 无类型转换 (严格比较) 0 == false; // true 0 === false; // false 1 == "1"; // true 1 === "1"; // false null == undefined; // true null === undefined; // false 解构赋值 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 const forest = { location: "Sweden", animals: 3, animalsTypes: ["Lions", "Tigers", "Bears"], }; const { location, animals, animalsTypes } = forest; const [lions, tigers, bears] = animalsTypes; console.log(location); // Sweden console.log(animals); // 3 console.log(lions); // Lions console.log(tigers); // Tigers console.log(bears); // Bears 交换变量的值 # js 复制 1 2 3 4 let bears = "bears"; let tigers = ("tigers"[(bears, tigers)] = [tigers, bears]); console.log(bears); // tigers console.log(tribes); // bears 判断回文字符串 # js 复制 1 2 3 4 5 6 const isRevervse = (str1, str2) => { const normalize = (str) => str.toLowerCase().normalize("NFD").split("").reverse().join(""); return normalize(str1) === str2; }; console.log(isRevervse("anagram", "margana")); // true console.log(isRevervse("rac", "car")); // true 回文字符串: 正着写和反着写都一样的字符串 (特别感谢 @浮生阁阁主 勘误) ...

2024-05-07 · 3 分钟 · 1099 字 · Linlccc

Nginx基础配置

具体配置可见 # NGINX 配置 NGINX 入门学习笔记 NGINX 备忘清单 Web 服务器 # nginx 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # http server { listen 80; server_name _; location / { root /data; index index.html index.htm; } } # https server { listen 443 ssl; server_name _; ssl_certificate /path/to/certificete.crt; ssl_certificate_key /path/to/private-key.key; location / { root /data; index index.html index.htm; } } 反向代理 # nginx 复制 1 2 3 4 5 6 7 8 9 server { listen 80; server_name _; location / { proxy_pass http://192.168.241.11; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } 负载均衡 # nginx 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 upstream web { ip_hash #会话保持 server 192.168.241.22; server 192.168.241.23; } server { listen 80; server_name _; location / { proxy_pass http://web; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } } 重定向 # nginx 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 老域名跳转新域名 server { listen 80; server_name old.cxk.cn; location / { rewrite ^/(.*)$ https://new.cxk.cn/$1; } } # 路径重定向 server { listen 80; server_name old.cxk.cn; location / { rewrite ^/old.cxk.cn/(.*)$ /new-path/$1; } } 防盗链 # nginx 复制 1 2 3 4 5 6 7 8 9 10 server { listen 80; server_name _; location ~* \.(gif|jpg|jpeg|png) { valid_referers none blocked *.cxk.cn; if ($invalid_referer) { return 403; } } } 手机端重定向 PC # nginx 复制 1 2 3 4 5 6 7 8 9 server { listen 80; server_name _; location / { if ($http_user_agent ~* '(android|iphone|ipad)') { return ^/(.*)$ https://yd.cxk.cn/$1; } } } 基于请求路径转发不同服务 # nginx 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 server { listen 80; server_name _; location / { proxy_pass http://192.168.241.11; proxy_set_header Host $host; proxy_set_header X-Real_IP $remote_addr; } location /beijing { proxy_pass http://192.168.241.22; proxy_set_header Host $host; proxy_set_header X-Real_IP $remote_addr; } location /nanjing { proxy_pass http://192.168.241.23; proxy_set_header Host $host; proxy_set_header X-Real_IP $remote_addr; } }

2024-05-05 · 1 分钟 · 408 字 · Linlccc

Linux 命令大全

系统指令 # Bash 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # 显示系统信息:内核版本、机器类型等 uname # 显示正在运行的Linux内核的发行版本 uname -r # 显示当前时间、系统运行时间、用户和负载平均值 uptime # 显示系统主机名 hostname # 显示当前主机的ip地址 hostname -i # 查看系统最近一次的重启时间以及重启之前的系统登录信息 last reboot # 显示当前日期和时间 date # 设置系统时间与日期 timedatectl # 快速查看当前/指定年份日历 cal # 显示目前登入系统的用户信息 w # 显示当前用户的用户名 whoami # 显示名为"username"的用户的信息 finger username 文件命令 # Bash 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 # 以长格式列出所有文件的详细信息 ls -al # 显示当前工作目录的路径 pwd # 创建一个名为 dir的新目录 mkdir dir1 # 删除名为 file的文件 rm file1 # 强制删除名为 file的文件 rm -f file2 # 递归删除目录 dir及其内容 rm -r dir1 # 强制删除目录 dir及其内容 rm -rf dir1 # 复制 file1,创建或覆盖 file2 cp filefile2 # 将 dir复制到 dir2,包括子目录 cp -r dirdir2 # 将 file重命名或移动到 file2 mv filefile2 # 创建名为 linkName 到 fileName 的符号链接 ln -s /oath/to/fileName linkName # 创建一个名为 file的空文件 touch file1 # 创建/覆盖 file1,等得标准输入 cat > file1 # 逐页显示们 file的内容 more file1 # 显示 file的前十行 head file1 # 显示 file的最后十行 tail file1 # 使用对称密码对 file进行加密,需要提供密码短语 gpg -c file1 # 解密 file2.gpg,提示输入密码 gpg file2.gpg # 统计文件中的字数、行数和字符数 wc # 使用管道或文件提供的参数执行命令 xargs 用户管理 # Bash 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 # 显示用户的UID、GID、组 id # 显示最后登录用户的列表 last # 显示当前登录的用户 who # 创建一个名为 Admin 的新用户组 groupadd admin # 创建一个名为 Sam 的新用户组 adduser Sam # 删除名为 Sam 的用户 userdel Sam # 修改现有用户的属性 usermod 硬件 # Bash 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 # 内核会将开机过程信息存储在环形缓冲区中 dmesg # 显示 CPU 的详细信息 cat/proc/cpuinfo # 显示详细的系统内存使用信息 cat/proc/meminfo # 列出系统的详细硬件配置 lshw # 列出所有可用的块设备的信息 lsblk # 显示系统内存使用情况 free -m # 以树状格式详细显示 PCI 设备信息 lspci -tv # 以树状格式详细显示 USB 设备信息 lsusb -tv # 显示系统 BIOS 中的硬件信息 dmidecode # 显示磁盘 /dev/sda 的信息 hdparm -i /dev/sda # 用于检查设备 /dev/sda 是否存在坏块,并显示检测进度 badblocks -s /dev/sda 登录 # Bash 复制 1 2 3 4 5 6 7 8 # 向指定主机名发起 SSH 连接 ssh user@hostname # 使用特定端口发起 SSH 连接 ssh -p portNumber user@hostname # 通过 telnet 连接到主机的默认端口 23 Connect to the host via telnet default port 23 # 通过l elnet 默认端口23连接到主机 telnet host 安装包 # Bash 复制 1 2 3 4 5 6 7 8 # 使用 RPM 包管理器安装 pkgName.rpm 包 rpm -i pkgName.rpm # 卸载指定的 RPM 包 rpm -e pkgName # 使用 DNF 安装指定的包, dnf install pkgName # 使用 Pacman 安装指定的包 pacman -S 安装源(编译) # Bash 复制 1 2 3 4 5 6 # 检查系统兼容性并生成用于软件安装的 makefile ./configure # 按照 makefoile 中的指令编译代码 make # 将编译后的代码安装到指定的系统位置 make install 目录遍历 # Bash 复制 1 2 3 4 5 6 # 切换到父目录 cd .. # 将当前目录更改为用户的主目录 cd # 将当前目录更改为"/mnt" cd /mnt 流程相关 # Bash 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 # 显示当前进程的快照 ps # 显示运行中的 tolnet 进程的详细信息 ps aux | grep telnet # 显示进程的内存映射 pmap # 显示运行任务的动态实时视图 top # 终止具有 PID 的进程 kill 1234 # 终止所有名为'proc' 的进程 killall proc # 终止具有指定名称的进程 pkill processName # 在后台恢复暂停的作业 bg # 将暂停的作业带到前台 fg # 将作业编号为'n' 的作业移到前台运行 fg n # 列出所有打开的文件和进程 lsof # 更改具有给定 PID 的进程的优先级 renice 19 PID # 显示firefox 进程的进程ID pgrep firefox # 显示运行中的进程树 pstree 网络 # Bash 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 # 显示所有网络接口及其信息 ip addr show # 将 IP 地址 192.168.0.分配给eth0接口 ip address add 192.168.0.1/dev eth0 # 显示网络接口及其配置 ifconfig # 发送 ICMP 数据包,测量与 host 之问的往返时间 ping host # 检索并显示域名的注册信息 whois domain # 查询 DNS,提供域名的 DNS 信息 dig domain # 将 IP 地址解析为主机名,显示 DNS 信息 dig -x host # 对域名进行 IP 查找 host gexample.com # 从指定路径下载文件 wget flePath # 显示各种与网络相关的信息和统计数据 netstat 磁盘使用情况 # Bash 复制 1 2 3 4 5 6 7 8 9 10 11 12 # 显示所有已挂载文件系统可读的磁盘空问使用情况 df -h # 显示所有已挂载文件系统的 inode 使用情况 df -i # 列出所有驱动器上的分区及其信息 fdisk -l # 显示 /dir目录的总磁盘使用大小的摘要,以可读方式呈现 du -sh/dir1 # 显示所有已挂载文件系统及其属性的列表 findmnt # 将设备挂载到指定的文件系统挂载点上 mount devicePath mountPoint 压缩/存档 # Bash 复制 1 2 3 4 5 6 7 8 # 创建一个名为 backup.tar 的 tar 归档文件,其中包含 /home/ubuntu 目录的内容 tar -cf backup.tar/home/ubuntu # 从 backup.tar 归档文件中提取文件 tar -xf backup.tar # 创建一个名为 backup.tar.gz 的压缩 tar 归档文件,其中包含 /home/ubuntu 目录的内容 tar -zcvf backup.tar.gz/home/ubuntu # 将文件 file压缩为 file1.gz,并删除原始文件 gzip file1 日志文件传输 # Bash 复制 1 2 3 4 5 6 # 将们 file.txt 复制到远程主机的指定目录 scp file.txt remoteuser@remoteHost:/remote/diroctory # 将源目录的内容同步到目标目录,保留属性 rsync -a /home/ubuntu/backup/ # 同步本地目录到远程,保留属性 rsync -a /var/www/web/user@remoteHost:/backup/webBackup/ 搜索 # Bash 复制 1 2 3 4 5 6 7 8 9 10 # 在文件中搜索给定的模式 grep pattern file # 在 dir目录及其子目录中递归搜索指定的 pattern grep -r pattern dir1 # 使用预建的数据库查找名为 file 的文件 locate file # 递归搜索 /home 目录中名为 index 的文件 find /homeName index # 在 /home 目录中查找大小超过 10000k 的文件 find /homeSize +10000k 文件权限 # Bash 复制 1 2 3 4 5 6 7 8 # 设置文件/data的权限为所有者读/写,组和其他人只读 chmod 644 /data/ # 将目录 /dir的权限设置为对所有者可读可写/可执行,对组和其他用户可读/可执行 chmod 755 /dir1 # 将文件 filename 的所有者更改为 bob 并将所属组更改为 devops chown bob:devops filename # 更改目录的所有者和所属组 chown ownername

2024-05-05 · 5 分钟 · 2242 字 · Linlccc

VsCode 常用扩展推荐

基础扩展 # Chinese (Simplified) # 插件 txt 复制 1 VS Code 的中文(简体)语言包 vscode-icons # 插件 txt 复制 1 图标 XML,Json,TOML 扩展 # JSON Crack # 插件 txt 复制 1 Json 数据可视化 Even Better TOML # 插件 txt 复制 1 TOML 语言支持 Markdown All in One # 插件 txt 复制 1 Markdown 快捷键等支持 Markdown Preview Enhanced # 插件 txt 复制 1 Markdown 预览 markdownlint # 插件 txt 复制 1 Markdown 语法检查 C# 扩展 # .NET Install Tool # 插件 txt 复制 1 此扩展安装和管理不同版本的 .NET SDK 和运行时 C# # 插件 依赖 .NET Install Tool txt 复制 1 C# 的基本语言支持 C# Dev Kit # 插件 依赖 .NET Install Tool C# txt 复制 1 2 3 帮助 C# 开发人员更快、更快速地编写、调试和维护其代码 ps: 此扩展依赖以上两个扩展,直接安装该扩展即可 Js 扩展 # EsLint # 插件 中文官网 规则参考 txt 复制 1 2 3 4 5 6 JavaScript 语法检查工具 规则配置: "off" 或 - 关闭规则 "warn" 或 - 启用并视作警告(不影响退出) "error" 或 - 启用并视作错误(触发时退出代码为 1) 常用规则 json 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 rules: { // 箭头函数的参数始终使用括号 "arrow-parens": ["error", "always"], // 大括号与代码不在同一行 "brace-style": ["error", "1tbs", { "allowSingleLine": true }], // 多行末尾逗号 "comma-dangle": ["error", "always-multiline"], // 逗号前后的空格 "comma-spacing": "error", // 缩进为2个空格,switch case的缩进为1个空格 "indent": ["error", 2, { "SwitchCase": 1 }], // 在JSX中使用双引号 "jsx-quotes": ["error", "prefer-double"], // 使用双引号 "quotes": ["error", "double"], // 使用分号 "semi": ["error", "always"], // 大括号内始终有空格 "object-curly-spacing": ["error", "always"], // 对象属性引号根据需要添加 "quote-props": ["error", "as-needed"], // 函数圆括号前不添加空格 "space-before-function-paren": ["error", "never"], // 最大行长度为80个字符 "max-len": ["error", { "code": 80 }] } Regex Previewer # 插件 txt 复制 1 2 正则表达式测试 在js文件中输入正则表达式按下 Ctrl+Alt+M` 即可快速测试 Turbo Console Log # 插件 txt 复制 1 在变量上按下 Ctrl+Alt+L` 快速添加 console.log 代码 Path Intellisense # 插件 txt 复制 1 自动完成路径文件名 Vue - Official # 插件 txt 复制 1 Vue 支持 Web # Live Server # 插件 txt 复制 1 启动具有静态和动态页面实时重新加载功能的开发本地服务器 Thunder Client # 插件 txt 复制 1 API 客户端 格式化扩展 # Prettier # 插件 官网 txt 复制 1 支持 JavaScript · TypeScript · Flow · JSX · JSON · CSS · SCSS · Less · HTML · Vue · Angular HANDLEBARS · Ember · Glimmer · GraphQL · Markdown · YAML 代码格式化 常用规则 json 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 // ps: 以下规则可在 .prettierrc.json 文件中配置,在 prettierrc 中时不能有注释 { // 是否始终在箭头函数的参数周围使用括号 "arrowParens": "always", // 是否大括号与代码在同一行上 "bracketSameLine": false, // 是否在大括号内添加空格 "bracketSpacing": true, // 是否使用分号作为语句结束符 "semi": true, // 是否启用实验性的三元运算符格式化 "experimentalTernaries": false, // 是否使用单引号 "singleQuote": false, // 在JSX中是否使用单引号 "jsxSingleQuote": false, // 对象属性是否需要引号 "quoteProps": "as-needed", // 是否在多行对象、数组末尾添加逗号 "trailingComma": "all", // 是否将JSX元素的每个属性放在单独的行上 "singleAttributePerLine": false, // HTML空白符的敏感度 "htmlWhitespaceSensitivity": "css", // 是否在Vue文件中缩进脚本和样式 "vueIndentScriptAndStyle": false, // 是否在Markdown文件中保留文本换行符 "proseWrap": "preserve", // 是否在文件开头插入格式化的特殊字符串以启用格式化 "insertPragma": false, // 每行代码的最大字符数 "printWidth": 80, // 是否要求格式化的文件包含特殊的格式化字符串才会被格式化 "requirePragma": false, // 制表符的宽度 "tabWidth": 2, // 是否使用制表符而不是空格进行缩进 "useTabs": false, // 嵌入式语言的格式化方式 "embeddedLanguageFormatting": "auto" } Ai 扩展 # Fitten Code # 插件 txt 复制 1 AI 代码助手 Hugo 扩展 # Hugo Snippets # 插件 txt 复制 1 2 Hugo 代码片段 使用时键入 h- 即可ktivai 代码片段 Hugo Themer # 插件 txt 复制 1 2 鼠标悬停在 partial 或 partialCached 引用上时,显示引用的部分文件的完整路径 按 F跳转到引用的部分文件

3 分钟 · 1263 字 · Lin

常用js

防抖 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 function debounce(fn, delay) { let timer; return function (...args) { timer && clearTimeout(timer); timer = setTimeout(() => fn.apply(this, args), delay); }; } // 测试 function task(arg) { console.log("run task" + arg); } const debounceTask = debounce(task, 1000); window.addEventListener("scroll", () => debounceTask(11)); 节流 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function throttle(fn, delay) { let last = 0; return function (...args) { const now = Date.now(); if (now - last < delay) return; last = now; fn.apply(this, args); }; } // 测试 function task() { console.log("run task"); } const throttleTask = throttle(task, 1000); window.addEventListener("scroll", throttleTask); 深拷贝 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function deepClone(obj, cache = new WeakMap()) { if (typeof obj !== "object") return obj; // 普通类型,直接返回 if (obj === null) return obj; if (cache.get(obj)) return cache.get(obj); // 防止循环引用,程序进入死循环 if (obj instanceof Date) return new Date(obj); if (obj instanceof RegExp) return new RegExp(obj); // 找到所属原型上的constructor,所属原型上的constructor指向当前对象的构造函数 let cloneObj = new obj.constructor(); cache.set(obj, cloneObj); // 缓存拷贝的对象,用于处理循环引用的情况 for (let key in obj) { if (obj.hasOwnProperty(key)) { cloneObj[key] = deepClone(obj[key], cache); // 递归拷贝 } } return cloneObj; } // 测试 const obj = { name: "Jack", address: { x: 100, y: 200 } }; obj.a = obj; // 循环引用 const newObj = deepClone(obj); console.log(newObj.address === obj.address); // false 手写 Promise # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 class MyPromise { constructor(executor) { // executor执行器 this.status = "pending"; // 等待状态 this.value = null; // 成功或失败的参数 this.fulfilledCallbacks = []; // 成功的函数队列 this.rejectedCallbacks = []; // 失败的函数队列 const that = this; function resolve(value) { // 成功的方法 if (that.status === "pending") { that.status = "resolved"; that.value = value; that.fulfilledCallbacks.forEach((myFn) => myFn(that.value)); //执行回调方法 } } function reject(value) { //失败的方法 if (that.status === "pending") { that.status = "rejected"; that.value = value; that.rejectedCallbacks.forEach((myFn) => myFn(that.value)); //执行回调方法 } } try { executor(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { if (this.status === "pending") { // 等待状态,添加回调函数到成功的函数队列 this.fulfilledCallbacks.push(() => { onFulfilled(this.value); }); // 等待状态,添加回调函数到失败的函数队列 this.rejectedCallbacks.push(() => { onRejected(this.value); }); } if (this.status === "resolved") { // 支持同步调用 console.log("this", this); onFulfilled(this.value); } if (this.status === "rejected") { // 支持同步调用 onRejected(this.value); } } } // 测试 function fn() { return new MyPromise((resolve, reject) => { setTimeout(() => { if (Math.random() > 0.6) { resolve(1); } else { reject(2); } }, 1000); }); } fn().then( (res) => { console.log("res", res); // res 1 }, (err) => { console.log("err", err); // err 2 }, ); 异步控制并发数 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 function limitRequest(urls = [], limit = 5) { return new Promise((resolve, reject) => { const len = urls.length; let count = 0; // 当前进行到第几个任务 const start = async () => { const url = urls.shift(); // 从数组中拿取第一个任务 if (url) { try { await axios.post(url); if (count == len - 1) { // 最后一个任务 resolve(); } else { count++; // 成功,启动下一个任务 start(); } } catch (e) { count++; // 失败,也启动下一个任务 start(); } } }; // 启动limit个任务 while (limit > 0) { start(); limit -= 1; } }); } // 测试 limitRequest(["http://xxa", "http://xxb", "http://xxc", "http://xxd", "http://xxe"]); 继承 # ES继承 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 function Parent(name) { this.name = name; } Parent.prototype.eat = function () { console.log(this.name + " is eating"); }; function Child(name, age) { Parent.call(this, name); this.age = age; } Child.prototype = Object.create(Parent.prototype); Child.prototype.constructor = Child; // 测试 let xm = new Child("xiaoming", 12); console.log(xm.name); // xiaoming console.log(xm.age); // 12 xm.eat(); // xiaoming is eating ES继承 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 class Parent { constructor(name) { this.name = name; } eat() { console.log(this.name + " is eating"); } } class Child extends Parent { constructor(name, age) { super(name); this.age = age; } } // 测试 let xm = new Child("xiaoming", 12); console.log(xm.name); // xiaoming console.log(xm.age); // 12 xm.eat(); // xiaoming is eating 数组排序 # sort 排序 # js 复制 1 2 3 4 5 6 7 8 9 // 对数字进行排序,简写 const arr = [3, 2, 4, 1, 5]; arr.sort((a, b) => a - b); console.log(arr); // [1, 2, 3, 4, 5] // 对字母进行排序,简写 const arr = ["b", "c", "a", "e", "d"]; arr.sort(); console.log(arr); // ['a', 'b', 'c', 'd', 'e'] 冒泡排序 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 function bubbleSort(arr) { let len = arr.length; for (let i = 0; i < len - 1; i++) { // 从第一个元素开始,比较相邻的两个元素,前者大就交换位置 for (let j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { let num = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = num; } } // 每次遍历结束,都能找到一个最大值,放在数组最后 } return arr; } //测试 console.log(bubbleSort([2, 3, 1, 5, 4])); // [1, 2, 3, 4, 5] 数组去重 # Set 去重 # js 复制 1 2 cosnt newArr = [...new Set(arr)]; const newArr = Array.from(new Set(arr)); indexOf 去重 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 function resetArr(arr) { let res = []; arr.forEach((item) => { if (res.indexOf(item) === -1) { res.push(item); } }); return res; } // 测试 const arr = [1, 1, 2, 3, 3]; console.log(resetArr(arr)); // [1, 2, 3] 获取 url 参数 # URLSearchParams 方法 # js 复制 1 2 3 4 // 创建一个URLSearchParams实例 const urlSearchParams = new URLSearchParams(window.location.search); // 把键值对列表转换为一个对象 const params = Object.fromEntries(urlSearchParams.entries()); split 方法 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function getParams(url) { const res = {}; if (url.includes("?")) { const str = url.split("?")[1]; const arr = str.split("&"); arr.forEach((item) => { const key = item.split("=")[0]; const val = item.split("=")[1]; res[key] = decodeURIComponent(val); // 解码 }); } return res; } // 测试 const user = getParams("http://www.baidu.com?user=%E9%98%BF%E9%A3%9E&age=16"); console.log(user); // { user: '阿飞', age: '16' } 发布订阅模式 # js 复制 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 class EventEmitter { constructor() { this.cache = {}; } on(name, fn) { if (this.cache[name]) { this.cache[name].push(fn); } else { this.cache[name] = [fn]; } } off(name, fn) { const tasks = this.cache[name]; if (tasks) { const index = tasks.findIndex((f) => f === fn || f.callback === fn); if (index >= 0) { tasks.splice(index, 1); } } } emit(name, once = false) { if (this.cache[name]) { // 创建副本,如果回调函数内继续注册相同事件,会造成死循环 const tasks = this.cache[name].slice(); for (let fn of tasks) { fn(); } if (once) { delete this.cache[name]; } } } } // 测试 const eventBus = new EventEmitter(); const task1 = () => { console.log("task1"); }; const task2 = () => { console.log("task2"); }; eventBus.on("task", task1); eventBus.on("task", task2); eventBus.off("task", task1); setTimeout(() => { eventBus.emit("task"); // task2 }, 1000);

2024-06-16 · 4 分钟 · 1755 字 · Linlccc