自从大二初次接触前端以来,一直都有记markdown笔记的习惯.又因为掘金最近有一个活动.所以开了这个专栏。我会写一些业务相关的小技巧和前端知识中的重点内容之类的整理一下发上来。难免有点地方不够细致。欢迎大家指教
这篇文章涵盖了
- length | 码元 | substring bug
- 遍历 object | set | array | map 删除元素
- 空数组用every或some
- for 和 foreach 的 异步处理
- 路由原理
- 异步数组循环 | 阻塞
- 短路运算符 和 ??
- encodeURIComponent | decodeURIComponent
- cjs、esm、umd的区别
- intl
- stopPropagation | stopImmediatePropagation
这些概念的辨析和个人总结
2.1.66 剪切板
scss
--1.
navigator.clipboard.writeText("dsa")
.then(() => alert("复制成功!"));
//如果我们想直接使用会报错
--2.
创造一个文本域
oInput.select();
document.execCommand("Copy");
//对选择对象的值进行复制到浏览器中
2.1.67 事件冒泡
指的是在设置了事件监听器时候,会顺着dom树的结构,向上执行
xml
<div id="div1">
div1
<div id="div2">
div2
<div id="div3">div3</div>
</div>
</div>;
// javascript:
<body>
function handleClick(event) {
console.log(event.currentTarget.id);
}
for (let i = 1; i <= 3; i++) {
let div = document.getElementById(`div${i}`);
div.addEventListener("click", handleClick);
}
</body>
<!-- 我们再点击在里面的div3的时候,会输出div3 div2 div1-->
<!-- 如果说要避免这一个情况可以
function handleClick(event) {
event.stopPropagation();
console.log(event.currentTarget.id);
}
-->
event.stopPropagation();
2.1.69 length | bug | 码元是小一点 | substring bug
matlab
一些 emoji 的东西的length 可能会有一点不一样
原因在于 length 的 码点 和 码元
我们将一个16/32位的二进制编码 叫做一个码元,一个码点 可以是 一个码元 也可以是两个码元. length 属性 返回的是 码元(小)
正确的方式是Array.from("xx").length
2.1.70 class 内 | 私有字段 | 静态变量 | 类静态初始化
javascript
--1.私有字段
以前是加一个_
_myName(){
}
现在可以命名成
#myName(){
}
在外面就不可以直接调用
--2.static 的 作用
class Person {
/* 1.1、实例属性,直接定义的属性,要new实例后,实例去访问的*/
name= "tom";
/* 1.2、静态属性(类属性),通过static开头的属性,Person类可以访问,
不需要创建实例,实例访问不到static */
static height = 180;
/* 1.3、只读属性,readonly开头的属性,只可读,不可改 ts才能用 */
//readonly money= 1000;
/* 1.4、方法,readonly开头的属性,只可读,不可改*/
say(){
console.log('hello world');
}
static work(){
console.log('我能挣钱');
}
}
console.log(new Person().height)
--3.类静态初始化
例如
class person {
static age =1.2
}
可以变成
class person {
static{
this.age = 1.2
}
}
2.1.71 worker | 优化
javascript
worker.js中
接收 worker 并且进行 事件逻辑处理
onmessage = function (e) {
let sortData = e.data.sort((a,b)=>{
return a-b
})
postMessage(sortData)
}
index.html 中
let worker = new Worker("worker.js")
let arr = [1,3,4,34,2]
worker.postMessage(arr)
worker.onmessage= function (e){
console.log(e.data)
}
2.1.72 遍历 object | set | array | map 删除元素会怎么样
边遍历 边删除元素
ini
遍历Object | array | set | map 时删除元素,那么就直接删掉了
const myObject = { a: 1, b: 2, c: 3 };
for (const key in myObject) {
if (myObject[key] === 2) {
delete myObject["c"];
}
console.log(key, myObject[key]);
}
// 输出 a 1 | b 2
const mySet = new Set([1, 2, 3, 4]);
for (const item of mySet) {
if (item === 2) {
mySet.delete(1);
}
console.log(item);
};
console.log(mySet) // 2 3 4
css
const a = [1,5,6,9]
let b =a.map((e,index)=>{
delete a[index]
return index
})
ini
let ac = [5,4,9];
for (const key in ac) {
if (ac[key] === 4) {
delete ac[0];
}
console.log(key, ac[key],ac);
}
2.1.73 空数组用every或some会返回什么
swift
every 是 true // 所有元素满足
some 是 false // 有一个元素满足测试函数
2.1.74 for 和 foreach 的 异步处理
- 在forEach中,异步方法不会阻塞循环本身的执行,而是会在后台异步执行。用 return 可以实现 continue的效果
- 而在for循环中,异步方法如果使用await等待异步操作完成,会导致循环会等待每个异步任务完成后再继续执行下一次循环迭代
csharp
总结:forEach循环和for循环对于异步方法的处理有一些区别。。所以,如果你需要保证异步方法按顺序执行,可以使用for循环,并在异步方法内使用await等待异步操作的完成。
2.1.76 路由原理
perl
hashrouter中存放两个状态 一个是hash一个是push方法。push方法就是提供给其他组件进行调用。其实原理就是window..location.hash=xxxx,然后监听hashchange状态,在状态改变的时候给状态赋值,然后内部给一个createcontext,里面是在路由文件中定义的组件 {{props.child}}。 用provider渲染
route 里面存放 路径,是否匹配 和路由文件三个。这里面其实是一个消费者
link 是一个其实调用了第一个的push方法。也是一个消费者,comsumer
而默认404路由是通过一个switchjs匹配不到其他的组件才会匹配一个默认的
history{
pathname
push 方法
}
queue数组
browerroute的区别在于 这是通过window.location.pushstate.然后多添加了一个queqe方法来做。window.addeventlistener 的popstate方法
2.1.77 异步数组循环 | 阻塞
javascript
刚刚发现了一个东西,map,reduce,forEach,map中用异步函数加上async await都不会阻塞,只有for,for...in,for...of加上async await能够阻塞
示例
async function asyncFunc(data:any) {
return new Promise(async(resolve) => {
setTimeout(() => {
console.log(data)
resolve(data);
}, Math.random() * 1000);
});
}
const array = [1, 2, 3];
// 这样子 不会按照顺序输出
// array.map(async (item) => {
// const result = await asyncFunc(item);
// // console.log(result);
// return result
// });
// for循环 获取.也不能按顺序输出,但是可以把集合 合起来
// console.log(await Promise.all(array.map(async(e,i)=>{
// return await asyncFunc(i)
// })))
for(let i of array){
await asyncFunc(i);
}
console.log("dssds")
2.1.78 短路运算符 和 ??
javascript
一般来说,只会用 || 来进行默认值
像是 obj.a.b.c.d 比较危险 我们就可以 obj.a && obj.a.b && obj.a.b.c.可选链也可以
在 xx && yy 表达式中,只有当 xx 是真值时,yy 才会被执行,否则不会执行 yy 并且该表达式的结果为 串联
在 xx || yy 表达式中,只有当 xx 是假值时,yy 才会被执行,否则不会执行 yy 并且该表达式的结果为 并联
实例:
console.log("" && 'str1'); // 输出 ""
console.log("" || 'str1'); // 输出第二个。这个做空值表达式不错,可以用 不是正值的默认情况,比如后端返回 '' 的时候。玩不了一点
注意 ?? 不能用来随便来做 空值表达式 因为 ?? 只对 undefined 和 null 生效 像是 0 '' 是不会生效的 // 可以用来做一个变量的默认值
2.1.80 encodeURIComponent | decodeURIComponent
ini
encodeURIComponent 和 decodeURIComponent 方法主要用于处理 URI 字符串中的特殊字符,比如 %、+ 等。这些特殊字符在传输中需要进行转义,否则会造成意想不到的错误,而这些方法的作用就是对这些特殊字符进行编码和解码。
例如,当我们想要传输如下的URI查询字符串时:
foo=hello&bar=world!
如果直接将这个查询字符串作为URI传输,服务器就会将!解析成分隔符,导致查询参数读取错误。此时,我们需要对查询字符串进行编码操作,将其中的特殊字符转义为URI安全的字符,才能正确地传输和解析查询参数。使用 encodeURIComponent 方法可以将以上查询字符串编码为:
foo=hello&bar=world%21
其中,!被编码为 %21,以确保它不会被服务器解析成分隔符。在URL传输过程中,这些字符的编码和解码是非常重要的,否则可能会导致数据传输的错误或安全问题。
2.1.81 cjs、esm、umd的区别
- cjs:commonjs
是 Node 中的模块规范,通过
require及
exports进行导入导出 (进一步延伸的话,module.exports
属于commonjs2
)。webpack 也对cjs
模块得以解析,但不能在浏览器中直接使用。但如果你写前端项目在 webpack 中,也可以理解为它在浏览器和 Node 都支持。这就也是了很多时候我们cdn引入的时候报错的原因 - esm:
esm
是 tc39 对于 ESMAScript 的模块话规范,正因是语言层规范,因此在 Node 及 浏览器中均会支持 ,使用import/export
进行模块导入导出.。esm比cjs好很多的。esm 是编译时加载,输出的是值的引用 。cjs 模块是运行时加载,cjs 模块输出的是一个值的拷贝 - umd:兼容cjs和esm都可以
2.1.82 intl
-
目前来看 国际化复数不是很好用
-
他的时间格式化还可以
sqlconst rtf1 = new Intl.RelativeTimeFormat('pinyun', { style: 'short' }); console.log(rtf1.format(3, 'quarter')); console.log(rtf1.formatToParts(100, "day")); // const date = Date.UTC(2012, 11, 17, 3, 0, 42); // const date = new Date(2023, 09, 25).getTime() const date = new Date().getTime() const formatter = new Intl.DateTimeFormat("pinyin", { // 可能表示的值有2个 `long` 和 `short`.前者表现为 Thursday,后者表现为 Thu weekday: "long", // 可能表示的值有2个 `numeric `和 `2-digit`。 前者表现为 1,后者表现为 01 year: "numeric", // 可能表示的值有5个 `numeric `和 `2-digit` 和 `long` 和 `short` 和 `narrow`, `narrow` 表示marth为 M month: "numeric", // 可能的值有2个 "numeric" 和 `2-digit` day: "numeric", hour: "numeric", minute: "numeric", second: "numeric", fractionalSecondDigits: 3, hour12: true, }); console.log(formatter.format(date)) console.log(formatter.formatToParts(date))
-
字符串比较可以用
iniconst arr = ['武汉', '北京', '上海', '天津']; const resultArray = arr.sort((item1, item2) => { let flag = new Intl.Collator("pinyin",{ sensitivity: "base" }).compare(item1, item2) let TrueFlag = item1.localeCompare(item2, "zh") console.log(flag,TrueFlag) return flag } );
-
listFormat不太行,不是很清楚他的应用场景
-
Intl.Segmenter:很奇怪,用不了一点
2.1.83 Error cause
这个属性好像不生效,浪费我时间。吐槽一下,好像好多的无障碍属性也是这样
javascript
throw new Error("Connecting to database failed.", { cause: "datestinrh" });
2.1.84 JSBridge做了些什么
Native端和Web端的双向通信。Web调用Native端主要有两种方式,第一种是url schema。我们可以自定义JSBridge通信的URL Schema(这种方式似乎在苹果有问题),比如:jsbridge://showToast?text=hello。如果符合我们自定义的URL Schema,对URL进行解析,拿到相关操作、操作,进而调用原生Native的方法。如果不符合我们自定义的URL Schema,我们直接转发,请求真正的服务
2.1.85 event.target 与 event.currentTarget 的区别
- event.target 是触发事件的元素
- event.currentTarget 是绑定事件的元素
2.1.86 stopPropagation VS stopImmediatePropagation
- stopPropagation 会阻止冒泡
- stopImmediatePropagation 不仅会阻止冒泡,还会阻止监听对目标元素的监听事件