Javascript 克隆函数实现中“this”关键字的执行上下文

Javascript 克隆函数实现中“this”关键字的执行上下文,javascript,Javascript,我正在研究一个函数,该函数创建所提供对象的副本。除了涉及这个关键字的那一行之外,我基本上了解正在发生的事情。我明白,这个关键字的原始设计是指指向类定义中的对象实例,如果我们回到从C++借用的这个关键字的起源。但是JavaScript决定使用这个关键字来提供一个额外的特性,即携带一个指向执行上下文的链接。在下面的例子中,我试图理解为什么我们要使用这个关键字。如果你有任何想法,我将非常感激 function clone(obj) { const replace = {}; let idx =

我正在研究一个函数,该函数创建所提供对象的副本。除了涉及这个关键字的那一行之外,我基本上了解正在发生的事情。我明白,这个关键字的原始设计是指指向类定义中的对象实例,如果我们回到从C++借用的这个关键字的起源。但是JavaScript决定使用这个关键字来提供一个额外的特性,即携带一个指向执行上下文的链接。在下面的例子中,我试图理解为什么我们要使用这个关键字。如果你有任何想法,我将非常感激

function clone(obj) {
  const replace = {};
  let idx = 0;

  const undefCache = [];

  const replacer = (key, value) => {
    let result;
    if (value === undefined) {
      result = '__undefined__';
    } else if (typeof value === 'symbol' || typeof value === 'function') {
      const keyIdx = `__replaced__${idx}`;
      idx += 1;
      replace[keyIdx] = [this, key]; // I understand mostly what's happening except for the line
      result = keyIdx;
    } else {
      result = value;
    }
    return result;
  };

  function reviver(key, value) {
    let result;
    if (value === '__undefined__') {
      undefCache.push([this, key]);// I understand mostly what's happening except for the line
    } else if (replace[value] !== undefined) {
      result = replace[value][0][key];
    } else {
      result = value;
    }
    return result;
  }

  const json = JSON.stringify(obj, replacer);
  console.log(json);
  const newObject = JSON.parse(json, reviver);
  undefCache.forEach(el => {
    const [o, key] = el;
    o[key] = undefined;
  });
  return newObject;
}

const source = {
  a: 2,
  b: '2',
  c: false,
  g: [
    { a: { j: undefined }, func: () => {} },
    { a: 2, b: '2', c: false, g: [{ a: { j: undefined }, func: () => {} }] }
  ]
};

const targetOne = clone(source);
console.log(targetOne);

在对特殊值使用JSON.parse/stringify进行序列化/反序列化时,它用于处理嵌套对象

在replace/reviver函数中,此上下文是序列化程序stringify或反序列化程序解析正在处理的当前对象

例如,对于以下对象:

myObject = {
    "foo": {
        "bar": function () {}
    },
    "bar": "Different bar"
}
当它处理项目myObject[foo][bar]时,替换程序中的这个将是对myObject[foo]的引用,key=bar,value=function{}。这很有用,因为如果没有引用,我们就不知道是在处理myObject[bar]还是myObject[foo][bar]

因此,当它被保存到数组中时,它实际上只是保存了pair=[myObject[foo],bar]。稍后恢复时,对于这些对中的每一对,只需执行对[0][对[1]]即可恢复myObject[foo][bar]

这同样适用于复活者和未定义者。这里的问题是,恢复程序不能返回undefined并将值设置为undefined,因此代码段会记住哪些键是这样的,并对对象的副本进行后期处理以正确设置它们


Ref:

查看调用方API/契约,了解这是什么设置--。。然后调用[reviver],对象包含如下处理的属性,属性名称为字符串,属性值为参数。。。在这种情况下,考虑到它与表达函数RealValueObjt属性、键、值……的方式没有什么不同,除了通过此方式访问ObjutWess属性。