遇到的问题笔记

59 篇文章 1 订阅
7 篇文章 0 订阅

有关DNS

在这里插入图片描述

A. DNS(Domain Name System,域名系统),因特网上作为域名和IP地址相互映射的一个分布式数据库,能够使用户更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。
BC.DNS协议运行在UDP协议之上,使用端口号53。
D. 浏览器:chrome对每个域名会默认缓存60s,IE将DNS缓存30min,Firefox对DNS缓存功能,但是默认缓存时间只有1分钟,safari约为10s。
windows DNS缓存的默认值是MaxCacheTTL,它的默认值是86400s,也就是一天。
浏览器DNS缓存的时间跟ttl值无关,每种浏览器都使用一个固定值。

TCP

在这里插入图片描述

数组元素移动

在这里插入图片描述

function replaceElements( arr ) {
    let newArr = [];
    while(arr.length) {
    	//得到该元素的右边元素
        arr.shift();
        if(!arr.length) {
            newArr.push(-1)
        } else {
        	//得到右边元素
           newArr.push(Math.max(...arr)) 
        }
    }
    return newArr
}

两个数组的交集

在这里插入图片描述

const set_intersection = (set1, set2) => {
    if (set1.size > set2.size) {
        return set_intersection(set2, set1);
    }
    const intersection = new Set();
    for (const num of set1) {
        if (set2.has(num)) {
            intersection.add(num);
        }
    }
    return [...intersection];
}

var intersection = function(nums1, nums2) {
    const set1 = new Set(nums1);
    const set2 = new Set(nums2);
    return set_intersection(set1, set2);
};


webpack缓存:

  1. babel缓存
    cacheDirectory: true
    –> 让第二次打包构建速度更快
  2. 文件资源缓存
    hash: 每次wepack构建时会生成一个唯一的hash值。
    问题: 因为js和css同时使用一个hash值。
    如果重新打包,会导致所有缓存失效。(可能我却只改动一个文件)
    chunkhash:根据chunk生成的hash值。如果打包来源于同一个chunk,那么hash值就一样
    问题: js和css的hash值还是一样的
    因为css是在js中被引入的,所以同属于一个chunk
    contenthash: 根据文件的内容生成hash值。不同文件hash值一定不一样
    –> 让代码上线运行缓存更好使用(上线代码的性能优化的)

综上所述:开启缓存需要经历两个步骤:
1. 设置cacheDirectory: true
2. 在输出的数组中加上contenthash

toString与valueOf 巧妙使用

如何进入if语句中
在这里插入图片描述
在这里插入图片描述

	   let a = {
            _default: 0,

            valueOf: function() {
                return ++this._default;
            }

        }
        if (a == 1 && a == 2 && a == 3) {
            console.log("you are win !!")
        }

        let b = {
            _default: 0,
            valueOf: function() {
                return ++this._default;
            }

        }
        if (b == 1 && b == 2 && b == 3) {
            console.log("you are win !!")
        }

        var _default = 0;

        Object.defineProperty(window, 'c', {
            get() {
                return ++_default;
            }
        })


        if (c === 1 && c === 2 && c === 3) {
            console.log("you are win !!")
        }

Object.defineProperty()

Function

Function.length

length 是函数对象的一个属性值,指该函数有多少个必须要传入的参数,即形参的个数。形参的数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数。与之对比的是, arguments.length是函数被调用时实际传参的个数

Function 构造器的属性

Function 构造器本身也是个Function。他的 length 属性值为 1 。该属性 Writable: false, Enumerable: false, Configurable: true.

console.log(Function.length); /* 1 */

console.log((function()        {}).length); /* 0 */
console.log((function(a)       {}).length); /* 1 */
console.log((function(a, b)    {}).length); /* 2 etc. */

console.log((function(...args) {}).length);
// 0, rest parameter is not counted

console.log((function(a, b = 1, c) {}).length);
// 1, only parameters before the first one with
// a default value is counted

Function 构造器

Function 构造器创建的函数不会创建当前环境的闭包,它们总是被创建于全局环境
因此在运行时它们只能访问全局变量和自己的局部变量
不能访问它们被 Function 构造器创建时所在的作用域的变量。这一点与使用eval 执行创建函数的代码不同。

const test = new Function("a", 'b', 'c', "console.log(a+b+c)")
    // const test = new Function('a,b,c', "console.log(a+b+c)")
test(1, 3, 4) // 8
var x = 10;

function createFunction1() {
    var x = 20;
    return new Function('return x;'); // 这里的 x 指向最上面全局作用域内的 x
}

