首页 > 解决方案 > 克隆函数实现中“this”关键字的执行上下文

问题描述

我正在研究一个创建提供对象副本的函数。this除了涉及关键字的行之外,我主要了解正在发生的事情。我确实明白,this如果我们回到thisC++. 但是 JavaScript 决定使用this关键字来提供一个额外的功能,携带一个指向执行上下文的链接。在下面的示例中,我试图了解我们为什么使用this关键字。如果您有任何想法,我将不胜感激。

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);

标签: javascript

解决方案


It's used to handle nested objects when doing serialization/deserialization with JSON.parse/stringify on special values.

Within the replacer/reviver functions, the this context is the current object that the serializer (stringify) or deserializer (parse) is working on.

For example, for the object below:

myObject = {
    "foo": {
        "bar": function () {}
    },
    "bar": "Different bar"
}

When it's processing the item myObject["foo"]["bar"], this inside the replacer will be a reference to myObject["foo"] with key = "bar" and value = function () {}". This is useful because without the reference, we wouldn't know whether we were processing myObject["bar"] or myObject["foo"]["bar"].

Thus when it is saved into the array, it really just saved pair = [myObject["foo"], "bar"]. Later when it's recovered, for each of these pairs, it can just do pair[0][pair[1]] to recover myObject["foo"]["bar"].

This works similarly with the reviver and undefined. Here the problem is that the reviver cannot return undefined and have the value set to undefined, so instead the code snippet remembers which keys are like this and post-processes the copy of the object to set them properly.

Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify#The_replacer_parameter


推荐阅读