【问题标题】:Deep clone a function in javascript在javascript中深度克隆一个函数
【发布时间】:2020-09-01 22:39:38
【问题描述】:

我有一个对象:

nestedObj = {obj1:
{cat:'thing1', 
 scale: d3.scaleSequential(d3.interpolateGreens)},
 ...
}

然后我遍历一系列事物以创建在其他方面重复的对象:

things = ['thing1','thing2',...]
// A loop that creates:
nestedObj.obj2 = Object.assign({},nestedObj.obj1,{cat:thing2}}

然后在我的代码中,我迭代地设置每个函数的属性:

Object.keys(nestedObj)forEach(function(key){
 nestedObj[key].scale().domain([0,number])
}

这导致 obj1.scale 被 obj2.scale 覆盖,我认为是因为该函数是浅拷贝。 jQuery.extend(true)JSON.parse(JSON.stringify()) 似乎不起作用。有什么办法可以在不改变我的一般操作顺序的情况下解决这个问题吗?

谢谢!

【问题讨论】:

  • 在下面查看我的答案的更新。我认为您设置和使用scale 的方式存在不同的问题。

标签: javascript d3.js


【解决方案1】:

尚不清楚您的应用程序是否需要克隆函数,但有办法做到这一点。

我在下面包含了一个克隆功能。

function cloneFunction (fn) {
  let fnStr = fn.toString();
  let fnClone = new Function('return ' + fnStr);
  return fnClone();
}

let myFunc = function (a) { return a * 2; }
console.log('myFunc(1):', myFunc(1));

let mfClone = cloneFunction(myFunc);
console.log('mfClone(2):', mfClone(2));

这真的是函数克隆问题吗?

这个问题真的是克隆函数的问题吗?根据问题中提供的信息,似乎存在更根本的问题。

报告的故障项是scale

scale: d3.scaleSequential(d3.interpolateGreens)

此表达式将scale 的值设置为以下函数:

function scale(x) {
  return isNaN((x = +x))
    ? unknown
    : interpolator(
        k10 === 0
          ? 0.5
          : ((x = (transform(x) - t0) * k10),
            clamp ? Math.max(0, Math.min(1, x)) : x)
      );
}

然后,稍后,scale 在此语句中被调用:

nestedObj[key].scale().domain([0,number)

其中包括对scale() 的无参数调用。这将返回 undefined,因此 scale().domain([0,number) 会产生 TypeError

这里有一个代码 sn-p,它显示了问题的实际效果:

const result = document.getElementById('result');

function emitData() {
  let scale = d3.scaleSequential(d3.interpolateGreens);
  result.innerHTML = 'scale.toString():\n' + '"' + scale.toString() +
    '"\n\n';
  result.innerHTML += 'scale() returns:\n' + scale();
  result.innerHTML += '\n\nscale().domain([0,1]) returns:\n';
  try {
    let test = scale().domain([0,1]);
    result.innerHTML += test;
  } catch (e) {
    result.innerHTML += '"' + e.toString() + '"';
  }
}
pre {
  padding: 0.5rem;
  border: 1px solid #aaa;
  width: 95%;
  min-height: 6rem;
  white-space: pre;
  overflow-x: auto;
  display: inline-block;
}
<p id="client">Testing "scale = d3.scaleSequential(d3.interpolateGreens)"</p>
<button onclick="emitData()">Run Test</button><br/>
<pre id="result"></pre>
<script src="https://d3js.org/d3-array.v2.js"></script>
<script src="https://d3js.org/d3-color.v1.js"></script>
<script src="https://d3js.org/d3-format.v1.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.js"></script>
<script src="//d3js.org/d3-scale-chromatic.v0.3.js"></script>
<script src="https://d3js.org/d3-time.v1.js"></script>
<script src="https://d3js.org/d3-time-format.v2.js"></script>
<script src="https://d3js.org/d3-scale.v3.js"></script>

【讨论】:

  • 只有在没有依赖关系的情况下才能工作......a = (b) =&gt; b + b; c = (d) =&gt; d * a(d); 永远不会工作
  • @balexandre 如果您的意思是cloneFunction() 对函数进行了浅拷贝,那是真的。它不会克隆目标函数中的任何函数引用。
【解决方案2】:

您可以创建对象的深层克隆,如下所示:

const obj = {a: 'a'};
const deepClone = JSON.parse(JSON.stringify(obj));

【讨论】:

    猜你喜欢
    • 2013-10-11
    • 2010-12-22
    • 1970-01-01
    • 2016-12-20
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 2015-01-08
    • 2011-08-13
    相关资源
    最近更新 更多