function createFunction2() {
    var x = 20;
    function f() {
        return x; // 这里的 x 指向上方本地作用域内的 x
    }
    return f;
}

var f1 = createFunction1();
console.log(f1());          // 10
var f2 = createFunction2();
console.log(f2());          // 20

扁平数据树形结构化

测试data

const data = [{
        id: '1',
        menu_name: '设置',
        menu_url: 'setting',
        parent_id: 0
    }, {
        id: '1-1',
        menu_name: '权限设置',
        menu_url: 'setting.permission',
        parent_id: '1'
    }, {
        id: '1-1-1',
        menu_name: '用户管理列表',
        menu_url: 'setting.permission.user_list',
        parent_id: '1-1'
    }, {
        id: '1-1-2',
        menu_name: '用户管理新增',
        menu_url: 'setting.permission.user_add',
        parent_id: '1-1'
    }, {
        id: '1-1-3',
        menu_name: '角色管理列表',
        menu_url: 'setting.permission.role_list',
        parent_id: '1-1'
    }, {
        id: '1-1-4',
        menu_name: '角色管理新增',
        menu_url: 'setting.permission.role_add',
        parent_id: '1-1'
    }, {
        id: '1-2',
        menu_name: '菜单设置',
        menu_url: 'setting.menu',
        parent_id: '1'
    }, {
        id: '1-2-1',
        menu_name: '菜单列表',
        menu_url: 'setting.menu.menu_list',
        parent_id: '1-2'
    }, {
        id: '1-2-2',
        menu_name: '菜单添加',
        menu_url: 'setting.menu.menu_add',
        parent_id: '1-2'
    }, {
        id: '2',
        menu_name: '订单',
        menu_url: 'order',
        parent_id: 0
    }, {
        id: '2-1',
        menu_name: '报单审核',
        menu_url: 'order.orderreview',
        parent_id: '2'
    }, {
        id: '2-2',
        menu_name: '退款管理',
        menu_url: 'order.refundmanagement',
        parent_id: '2'
    }, {
        id: '2-3',
        menu_name: '实物订单',
        menu_url: 'order.realorder',
        parent_id: '2'
    }, {
        id: '2-1-1',
        menu_name: '全部报单',
        menu_url: 'order.orderreview.all',
        parent_id: '2-1'
    }, {
        id: '2-2-1',
        menu_name: '所有记录',
        menu_url: 'order.refundmanagement.all',
        parent_id: '2-2'
    }, {
        id: '2-2-2',
        menu_name: '待处理',
        menu_url: 'order.refundmanagement.wait',
        parent_id: '2-2'
    }, {
        id: '2-2-3',
        menu_name: '退款原因',
        menu_url: 'order.refundmanagement.result',
        parent_id: '2-2'
    }, {
        id: '2-3-1',
        menu_name: '实物订单管理',
        menu_url: 'order.realorder.list',
        parent_id: '2-3'
    }, {
        id: '3',
        menu_name: '商品',
        menu_url: 'commodity',
        parent_id: 0
    }, {
        id: '3-1',
        menu_name: '分类管理',
        menu_url: 'commodity.classifieldmanagement',
        parent_id: '3'
    }, {
        id: '3-1-1',
        menu_name: '管理',
        menu_url: 'commodity.classifieldmanagement.management',
        parent_id: '3-1'
    }, {
        id: '3-1-2',
        menu_name: '编辑或新增',
        menu_url: 'commodity.classifieldmanagement.edit',
        parent_id: '3-1'
    }, {
        id: '3-2',
        menu_name: '品牌管理',
        menu_url: 'commodity.brandmanagement',
        parent_id: '3'
    }, {
        id: '3-2-1',
        menu_name: '管理',
        menu_url: 'commodity.brandmanagement.management',
        parent_id: '3-2'
    }, {
        id: '3-2-2',
        menu_name: '编辑或新增',
        menu_url: 'commodity.brandmanagement.edit',
        parent_id: '3-2'
    }, {
        id: '3-3',
        menu_name: '商品管理',
        menu_url: 'commodity.commoditymanagement',
        parent_id: '3'
    }, {
        id: '3-3-1',
        menu_name: '管理',
        menu_url: 'commodity.commoditymanagement.management',
        parent_id: '3-3'
    }, {
        id: '3-3-2',
        menu_name: '编辑或新增',
        menu_url: 'commodity.commoditymanagement.edit',
        parent_id: '3-3'
    }, {
        id: '3-4',
        menu_name: '类型管理',
        menu_url: 'commodity.typeManagement',
        parent_id: '3'
    }, {
        id: '3-4-1',
        menu_name: '管理',
        menu_url: 'commodity.typeManagement.management',
        parent_id: '3-4'
    }, {
        id: '3-4-2',
        menu_name: '编辑或新增',
        menu_url: 'commodity.typeManagement.edit',
        parent_id: '3-4'
    },
    {
        id: "1-1-2-1",
        menu_name: "我是第四级",
        menu_url: "four",
        parent_id: "1-1-2"
    }
];

