越努力,越幸运,做个ccode~

0%

前言

需求如下 在写xinyi-ui 官网时,需要对组件进行文档说明,说明文档都是md格式的文件,能否直接将md文件显示到页面上,而不改为html 呢?
现在有 install.md 和 get-started.md 两个文件

第一步 实现一个vite插件 md => html

  • 将对md文件的请求进行数据处理
  • 通过markdown-it 将源文件转为html字符串
    Read more »

前言

什么是深拷贝?

简单理解: b 是 a 的一份拷贝,b 中没有对 a 中对象的引用
另一种理解: b 是 a 的一份拷贝,a、b 各自画图,a 与 b 没有连接

简单的方法

JSON 序列化与反序列化

1
let obj = {a:1,b:[2,3],c:{xx:4,yy:5}}
2
let obj2 = JSON.parse(JSON.stringify(obj))
3
obj2.a = 11
4
obj2.b[0] = 11
5
obj2.c.xx = 44
6
console.log(obj)  // {a:1,b:[2,3],c:{xx:4,yy:5}} 原先的obj不会被改变

缺点:

  • 不支持函数
  • 不支持 undefind(因为 JSON 只有 null)
  • 不支持日期(会把 date 变成 iso8601 格式的日期字符串)
  • 不支持正则
  • 不支持 Error 对象
  • 不支持环状结构
  • NaN Infinity 会变成 null
1
const obj = {
2
  a: "a",
3
  b: undefined, // undefinde 丢失
4
  c: function () {
5
    // 函数丢失
6
    console.log("this is a fnction");
7
  },
8
  d: NaN, // NaN 变为 null
9
  e: Infinity, // Infinity 变为 null
10
  f: new Date(), // 时间对象变为 iso8601格式字符串
11
  g: /123/, // 正则 变为 空对象
12
  h: new Error("error"), // 变为空对象
13
};
14
console.log(JSON.parse(JSON.stringify(obj)));
15
// {a: 'a',d:null,e: null,f: 'iso8601格式字符串',g:{},h: {}}
16
17
obj.i = obj;
18
console.log(JSON.parse(JSON.stringify(obj))); // 报错

自己实现一个深拷贝

复制基本类型

基本类型:

  • Number
  • String
  • Boolean
  • Symbol
  • undefined
  • null

基本类型直接返回就好了

1
function deepClone(souce) {
2
  return souce;
3
}

引用类型 递归克隆

  • 普通对象
1
function deepClone(source) {
2
  if (source instanceof Object) {
3
    const dist = new Object();
4
    for (let key in source) {
5
      dist[key] = deepClone(source[key]);
6
    }
7
    return dist;
8
  } else {
9
    return source;
10
  }
11
}
  • Array 数组对象
    如果是数组的话 用上面的方法去拷贝 返回的是一个伪数组 且不会拷贝 length 属性
    所以我们的 dist 要是一个数组对象
1
function deepClone(source) {
2
  if (source instanceof Object) {
3
    if (source instanceof Array) {
4
      // 数组
5
      const dist = new Array();
6
      for (let key in source) {
7
        dist[key] = deepClone(source[key]);
8
      }
9
      return dist;
10
    } else {
11
      // 普通对象
12
      const dist = new Object();
13
      for (let key in source) {
14
        dist[key] = deepClone(source[key]);
15
      }
16
      return dist;
17
    }
18
  } else {
19
    return source;
20
  }
21
}
  • Function 对象
    函数的话 有两种方法 第一种就是再封装一个函数去调用源函数
1
if(source instance of Function){
2
  const dist = function () {
3
    return source.apply(this, arguments);
4
  };
5
  for (let key in source) {
6
    dist[key] = deepClone(source[key]);
7
  }
8
  return dist;
9
}

但是这种方法不会拷贝 length 属性 也就是函数形参个数 可以通过正则匹配函数体 函数参数 然后重新生成函数

