Giter VIP home page Giter VIP logo

blog's People

Contributors

tarosunn avatar

Watchers

 avatar

blog's Issues

node链接mysql报错

{ Error: ER_NOT_SUPPORTED_AUTH_MODE: Client does not support authentication protocol requested by server; consider upgrading MySQL client
  ........
  code: 'ER_NOT_SUPPORTED_AUTH_MODE',
  errno: 1251,
  sqlMessage:
   'Client does not support authentication protocol requested byserver; consider upgrading MySQL client',
  sqlState: '08004',
  fatal: true }

查了一下mysql8.0加密方式变了?
不过执行ALTER USER 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY '密码';就可以正常链接了

探究深拷贝

深拷贝

深拷贝与浅拷贝的区别

浅拷贝:
image.png
深拷贝:
image.png

简单版

代码

JSON.parse(JSON.stringify(target))

缺点

  1. 不支持循环引用
  2. 不支持函数、new Date 等数据类型

基本版

代码

浅拷贝 + 递归

const baseClone = target => {
	if(typeof target === 'object') {
  	let cloneTarget = {}
    for(const key in target) {
    	cloneTarget[key] = baseClone(target[key])
    }
    return cloneTarget
  } else {
  	return target
  }
}

测试

const test1 = {
	name: 'sun',
  age: 25,
  child: {
  	name: 'sun1',
    age: 1
  }
}
const test2 = baseClone(test1)
test2.child.age = 2
console.log(test1, test2)

image.png
这一版已经解决了不支持函数

缺点

  1. 不支持循环引用
  2. 不支持数组、new Date 等数据类型

兼容数组版

代码

const ArrayClone = target => {
  if(typeof target === 'object') {
    let cloneTarget = Array.isArray(target) ? [] : {}
    for(const key in target) {
      cloneTarget[key] = ArrayClone(target[key])
    }
    return cloneTarget
  } else {
    return target
  }
}

测试

const test1 = {
  name: '123',
  age: 1,
  obj: {
    name: '12',
    age: 2
  },
  fun: () => {
    console.log(123)
  },
  arr: [1, 2, 3]
}
const test2 = ArrayClone(test1)
test2.arr = [2, 3, 4]
console.log(test1, test2)

image.png

缺点

  1. 不支持循环引用
  2. 其他对象数据类型

兼容循环引用

当出现循环引用时,会导致堆栈内存溢出
image.png
可以使用 Map 数据类型来存储,Map类型的键可以是引用类型

const MapClone = (target, map = new Map()) => {
  if(typeof target === 'object') {
    let cloneTarget = Array.isArray(target) ? [] : {}
    if(map.get(target)) {
      return map.get(target)
    }
    map.set(target, cloneTarget)
    for(const key in target) {
      cloneTarget[key] = MapClone(target[key], map)
    }
    return cloneTarget
  }else {
    return target
  }
}

测试

const test1 = {
  name: '123'
}
const test2 = MapClone(test1)
test2.test2 = test2

image.png

问题

但由于Map 类型的键是强引用,无法及时的被垃圾回收器回收,容易造成内存泄露,那么可以使用WeakMap,WeakMap的键是弱引用,那么垃圾回收器会帮助我们自动回收

使用 Map

function usageSize() {
  const used = process.memoryUsage().heapUsed;
  return Math.round((used / 1024 / 1024) * 100) / 100 + "M";
}

global.gc();
console.log(usageSize());

let arr = new Array(10 * 1024 * 1024);
const map = new Map();

map.set(arr, 1);
global.gc();
console.log(usageSize());

arr = null;
global.gc();
console.log(usageSize());

执行 node --expose-gc map.js
image.png

使用WeakMap

function usageSize() {
  const used = process.memoryUsage().heapUsed;
  return Math.round((used / 1024 / 1024) * 100) / 100 + "M";
}

global.gc();
console.log(usageSize());

