Javascript 从冻结的父对象创建新对象

Javascript 从冻结的父对象创建新对象,javascript,inheritance,prototypal-inheritance,Javascript,Inheritance,Prototypal Inheritance,本例创建一个对象,将其冻结,然后从冻结的对象创建一个新对象。 如果第二个对象试图更改测试属性,则它无法更改。它仍然被冰冻着 第一个对象的值为10 //Create an object and freeze it var first = { test: 10 }; Object.freeze(first); //Create a second object from the first one and //try and change the new test property (yo

本例创建一个对象,将其冻结,然后从冻结的对象创建一个新对象。 如果第二个对象试图更改测试属性,则它无法更改。它仍然被冰冻着 第一个对象的值为10

//Create an object and freeze it

var first = {
    test: 10
};
Object.freeze(first);

//Create a second object from the first one and
//try and change the new test property (you can't)

var second = Object.create(first);
second.test = 20;
console.log(second.test); //10
以下是我的问题:

是第二个。测试新对象上的新属性,还是它只是对冻结的第一个对象中属性的引用?
是否可以将冻结的
first.test
用作默认值,但如果需要,则让
second.test
覆盖它

我问这个问题的原因是因为我想用默认值将一个不可变的基本对象作为模板,然后用它来创建我可以自定义的新对象。最好的方法是什么


谢谢

second
实际上是一个新对象,
first
second
的原型。原因是什么

second.test = 20;
不起作用是因为在分配时,它将查找原型上的设置(即,
可配置的
可枚举的
可写的
[[Extensible]]
),如果其中任何设置为false,则不会分配给实例1。要直接分配给实例,您必须在
第二个
上使用
对象.defineProperty

var first = {
    test: 10
};
Object.freeze(first);

var second = Object.create(first);
Object.defineProperty(second, 'test', { value: 20, enumerable: true, configurable: true, writable: true });
console.log(second.test); // 20

1:

在您的情况下,
第二个
是对
第一个
的引用(就像您假设的那样)。一个解决方案是克隆您的对象。克隆对象没有内置方式—您必须自己完成,以下是如何实现的:

然后你可以这样使用它:

var first = {
    test: 10
};
Object.freeze(first);

// clone it into a new one
var second = clone(first);
second.test = 20;
console.log(second.test); // 20 where the first is locked
使用Object.assign

         var first = {
            test: 10
        };
        Object.freeze(first);

        //Create a second object from the first one and
        //try and change the new test property (you can't)

        var second = Object.assign({}, first, {
            test: 20
        });
        console.log(second.test); //20

在新版本的javascript中,可以使用对象分解来创建具有旧对象属性的新对象

const first = {
    test: 10
};
Object.freeze(first);

//Clone the object
const second = {...first};
second.test = 20;
console.log(second.test); // 20 where the first is locked

这种情况很简单,但是请注意,如果冻结对象包含对其他冻结对象的引用,并且您试图覆盖它们的属性,那么这仍然不起作用。对于简单的数据结构来说,这仍然是一种非常有用的技术,只是没有人认为这是一种创建不可变的万无一失的方法。没有内置的克隆方法吗?Object.assign几乎是一个克隆器,我得说。@loldrup这个问题在2013年得到了回答,我相信Object.assign是在ECMAScript2015规范中引入的,例如,即使现在IE11也需要多填充。无论如何,我同意答案可能应该更新/编辑,将其作为一个选项,并与时代同步。但要明确的是,“第二个是指第一个”不是真的。正如在公认的答案中所说,“第一个是第二个的原型”@PanuLogic,尽管您使用的术语在JS上下文中确实更好(我同意)。然而,从我的理解来看,这两个短语的意思是相同的?有语义上的区别吗?我的意思是,在JS中,作为“原型”就是“有参考”,不是吗?是的,单词可以有很多不同的含义。我的理解是,当你有一个“参考”时,你实际上是在谈论“同一件事”。然而,一个对象的原型是另一个对象,它是另一个对象的原型。原型的属性可能比它是原型的对象少,并且属性的值可能不同。原型为对象“B”的对象“A”确实引用了“B”。但是“B”并没有提到“a”。看来“second”的行为就好像它也被冻结了一样。它继承了它的“冻结”。但如果调用Object.isfronged(第二个),我认为返回false
const first = {
    test: 10
};
Object.freeze(first);

//Clone the object
const second = {...first};
second.test = 20;
console.log(second.test); // 20 where the first is locked