递归实现


function formatDataTree(data) {
    // 说明是根数据
    let parents = data.filter(p => p.parent_id === 0),
        //子元素 
        children = data.filter(p => p.parent_id != 0);

    dataTree(parents, children)

    // parents children  array[]
    function dataTree(parents, children) {
        parents.map(p => {
            children.map((c, i) => {
                if (c.parent_id === p.id) {
                    // 深拷贝一份,防止直接修改原先引用
                    let _children = JSON.parse(JSON.stringify(children))
                    _children.splice(i, 1)
                        // 再次递归寻找子节点
                    dataTree([c], _children)
                    if (p.children) {
                        p.children.push(c)
                    } else {
                        p.children = [c]
                    }
                }
            })
        })
    }
    return parents
}

const treeData = formatDataTree(data)

console.log(treeData)

循环实现

时间复杂度O(n^2)

function formatDataTree(data) {
    let _data = JSON.parse(JSON.stringify(data));
    return _data.filter(p => {
        const childrenArr = _data.filter(c => c.parent_id === p.id);
        childrenArr.length && (p.children = childrenArr);
        return p.parent_id == 0;
    })
}
const dataTree = formatDataTree(data);
console.log(dataTree)

转对象实现

时间复杂度 O(n)


function buildTree(list) {

    let temp = {};
    let tree = {};
    for (let i in list) {
        temp[list[i].id] = list[i];

    }
    for (let i in temp) {
        debugger
        if (temp[i].parent_id) {
            if (!temp[temp[i].parent_id].children) {
                temp[temp[i].parent_id].children = new Object();
            }
            temp[temp[i].parent_id].children[temp[i].id] = temp[i];
        } else {
            tree[temp[i].id] = temp[i];
        }
    }
    return tree;
}
let arr = [];
for (let index in data) {
    arr.push(JSON.parse(JSON.stringify(data[index])))
}

const dataTree = buildTree(arr);

实现MVVM

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <div id="app">
        <input type="text" v-model="name" placeholder="姓名" />
        <input type="text" v-model="age" placeholder="年龄" />
        <input type="text" v-model="email" placeholder="邮箱" />
        <input type="text" v-model="tel" placeholder="号码" />
        <div>
            <p>姓名:<span>{{name}}</span></p>
            <p>年龄:<span>{{age}}</span></p>
            <p>邮箱:<span>{{email}}</span></p>
            <p>
                <p>
                    号码:<span>{{tel}}</span>
                </p>
            </p>
        </div>
        <button id="btn">改变名字</button>
    </div>
    <script src="./mvvmProxy.js"></script>
    <script>
        const app = new MVVM('#app', {
            name: 'xxx',
            age: '',
            email: '',
            tel: '',
        })

        document.querySelector('#btn').addEventListener('click', function() {
            app.setData('name', "哈哈哈")
        })
    </script>
</body>

</html>

使用Object.defineProperty

步骤
  1. 数据 --> 响应式数据 Object.defineProperty Proxy
  2. input --> input/keyup–> 事件处理函数的绑定 --> 改变数值
  3. 相关的DOM --> 数据绑定 ==> 绑定在一起
    操作数据的某个属性 --> 对应的DOM 就改变
class MVVM {
    constructor(el, data) {
        this.el = document.querySelector(el);
        this._data = data;
        this.domPool = {}
        this.init()
    }
    init() {
        this.initData()
        this.initDom()
    }

