qugemingzizhenmafan / blog

0 stars 0 forks source link

深克隆循环引用,柯里化 #2

Open qugemingzizhenmafan opened 4 years ago

qugemingzizhenmafan commented 4 years ago

获取数据类型

typeof和instanceof

typeof [] === 'array' // false 1 instanceof Number // false 所以这两种方式获取引用类型都不能一步到位

toString

每一个引用类型都有toString方法,默认情况下,如果此方法未被覆写,toString() 返回 "[object type]",其中type是对象的类型。 但是大部分引用类型都重写了toString方法,可以直接调用Object原型上未被覆盖的toString()方法,使用call来改变this指向来达到需要的效果。 image

qugemingzizhenmafan commented 4 years ago

环(循环引用)

环,即对象循环引用自己。例如:

a = {}
a.me = a

普通的深克隆遇到这种情况会因栈溢出报错

使用WeakMap

思路:拷贝循环引用对象时,去weakMap查询是否存在已拷贝对象,有则返回,而不是多次拷贝。


function clone (obj, hash = new WeakMap()) {
  if (hash.has(obj)) 
    return hash.get(obj)
  let newObj = Array.isArray(obj) ? [] : {}
  hash.set(obj, newObj)
  for (const key in obj) {
    newObj[key] = typeof(obj[key]) === 'object' ? clone((obj[key]), hash) : obj[key]
  }
  return newObj
}
qugemingzizhenmafan commented 4 years ago

函数柯里化

我的理解是,把一个传入全部参数得到结果的函数,变为多次调用来传入全部参数得到结果的函数。

应用场景

减少重复传递参数不变的部分

例如,平时开发中有这些代码

function url(protocol, domain, path) {
    return protocol + '://' + domain + '/' + path
}

会发现,前两个参数保持不变,但每次调用都需要传递。所以可以对其优化,仅传递最后一个变化的参数。

function url(path) {
   return 'http://mysite/' + path;
}

但是,如果这个库给其他人使用呢,每次都需要修改 “http://mysite/” 的部分,这种情况可以使用柯里化解决。

// curry
function curry (fn, ...args) {
  if (fn.length === args.length) {  
    return fn(...args)
  } else {
    return function anonymous(...newArgs) {
      const allArgs = [...args, ...newArgs]
      return curry(fn, ...allArgs)
    }
  }
}
cosnt myUrl = curry(url)('http', 'mysite')
myUrl('index.html')
cosnt yourUrl = curry(url)('https', 'yoursite')
yourUrl('index.html')