1
const sourceString = source.toString();
2
let body = sourceString.match(/(?<={)((\n*.*)*)(?=})/m)[0];
3
let params = sourceString.match(/(?<=\().*(?=\))/)[0];
4
dist = new Function(...params.split(","), body);
  • RegExp 正则对象
1
else if (source instanceof RegExp) {
2
  dist = new RegExp(source.source, source.flags);
3
  for (let key in source) {
4
    dist[key] = deepClone(source[key]);
5
  }
6
  return dist
7
}
  • Date 日期对象
1
else if (source instanceof Date) {
2
  dist = new Date(source);
3
  for (let key in source) {
4
    dist[key] = deepClone(source[key]);
5
  }
6
  return dist
7
}
  • 环结构
1
a = { name: "a" };
2
a.self = a;

a 就是环状结构
可以通过缓存的方式去拷贝环结构 在拷贝 a.self 的时候我们已经拷贝过 a 了 可以将 a 与 a 的深克隆结果缓存起来

1
const cache = []
2
function deepClone(source){
3
  if(source instanceof Object){
4
   const sourceDist = cache.find((value) => value[0] === source)?.[1];
5
    if (sourceDist) {
6
      return sourceDist;
7
    } else {
8
      let dist
9
      ...
10
      // 放在for 循环的上面 否则会进入死循环
11
      cache.push([source,dist])
12
      for (let key in source) {
13
        dist[key] = deepClone(source[key]);
14
      }
15
      return dist
16
    }
17
  }
18
}

最终代码

1
// 会有bug catch 没有清空 会有影响 可以用面向对象的方法解决
2
const cache = [];
3
module.exports = function deepClone(source) {
4
  // 判断是不是对象
5
  if (source instanceof Object) {
6
    const sourceDist = cache.find((value) => value[0] === source)?.[1];
7
    if (sourceDist) {
8
      return sourceDist;
9
    } else {
10
      let dist;
11
12
      // 数组
13
      if (source instanceof Array) {
14
        dist = new Array();
15
16
        // 函数
17
      } else if (source instanceof Function) {
18
        // dist = function () {
19
        //   return source.apply(this, arguments);
20
        // };
21
22
        const sourceString = source.toString();
23
        let body = sourceString.match(/(?<={)((\n*.*)*)(?=})/m)[0];
24
        let params = sourceString.match(/(?<=\().*(?=\))/)[0];
25
        dist = new Function(...params.split(","), body);
26
27
        // 正则
28
      } else if (source instanceof RegExp) {
29
        dist = new RegExp(source.source, source.flags);
30
31
        // 日期
32
      } else if (source instanceof Date) {
33
        dist = new Date(source);
34
35
        // 普通对象
36
      } else {
37
        dist = new Object();
38
      }
39
40
      cache.push([source, dist]);
41
      for (let key in source) {
42
        // 跳过原型上的属性
43
        if (source.hasOwnProperty(key)) {
44
          dist[key] = deepClone(source[key]);
45
        }
46
      }
47
      return dist;
48
    }
49
50
    // 基本类型
51
  } else {
52
    return source;
53
  }
54
};

一些关于JS的基础知识巩固复习、整理

学了忘 忘了学。。。

一 instanceof

instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

Read more »

前言

vue组件通信的方式如此之多 今天我们来总结一下 完整代码

一、 props、$emit/v-on

父组件通过props向子组件传递数据
子组件使用事件抛出一个值

Read more »

前言

我们都知道v-model可以实现双向绑定,之前对v-model的了解还比较单一,今天来总结一下

单向绑定与双向绑定

单向绑定就是当我们用JavaScript代码更新Model时,View就会自动更新。
如果用户更新了View,Model的数据也自动被更新了,这种情况就是双向绑定。

Read more »

前言

在判断分支中使用符号”&“和”&&”作为逻辑判断是经常见的,但是这两者又有什么区别呢?
他们分别代表的位运算符和逻辑运算符又有什么区别呢?

Read more »

快速排序

什么是快速排序 ?

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

Read more »

正则实现一个手机号输入框

正则实现一个手机号输入框


Read more »