刘聪 3 anos atrás
pai
commit
2b4b01ce90
1 arquivos alterados com 277 adições e 2 exclusões
  1. 277 2
      TS/JaveScript.md

+ 277 - 2
TS/JaveScript.md

@@ -3,7 +3,7 @@
  * @Autor: LC
  * @Date: 2022-01-20 10:45:55
  * @LastEditors: LC
- * @LastEditTime: 2022-02-07 21:24:31
+ * @LastEditTime: 2022-02-08 11:29:07
  * @Description: file content
 -->
 # JavaScipt语法
@@ -4241,4 +4241,279 @@ exports = {
    - 因为模块对象module有个属性`loaded`,ture表示已经加载,false表示未加载
 3. 循环引入的加载顺序,深度优先搜索:main->aaa->ccc->ddd->eee->bbb
 
-![循环引用的加载顺序](./Image/23.png)
+![循环引用的加载顺序](./Image/23.png)
+
+
+**暂停 跳过 工作暂时不涉及 为时间紧张暂不学习**
+
+## JSON-数据存储
+
+**JSON**是非常重要的**数据格式**,轻量级资料交换格式  
+
+- JSON使用场景
+  - 网络数据的传输JSON数据
+  - 项目的配置文件
+  - 非关系型数据库(NoSQL)将json作为存储格式
+
+- JSON的顶层支持三种类型的值
+  - 简单值:数字(Number)、字符串(String,不支持单引号)、布尔类型(Boolean)、null类型
+  - 对象值:k-v组成,key是字符串类型,而且必须双引号,值可以是简单值、对象值、数组值
+  - 数组值:数组的值可以是简单值、对象值、数组值
+
+```json
+123
+```
+
+```json
+"123"
+```
+
+```json
+null
+```
+
+```json
+true
+```
+
+```json
+{
+    "name" : "x",
+    "frien" : {
+        "name" : "y"
+    },
+    "hobbies" : ["1", "2"]
+}
+```
+
+```json
+[
+    "abc",
+    1234,
+    {
+        "name" : "x"
+    }
+]
+```
+
+> JSON注释不能写  
+> 最后一个item后面不能加上逗号
+
+### JS中使用JSON
+
+```javascript
+const obj = {
+    name : "x",
+    age : 10,
+    hobbies : ["1", "2"]
+}
+
+// 将obj转成JSON格式的字符串
+const objString = JSON.stringify(obj);
+console.log(objString);
+
+// JSON格式转成对象
+const info = JSON.parse(objString);
+console.log(info);
+```
+
+### 一些细节
+
+```javascript
+const obj = {
+    name : "x",
+    age : 10,
+    hobbies : ["1", "2"]
+}
+// JSON.stringify(value : any, replacer ?: (this : any, key : string, value : any) => any, splace ? : string | number) : string
+
+// 直接转换
+const objString = JSON.stringify(obj);
+console.log(objString);
+
+// stringify的第二个参数 replacer
+
+// replacer传入数组 设定哪些key是需要转换的
+const objString2= JSON.stringify(obj, ['name', 'age']);
+console.log(objString2);
+
+// 传入回调函数 遍历整个kv对,对数据进行处理
+const objString3 = JSON.stringify(obj, (key, value) => {
+    if(key === "age"){
+        value += 1;
+    }  
+    return value;
+});
+console.log(objString3);
+
+// stringify的第三个参数用于美化,第二个参数设null表示使用默认的
+
+// 传入数字,表示缩进空格数目
+const jsonString4 = JSON.stringify(obj, null, 2);
+console.log(jsonString4)
+
+const jsonString5 = JSON.stringify(obj, null, 4);
+console.log(jsonString5)
+
+// 传入字符,表示缩进不使用空格,而是指定字符串
+const jsonString6 = JSON.stringify(obj, null, ".");
+console.log(jsonString6)
+```
+
+> `JSON.stringify`方法的一些解释和用法
+
+```javascript
+const obj = {
+    name : "x",
+    age : 10,
+    hobbies : ["1", "2"],
+    toJSON : function() {
+        return "myself JSON String";
+    }
+}
+
+const objString = JSON.stringify(obj);
+console.log(objString);
+
+const objString3 = JSON.stringify(obj, (key, value) => {
+    if(key === "age"){
+        value += 1;
+    }  
+    return value;
+});
+console.log(objString3);
+```
+
+> 当对象中存在`toJSON`方法时,`JSON.stringify`会直接使用`toJSON`的返回值
+
+```javascript
+const objString = '{"name":"x","age":10,"hobbies":["1","2"]}';
+const obj = JSON.parse(objString);
+
+// JSON.parse(text : string, reviver : (this : any, key : string, value : any) => any) : any
+
+// 第二个参数 reviver,对每个key、value进行操作
+const obj2 = JSON.parse(objString, (key, value) => {
+    if(key === "age"){
+        value += 1;
+    }
+    return value;
+});
+console.log(obj2);
+```
+
+### 利用JSON做深拷贝
+
+就是利用`JSON.stringify`和`JSON.parse`做对象转换
+
+## 自定义深拷贝函数
+
+- 几种对象赋值关系
+  - 引入的赋值:指向同一个对象,互相之间影响(`x = y`)
+  - 对象的浅拷贝:只是浅层的拷贝,内部引入对象时,依然会互相影响(`x = [...y]`)
+  - 对象的深拷贝:两个对象不再有任何关系,不会互相影响
+
+```javascript
+// 简单的深拷贝
+let s1 = Symbol();
+const boj = {
+    name : "x",
+    foo : function() {
+        return 1;
+    }
+    [s1] : "qwe",
+}
+boj.inner = obj;    // 某些情况需要自己引用自己
+const info = JSON.parse(JSON.stringify(boj));
+```
+
+> 利用JSON深拷贝对象时,对函数无法进行处理  
+> 如果`Symbol`作为key,也无法处理  
+> 不支持循环引用  
+
+- 自定义深拷贝函数
+  - 自定义深拷贝的基本功能
+  - 对`Symbol`的key进行处理
+  - 其他数据类型的值进程处理:数组、函数、Symbol、Set、Map
+  - 对循环引用的处理
+
+```javascript
+function isObject(value){
+    const valueType = typeof value;
+    return (value !== null) && (valueType === "object" || valueType === "function");
+}
+
+// 因为deepClone可能在多个地方调用,所以将noteObjs声明为局部变量
+// 又因为Map是强引用会影响对象的销毁,所以需要使用WeakMap弱引用
+function deepClone(originValue, noteObjs = new WeakMap()){
+    // 判断是否是set类型 这里写的是浅拷贝 一般而言够用
+    if (originValue instanceof Set){
+        return new Set([...originValue]);
+    }
+
+    // 判断是否是map类型 这里写的是浅拷贝 一般而言够用
+    if (originValue instanceof Map){
+        return new Map([...originValue]);
+    }
+    
+    // 一般而言函数可以复用 直接返回就行
+    if(typeof originValue === "function"){
+        return originValue;
+    }
+    
+    // 普通类型直接return 普通类型是值拷贝
+    if(!isObject(originValue)){  
+        return originValue;
+    }
+
+    if(noteObjs.has(originValue)){
+        return noteObjs.get(originValue);
+    }
+    
+    // 不做判断,数组直接赋值给对象是错误的效果
+    // const newObj = {};
+    const newObj = Array.isArray(originValue) ? [] : {};    
+    noteObjs.set(originValue, newObj);  // 记录一下 表示该对象本次被处理了 防止对象中循环引用
+    for(const key in originValue){
+        newObj[key] = deepClone(originValue[key], noteObjs);  // 递归拷贝复制
+    }
+    
+    // 对Symbol的key做特殊处理,因为Symbol作为key时遍历不到
+    const symbolKeys = Object.getOwnPropertySymbols(originValue);
+    for(const sKey of symbolKeys){
+        // 一般而言Symbol是为了防止对象内部key的冲突,不同对象倒不影响
+        // const newsKey = Symbol(sKey.description);
+        // newObj[newsKey] = deepClone(originValue[sKey]);
+        newObj[sKey] = deepClone(originValue[sKey], noteObjs);
+    }
+
+    return newObj;
+}
+const s1 = Symbol("aaa");
+const s2 = Symbol("bbb");
+const obj = {
+    name : "x",
+    age : 10,
+    friend : {
+        name : "y",
+        age : 11,
+        address : {
+            city : "BJ"
+        }
+    },
+    hobbies : [1, 2, 3],
+    foo : function(){
+        console.log("qwer");
+    },
+    [s1] : "aaa",
+    s2key : s2,
+    set : new Set([1, 2, 3, 4]),
+    map : new Map([["x", 1], ["y", 2]])
+}
+
+obj.inner = obj;    // 自己引用自己
+
+const newObj = deepClone(obj);
+console.log(newObj);
+```
+