    initDom() {
        this.bindDom(this.el);
        this.bindInput(this.el);
        console.log(this.domPool)
    }
    initData() {
        const _this = this;
        this.data = {};
        for (let key in this._data) {
            Object.defineProperty(this.data, key, {
                get() {
                    console.log("获取数据:", key, _this._data[key])
                    return _this._data[key];
                },
                set(newValue) {
                    console.log("设置数据:", key, newValue)
                    _this.domPool[key].innerHTML = newValue;
                    _this._data[key] = newValue
                }
            })
        }


    }
    bindDom(el) {
            // 取出子节点
            const childNodes = el.childNodes;

            // 寻找文本节点
            childNodes.forEach(item => {
                // item.nodeType === 3 寻找文本类型节点
                if (item.nodeType === 3) {
                    const _value = item.nodeValue;

                    if (_value.trim().length) {
                        // 匹配 {{nameString}}
                        let _isValid = /\{\{(.+?)\}\}/.test(_value);
                        if (_isValid) {
                            // 将{{nameString}} 中的 nameString 取出
                            const _key = _value.match(/\{\{(.+?)\}\}/)[1].trim();
                            // 存储文本节点的父节点
                            this.domPool[_key] = item.parentNode;

                            // 初始化数据
                            item.parentNode.innerText = this.data[_key] || undefined;
                        }
                    }
                }
                // 递归寻找子节点
                item.childNodes && this.bindDom(item);
            });
        }
        // 给所有的输入框绑定事件
    bindInput(el) {

            // 获取输入框的值
            const _allInput = el.querySelectorAll('input');
            _allInput.forEach(input => {
                // 获取v-model 的值
                const _vModel = input.getAttribute('v-model');

                if (_vModel) {
                    // 监听输出框数据改变
                    input.addEventListener('keyup', this.handleInput.bind(this, _vModel, input));
                }

            });
        }
        // 输入框数据改变回调函数
    handleInput(key, input) {
            // 当输入框数据改变时,将数据保存在data中
            const _value = input.value;
            this.data[key] = _value;

        }
        // 设置数据
    setData(key, value) {
        this.data[key] = value
    }

}

/*
    1. 数据 --> 响应式数据 Object.defineProperty  Proxy
    2. input --> input/keyup --> 事件处理函数的绑定  --> 改变数值
    3. 相关的DOM  --> 数据绑定 ==> 绑定在一起
       操作数据的某个属性 --> 对应的DOM 就改变




*/

使用Proxy代理捕获

const reg_var = /\{\{(.+?)\}\}/;

class MVVM {
    constructor(el, data) {
        this.el = document.querySelector(el);

        this.data = data;
        this.domPool = {}
        this.init()
    }
    init() {
        this.initData()
        this.initDom()
    }

    initDom() {
        this.bindDom(this.el);
        this.bindInput(this.el);
        console.log(this.domPool)
    }
    initData() {
        const _this = this;
        // Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
        // 使用Proxy代理拦截捕获值的变化
        this.data = new Proxy(this.data, {
            get(target, key) {
                return Reflect.get(target, key)
            },
            set(target, key, value) {
                _this.domPool[key].innerHTML = value;
                return Reflect.set(target, key, value)
            }

        })
    }
    bindDom(el) {
            // 取出子节点
            const childNodes = el.childNodes;

            // 寻找文本节点
            childNodes.forEach(item => {
                // item.nodeType === 3 寻找文本类型节点
                if (item.nodeType === 3) {
                    const _value = item.nodeValue;

                    if (_value.trim().length) {
                        // 匹配 {{nameString}}
                        let _isValid = reg_var.test(_value);
                        if (_isValid) {
                            // 将{{nameString}} 中的 nameString 取出
                            const _key = _value.match(reg_var)[1].trim();
                            // 存储文本节点的父节点
                            this.domPool[_key] = item.parentNode;

                            // 初始化数据
                            item.parentNode.innerText = this.data[_key] || undefined;
                        }
                    }
                }
                // 递归寻找子节点
                item.childNodes && this.bindDom(item);
            });
        }
        // 给所有的输入框绑定事件
    bindInput(el) {

            // 获取输入框的值
            const _allInput = el.querySelectorAll('input');
            _allInput.forEach(input => {
                // 获取v-model 的值
                const _vModel = input.getAttribute('v-model');

                if (_vModel) {
                    // 监听输出框数据改变
                    input.addEventListener('keyup', this.handleInput.bind(this, _vModel, input));
                }

            });
        }
        // 输入框数据改变回调函数
    handleInput(key, input) {
            // 当输入框数据改变时,将数据保存在data中
            const _value = input.value;
            this.data[key] = _value;

        }
        // 设置数据
    setData(key, value) {
        this.data[key] = value
    }

}

/*
    1. 数据 --> 响应式数据 Object.defineProperty  Proxy
    2. input --> input/keyup --> 事件处理函数的绑定  --> 改变数值
    3. 相关的DOM  --> 数据绑定 ==> 绑定在一起
       操作数据的某个属性 --> 对应的DOM 就改变




*/

mustache

git地址:Mustache源码

diff算法

git地址:Diff算法
博客文章地址:Diff算法

