判断是否为空对象
const isEmpty = obj => Reflect.ownKeys(obj).length === 0 && obj.constructor === Object;
isEmpty({}) // true
isEmpty({a:"not empty"}) //false
生成十六进制颜色值
const randomHexColor = () => `#${Math.floor(Math.random() * 0xffffff).toString(16).padEnd(6, "0")}`
console.log(randomHexColor());
// #a2ce5b
文字复制到剪贴板
const copyText = async (text) => await navigator.clipboard.writeText(text)
copyText('单行代码 前端世界')
两日期之间相差的天数
const dayDiff = (date1, date2) => Math.ceil(Math.abs(date1.getTime() - date2.getTime()) / 86400000);
dayDiff(new Date("2021-10-21"), new Date("2022-02-12"))
// Result: 114
从url获取参数并转为对象
const getParameters = URL => JSON.parse(`{"${decodeURI(URL.split("?")[1]).replace(/"/g, '\\"').replace(/&/g, '","').replace(/=/g, '":"')}"}`
)
getParameters("https://www.google.com.hk/search?q=js+md&newwindow=1");
// {q: 'js+md', newwindow: '1'}
对象obj中取值
对象obj中取值 解构的对象不能为undefined、null。否则会报错,故要给被解构的对象一个默认值
const {a,b,c,d,e} = obj || {};
合并两个数组,合并两个对象
旧方法:
const a = [1,2,3];
const b = [1,5,6];
const c = a.concat(b);//[1,2,3,1,5,6]
const obj1 = {
a:1,
}
const obj2 = {
b:1,
}
const obj = Object.assign({}, obj1, obj2);//{a:1,b:1}
新方法:
const c = [...new Set([...a,...b])];//[1,2,3,5,6] 合并两个数组
const obj = {...obj1,...obj2};//{a:1,b:1} 合并两个对象
if判断多个或者条件的时候
if(
type == 1 ||
type == 2 ||
type == 3 ||
type == 4 ||
){
//...
}
改进:
const condition = [1,2,3,4];
if( condition.includes(type) ){
//...
}
使用 slice 和 padStart 掩码数字
const cardNumber = '400000033330000';
const last4Light = cardNumber.slice(4)
const maskNumber = last4Light.padStart(cardNumber.length, '*');
console.log(maskNumber); 结果: ***********0000
列表搜索
一般用filter来实现,find方法中找到符合条件的项,就不会继续遍历数组。注意是搜索 不能一概而论都用find
const a = [1,2,3,4,5];
const result = a.find(
item =>{
return item === 3
}
)
最简单的方法:if 判断 好一点的方法:Switch 更优的方法:
const commodity = new Map([
['phone', 1999],
['computer', 9999],
['television', 2999],
['gameBoy', 3999],
])
const price = (name) => {
return commodity.get(name)
}
price('phone') // 1999
数组去重
const uniqueArr = (arr) => [...new Set(arr)];
console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]))
// [1, 2, 3, 5, 6, 7, 4]
防抖与节流
持续触发 scroll 事件时,并不立即执行 handle 函数,当 1000 毫秒内没有触发 scroll 事件时,才会延时触发一次 handle 函数。
function debounce(fn, wait) {
let timeout = null
return function () {
if (timeout !== null) clearTimeout(timeout)
timeout = setTimeout(fn, wait)
}
}
function handle() {
console.log(Math.random())
}
window.addEventListener('scroll', debounce(handle, 1000))
使用some方法判断是否有满足条件的元素
let arr = [1, 3, 5, 7]
let isHasNum = (n, arr) => arr.some(num => num === n)
在if中判断数组长度为零的正确姿势
// good
if (!arr.length) {
// todo
}
在if中判断数组长度不为零的正确姿势
// good
if (arr.length) {
// todo
}
使用filter方法过滤原数组,形成新数组
// good
let arr = [1, 3, 5, 7]
let newArr = arr.filter(n => n > 4) // [5, 7]
使用map对数组中所有元素批量处理,形成新数组
// good
let arr = [1, 3, 5, 7]
let newArr = arr.map(n => n + 1) // [2, 4, 6, 8]
字符串转数字
接口返回的一串数字有时候是字符串的形式,通过前面加个‘+’号 通通转化为数字
+this.time
处理多个条件 some
- 如果有一个元素满足条件,则表达式返回true , 剩余的元素不会再执行检测。
- 如果没有满足条件的元素,则返回false。
someFunction(str){
const conditions = ["someValue1","someValue2"];
return conditions.some(condition=>str.includes(condition));
}
使用事件委托
<ul>
<li>字节跳动</li>
<li>阿里</li>
<li>腾讯</li>
<li>京东</li>
</ul>
// good
document.querySelector('ul').onclick = (event) => {
const target = event.target
if (target.nodeName === 'LI') {
console.log(target.innerHTML)
}
}
// bad
document.querySelectorAll('li').forEach((e) => {
e.onclick = function() {
console.log(this.innerHTML)
}
})
交换两个变量的简单方法
let a = 10;
let b = 20;
[b,a] = [a,b]
console.log(a); // 20
console.log(b); // 10
Nullish Coalescing Operator (??) 是一个逻辑运算符
它接受两个值,如果第一个值为 null 或未定义则返回第二个值,否则返回第一个值
相比||运算更加准确
let num1 = 0;
let num2;
const default1 = num1 || 1; // 打印输出 // 1
const default2 = num2 || 2 // 打印输出 // 2
// 在vue(vue-cli3)项目中使用会编译报错 需要安装额外依赖
const default3 = num1 ?? 1 // 打印输出 // 0
const default4 = num2 ?? 2 // 打印输出 // 2
有条件的为对象添加属性
// 这是第一种普遍写法
const includeSumary = true;
const bankYee = {
id: 1,
name: 'fish'
}
if (includeSumary){
bankYee.yee = 500;
}
// 高级写法
const bankYees = {
id: 1,
name: 'fish',
...(includeSumary && {bankYee: 500})
}
路由参数解耦 以及路由的传参方式
// 定义
routes: [
{
path: /user:id,
component: '',
props: true
}
]
// 使用
export default {
props: [id],
methods: {
getParams() {
return this.id;
}
}
}
第三方组件样式渗透
可以使用 >>> 或者 /deep/ 来解决这个问题
layer >>> .el-checkbox
layer /deep/ .el-checkbox
watch的高级使用
watch时有一个特点,就是当值第一次绑定的时候,不会执行监听函数
如果需要在最初绑定值的时候也执行函数,则需要用到immediate属性。
普通的watch方法无法监听到对象内部属性的改变 则需要用到deep属性
watch: {
name: {
handler: sayName,
immediate: true,
deep: true,
}
}
methods: {
sayName() {
console.log(this.name)
}
}
watch监听多个变量-本身不能监听多个变量
export default {
data() {
return {
msg1: apple ,
msg2: banana
}
},
compouted: {
msgObj() {
const { msg1, msg2 } = this
return {
msg1,
msg2
}
}
},
watch: {
msgObj: {
handler(newVal, oldVal) {
if (newVal.msg1 != oldVal.msg1) {
console.log( msg1 is change )
}
if (newVal.msg2 != oldVal.msg2) {
console.log( msg2 is change )
}
},
deep: true
}
}
}
监听页面生命周期 清除定时器
export default {
mounted() {
this.creatInterval( hello )
this.creatInterval( world )
},
creatInterval(msg) {
let timer = setInterval(() => {
console.log(msg)
}, 1000)
this.$once( hook:beforeDestroy , function() {
clearInterval(timer)
})
}
}
使用@hook 来监听组件的生命周期
<template>
<List @hook:mounted="listenMounted" />
</template>
浏览器一键重新发起请求
network 选择要重新发送的请求 右键选择Replay XHR
控制台快速发起请求 需要修改入参的接口
network 选择要修改后重新发送的请求 右键选择 选择Copy as fetch 控制台粘贴代码 修改参数,回车发起请求
截取一张全屏的网页
cmd + shift + p 执行Command命令 输入Capture full size screenshot 按下回车 可以输入full来搜索
截取选中的部分元素
选中节点 鼠标右键选择 Capture node screenshot
常量命名规范
常量的命名规范常量命名应该使用全大写格式,并用下划线分割
git分支命名规范
主分支(master)、集成上前准备分支(release)、灰度分支(gray) 灰度分支(gray)只进不出
git新建分支步骤
新建分支 1、git checkout -b xxx 2、git push -u origin xxx
git stash 使用场景
正在feature分支开发新需求,突然线上有bug,必须马上修复需要切到master 新开发的需求怎么办?
# 保存当前未commit的代码
git stash
# 保存当前未commit的代码并添加备注
git stash save "备注的内容"
# 列出stash的所有记录
git stash list
# 删除stash的所有记录
git stash clear
# 应用最近一次的stash
git stash apply
# 应用最近一次的stash,随后删除该记录
git stash pop
# 删除最近的一次stash
git stash drop
reset 使用场景
git reset --soft 相当于后悔药,给你重新改过的机会。保持干净的commit记录 注意只针对未 push 的commit 执行后修改内容都回到了暂存区
git reset --hard 强制回溯
git reset --soft 软回溯
git push -f 强制提交
cherry-pick 使用场景
将已经提交的commit 复制 应用到别的分支里 分支代码被污染拉一条干净的开发分支从旧的分支中,把commit复制到新分支
git cherry-pick commitID
revert 使用场景(简单版)
上线的功能有问题,需要马上撤回 如果用reset会把其他同事的代码也撤回,revert 会生成一条新的提交记录 虽然之前的提交记录还保留着,但你修改的代码内容已经被撤回了
git revert 21dcd937fe555f58841b17466a99118deb489212
revert 合并提交 (切合实际版)
使用场景 合并提交两条分支的交集节点,而git不知道需要撤销的哪一条分支,需要添加参数 -m 指定主线分支,保留主线分支的代码,另一条则被撤销
git revert -m 1 <commitHash>
注意
revert 合并提交后,再次合并分支会失效,在 master 分支 revert 合并提交后,然后切到 feature 分支修复好 bug,再合并到 master 分支时,会发现之前被 revert 的修改内容没有重新合并进来。因为使用 revert 后, feature 分支的 commit 还是会保留在 master 分支的记录中,当你再次合并进去时,git 判断有相同的 commitHash,就忽略了相关 commit 修改的内容。
需要 revert 掉之前 revert 的合并提交
reflog 记录了所有的 commit 操作记录
用 git reflog 查看历史记录
script[type=module]
通过 script[type=module],可直接在浏览器中使用原生 ESM。这也使得前端不打包 (Bundless) 成为可能。
<script type="module">
import lodash from "https://cdn.skypack.dev/lodash";
</script>
通过 script[type=module],不仅可引入 Javascript 资源,甚至可以引入 JSON/CSS,示例如下
<script type="module">
import data from "./data.json" assert { type: "json" };
console.log(data);
</script>