【问题标题】:Purpose of moving data through JSON通过 JSON 移动数据的目的
【发布时间】:2018-11-02 04:34:23
【问题描述】:

JSON.stringify(value) 会将 JavaScript 值转换为 JSON 字符串。 JSON.parse(value) 会将有效的 JSON 字符串转换为 JavaScript 值(对象、数组或其他 JSON 可用的原语)。

您为什么要获取一个 JavaScript 值并通过 JSON 移动它?意味着取一个值,然后对其进行字符串化,然后将其解析回来。据我所知,它没有任何用途,只会浪费机器资源。

我问这是因为我遇到了这个功能:

function ser(value) {
    return value == null ? null : JSON.parse(JSON.stringify(value))
}

它在 Marijn Heverbeke 的 Eloquent JavaScript 一书第 11 章的 crow-tech.js 中的 crow-tech.js 中找到,我想知道他为什么要这样做!

【问题讨论】:

  • 除非您尝试对其进行深度克隆,否则字符串化然后解析没有意义,但是您不能通过网络发送 plain Javascript 对象 - 所以,将其字符串化一端,发送JSON字符串,然后在另一端解析(例如,如果两端都使用JS)
  • 谢谢!我明白了:您可以通过此方法克隆(深拷贝)值,但删除了(函数/类型信息)。 (也不要将它用于大对象,因为它会产生性能问题 - 但可以用作小对象深度复制的快速简写,只有 JSON 数据)

标签: javascript json


【解决方案1】:

这是一种廉价的方式to deep clone an object in JavaScript。考虑以下几点:

function a() {
  const obj = {name: "fred"};
  
  b(obj);
  
  console.log(obj);
}


function b(obj) {
  obj.age = 42;
}

a();

函数a 将一个对象传递给b 以及它何时被修改。有时这就是你想要的,有时你想保留原始对象不被修改,所以你必须克隆它。 JavaScript 没有任何功能可以做到这一点,但 JSON.stringify -> JSON.parse 将为您创建一个新对象,以便用于克隆:

function a() {
  const obj = {name: "fred"};
  
  b(JSON.parse(JSON.stringify(obj)));
  
  console.log(obj);
}

function b(obj) {
  obj.age = 42;
}

a();

这很好地说明了什么会出错,但在现实世界中,事情并不总是那么简单。以上也可以通过对象的浅层克隆来完成

function a(){
  const obj = {name: "fred"};
  
  b(Object.assign({}, obj)); //shallow clone
  
  console.log(obj);
}

function b(obj) {
  obj.age = 42;
}

a();

但是,在以下情况下会失败:

const obj = {
  name: "fred",
  child: { name: "pebbles" }
};

const objClone = Object.assign({}, obj)

objClone.age = 42;
objClone.child.age = 2;

console.log('the "cloned" object was modified', objClone);

console.log("so was the original nested object", obj);

这是因为嵌套对象child没有被克隆,所以我们修改了父级的顶级克隆,然后修改了原始子级。这是深度克隆有用的时候:

const obj = {
  name: "fred",
  child: { name: "pebbles" }
};

const objClone = JSON.parse(JSON.stringify(obj));

objClone.age = 42;
objClone.child.age = 2;

console.log('the cloned object was modified', objClone);

console.log("none of the original was", obj);

这并不能解决所有问题。 JSON.stringify 然后JSON.parse 只适用于任何地方的非常简单的对象,它不会复制原型或函数。一些例子:

const obj = { name: "Alice" };
const proto = { age: 42 };

Object.setPrototypeOf(obj, proto);

console.log("assembled object", obj);

const clone = JSON.parse(JSON.stringify(obj));

console.log("cloned object", clone);

const objWithFunction = { name: "Bob", getAge: function() { return 42; } };

console.log("object with function assigned to property", objWithFunction);
console.log("getAge from original", objWithFunction.getAge());

const cloneWithFunction = JSON.parse(JSON.stringify(objWithFunction));

console.log("cloned object with function assigned to property", cloneWithFunction);
console.log("getAge from clone", cloneWithFunction.getAge());

function Person(name, age) {
  this.name = name;
  this.age = age;
}

const p = new Person("Carol", 42);

console.log("what is p:", p);
console.log("is p a Person?", p instanceof Person);

const clone = JSON.parse(JSON.stringify(p));
console.log("what is clone:", clone);
console.log("is clone a Person?", clone instanceof Person);
console.log("the clone is actually a plain object:", Object.getPrototypeOf(clone) == Object.prototype);

【讨论】:

  • 也从直接 cmets 中得到了这一切(导致另外两个 stackoverflow 问题)我知道当您通过 JSON 中的对象时,您也会丢失类型信息
  • @DanishALI 是的,你知道。我只是在最后添加了另一个示例以显示另一个故障点。尽管如此,如果您将普通对象(包括数组)嵌套到普通对象中,它可能会很有用。在这种情况下,stringify -> parse 肯定比编写自定义克隆实用程序更容易。我将添加一个示例来展示它的优势所在。
  • @DanishALI 当您可能需要深度克隆时,我添加了一个示例。只要您的对象很简单,那么它就是一种可靠且廉价的克隆方式。如果您有任何复杂的事情,它就会成为一个问题。
【解决方案2】:
JSON.parse(JSON.stringify(value))

这主要用于克隆对象。您不能直接将对象复制到另一个变量,因为对象是通过引用复制的。

let user = {name : "John"}

let newUser = user; // newUser and user refer to same object (ie same memory location.) . 

如果您修改user,那么newUser 也会被修改。这是因为对象是通过引用而不是按值复制的。

所以要进行对象复制,我们使用您指定的方法。

示例

let value = {"name": "John"}; // this is a object.

JSON.stringify(value) // were are changing the type object to string

字符串可以按值复制。

现在我们需要再次将字符串转换为对象,为此我们使用

let newValue = JSON.parse(JSON.stringify(value)); 

这会返回一个对象 - value 的克隆

现在 value 和 newValue 是两个不同的对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-11-05
    • 2015-07-08
    • 1970-01-01
    相关资源
    最近更新 更多