函数、对象、数组的length 相关

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        // 字符串的 toString
        let len1 = ({} + {}).length;
        console.log(len1); // 30   ==> "[object Object][object Object]".length


        let arrNullAdd = [] + []; //  ==> 相当于 "" + ""
        console.log(typeof arrNullAdd) //string
        console.log(arrNullAdd) //"": string
        console.log(arrNullAdd.length) // 0 ==> "".length = 0;

        // 数组相加
        let arr = [12];
        let arrAdd = 4 + arr; //  "412" string   ==> 4+"12"
        let arr2 = 4 * arr; // 48 number ==> 4*"12"
        console.log(arrAdd) // "412" string 
        console.log(4 + "12")
        console.log(arr2) // 48 number
        console.log(4 * "12") // 48 number

        let arr3 = [1, 3];
        let arr4 = [2, 2];
        let arrHaveAdd = arr3 + arr4; // "1,32,2"   ==> "1,3" +"2,2"
        console.log(arrHaveAdd) // "1,32,2"
        console.log("1,3" + "2,2") // "1,32,2"
        let len2 = arrHaveAdd.length; // 6
        console.log(len2) // 6

        let arr5 = [1];
        let arr6 = [2];
        let arrOneAdd = arr5 + arr6; // "12"  string   ==> "1"+"2"
        console.log(arrOneAdd)


        // 函数的length
        console.log("--------------函数----------")

        /* 
            - 函數的length 属性
            
            length 属性指明函数的形参个数。
            length 是函数对象的一个属性值,指该函数有多少个必须要传入的参数,即形参的个数。
            形参的数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数。
            与之对比的是,  arguments.length 是函数被调用时实际传参的个数。

            Function 构造器本身也是个Function。他的 length 属性值为 1 。该属性 Writable: false, Enumerable: false, Configurable: true.
        */
        let funLen = (function() {}).length

        console.log(funLen)
        console.log(Function.length); /* 1 */

        console.log((function() {}).length); /* 0 */
        console.log((function(a) {}).length); /* 1 */
        console.log((function(a, b) {}).length); /* 2 etc. */

        console.log((function(...args) {}).length); //形参的数量不包括剩余参数个数,
        // 0, rest parameter is not counted

        console.log((function(a, b = 1, c) {}).length); //形参的数量不包括剩余参数个数,仅包括第一个具有默认值之前的参数个数。
        // 1, only parameters before the first one with
        // a default value is counted
    </script>
</body>

</html>

toString、valueOf和Object.defineProperty

如何使以下条件成立

if (a == 1 && a == 2 && a == 3) {
            console.log("you are win !!")
 }
 if (c === 1 && c === 2 && c === 3) {
            console.log("you are win !!")
  }
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>
    <script>
        //  tostring  与 valueOf 使用

        /* 
            tostring  与 valueOf 隐式调用
            https://blog.csdn.net/qq_45768871/article/details/110365885
        
        */

        // 使用valueOf  隐式调用
        let a = {
            _default: 0,

            valueOf: function() {
                return ++this._default;
            }

        }
        if (a == 1 && a == 2 && a == 3) {
            console.log("you are win !!")
        }

        // 使用toString 隐式调用
        let b = {
            _default: 0,
            toString: function() {
                return ++this._default;
            }

        }
        if (b == 1 && b == 2 && b == 3) {
            console.log("you are win !!")
        }

        // 使用 Object.defineProperty  绑定对象属性 + get 获取
        var _default = 0;

        Object.defineProperty(window, 'c', {
            get() {
                return ++_default;
            }
        })


        if (c === 1 && c === 2 && c === 3) {
            console.log("you are win !!")
        }
    </script>
</body>

</html>

Function

const test = new Function("a", 'b', 'c', "console.log(a+b+c)")
    // const test = new Function('a,b,c', "console.log(a+b+c)")
test(1, 3, 4) // 8

var a = 1,
    b = 2;

function fun() {
    var b = 3;
    return function(c) {
        console.log(a + b + c);
    }
}

var funTest = fun();
funTest(4); // 8

/* 
由 `Function 构造器创建的函数不会创建当前环境的闭包`,它们总是`被创建于全局环境`,
因此在运行时它们`只能访问全局变量和自己的局部变量`,
不能访问它们被 Function 构造器创建时所在的作用域的变量。这一点与使用` eval 执行创建函数`的代码不同。

*/

function fun2() {
    var b = 3;
    return new Function('c', "console.log(a+b+c)")
}

var funTest2 = fun2();
funTest2(4); // 7
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值