let arr = new Array(10 * 1024 * 1024);
const map = new WeakMap();

map.set(arr, 1);
global.gc();
console.log(usageSize());

arr = null;
global.gc();
console.log(usageSize());

执行 node --expose-gc weakmap.js
image.png
可以看到,Map 的键的强引用,无法手动被垃圾回收器回收

代码

const MapClone = (target, map = new WeakMap()) => {
  if(typeof target === 'object') {
    let cloneTarget = Array.isArray(target) ? [] : {}
    if(map.get(target)) {
      return map.get(target)
    }
    map.set(target, cloneTarget)
    for(const key in target) {
      cloneTarget[key] = MapClone(target[key], map)
    }
    return cloneTarget
  }else {
    return target
  }
}

兼容其他类型

JavaScript 中的引用数据类型不止包括 对象和数组,还包括基本数据类型的对应的引用类型,如 String Date...
image.png
可以通过 Object.prototype.toString 方法区别

代码

const toRawType = value => {
  let _toString = Object.prototype.toString
  let str = _toString.call(value)
  return str.slice(8, -1)
}

const cloneReg = target => {
  const reFlags = /\w*$/
  const result = new target.constructor(target.source, reFlags.exec(target))
  result.lastIndex = target.lastIndex
  return result
}

const cloneSymbol = target => {
  return Object(Symbol.prototype.valueOf.call(target))
}

const cloneOtherType = target => {
  const constrFun = target.constructor
  switch (toRawType(target)) {
    case 'Boolean':
    case 'Number':
    case 'String':
    case 'Error':
    case 'Date':
      return new constrFun(target)
    case 'RegExp':
      return cloneReg(target)
    case 'Symbol':
      return cloneSymbol(target)
    case 'Function':
      return target
    default:
      return null;
  }
}


const clone = (target, map = new WeakMap()) => {
  if(typeof target !== 'object' || target === null) {
    return target
  }
  const type = toRawType(target)
  let cloneTarget = null
  if(map.get(target)) {
    return map.get(target)
  }
  map.set(target, cloneTarget)

  if(type !== 'Set' && type !== 'Map' && type !== 'Array' && type !== 'Object') {
    return cloneOtherType(target)
  }

  if(type === 'Set') {
    cloneTarget = new Set()
    target.forEach(value => {
      cloneTarget.add(clone(value, map))
    })
    return cloneTarget
  }

  if(type === 'Map') {
    cloneTarget = new Map()
    target.forEach((value, key) => {
      cloneTarget.set(key, clone(value, map))
    })
    return cloneTarget
  }

  if(type === 'Array' || type === 'Object') {
    cloneTarget = (type === 'Array' ? new Array() : new Object())
    for(const key in target) {
      cloneTarget[key] = clone(target[key], map)
    }
  }
  return cloneTarget
}

测试代码

const map = new Map();
map.set('key', 'value');

const set = new Set();
set.add('value1');
set.add('value2');

const target = {
    field1: 1,
    field2: undefined,
    field3: {
        child: 'child'
    },
    field4: [2, 4, 8],
    empty: null,
    map,
    set,
    bool: new Boolean(true),
    num: new Number(2),
    str: new String(2),
    symbol: Object(Symbol(1)),
    date: new Date(),
    reg: /\d+/,
    error: new Error(),
    func1: () => {
        console.log('hello friend!');
    },
    func2: function (a, b) {
        return a + b;
    }
};

const result = clone(target);
console.log(result);
console.log(result.field3 === target.field3)
console.log(result.field4 === target.field4)
console.log(result.map === target.map)
console.log(result.num === target.num)
console.log(result.reg === target.reg)

image.png

参考资料

  1. Write a Better Deep Clone Function in JavaScript
  2. 深拷贝的终极探索(99%的人都不知道)
  3. 你不知道的 WeakMap
  4. 如何 clone 一个正则?
  5. ECMAScript 6 入门---Set 和 Map 数据结构

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.