关于Object.create()与对象字面量的混淆

huangapple go评论75阅读模式
英文:

Confusion about Object.create() vs Object Literals

问题

I am currently completing the front-end web development course offered by Meta.

I am confused with the usage of Object.create() and Object Literals. Let's use the following code for reference:

let bird = {
  hasWings: true,
  canFly: true,
  hasFeathers: true
};

let eagle = bird;
console.log("Eagle can fly: ", eagle.canFly); //"Eagle can fly: " true
eagle.canFly = false;
console.log("Eagle can fly: ", eagle.canFly); // "Eagle can fly: " false

let penguin = Object.create(bird);
penguin.canFly = false;
console.log("Penguin can fly: ", penguin.canFly); //"Penguin can fly: " false

If I can achieve the same results by simply using the object literals like in the case of eagle, then what difference does using Object.create()` make in the case of penguin?

I tried to take help from ChatGPT, but it was confusing.

英文:

I am currently completing the front-end web development course offered by Meta.

I am confused with the usage of Object.create() and Object Literals. Let's use the following code for the reference:

let bird = {
  hasWings: true,
  canFly: true,
  hasFeathers: true
};

let eagle = bird;
console.log("Eagle can fly: ", eagle.canFly); //"Eagle can fly: " true
eagle.canFly = false;
console.log("Eagle can fly: ", eagle.canFly); // "Eagle can fly: " false

let penguin = Object.create(bird);
penguin.canFly = false;
console.log("Penguin can fly: ", penguin.canFly); //"Penguin can fly: " false

If I can achieve the same results by simply using the object literals like in case of eagle, then what difference does using Object.create()` make in the case of penguin?

I tried to take help from ChatGPT, but it was confusing.

答案1

得分: 0

使用您的代码,我可以重写类似于以下的内容:

let bird = {
  hasWings: true,
  canFly: true,
  hasFeathers: true
};

let eagle = bird;
console.log("Eagle can fly: ", eagle.canFly); // "Eagle can fly: " true
eagle.canFly = false;
console.log("Eagle can fly: ", eagle.canFly); // "Eagle can fly: " false

// 但是您也改变了BIRD!!!
console.log("Bird can fly: ", bird.canFly); // Bird cannot fly :(
bird.canFly = true;
console.log("Bird can fly: ", bird.canFly); // Bird can fly again :)
// 但是您又改变了EAGLE!
console.log("Eagle can fly: ", eagle.canFly); // Eagle can fly again, even if you set false before

为了避免这些问题,Object.create() 将为您提供一个新的对象,不包含来自其他对象的引用。

let eagle = Object.create(bird);

类似这样。

英文:

Using your code, I could rewrite something like this:

let bird = {
  hasWings: true,
  canFly: true,
  hasFeathers: true
};

let eagle = bird;
console.log("Eagle can fly: ", eagle.canFly); //"Eagle can fly: " true
eagle.canFly = false;
console.log("Eagle can fly: ", eagle.canFly); // "Eagle can fly: " false

// but you changed BIRD also!!!
console.log("Bird can fly: ", bird.canFly); // Bird cannot fly :(
bird.canFly = true;
console.log("Bird can fly: ", bird.canFly); // Bird can fly again :)
// but you changed EAGLE again!
console.log("Eagle can fly: ", eagle.canFly); // Eagle can fly again, even if you set false before

To avoid those problems, Object.create() will give you a new object without any references from other objects.

let eagle = Object.create(bird);

Something like that.

答案2

得分: 0

我相信这里有很多细节需要解释,所以让我们逐一开始。

根据定义,Object.create 创建另一个对象并将其原型设置为您作为第一个参数传递的对象。

基本上在您的情况下,当您创建penguin对象时,您检索到一个空对象并将其原型设置为bird对象。
尝试记录penguin对象并查看其属性,您会感到非常惊讶。

这是JavaScript用来管理继承的一种称为原型链的机制。

正如您所看到的,Object.create方法并不像看起来那么直接,我鼓励您阅读以下链接以了解更多信息。

Object.create

对象原型

对象字面量Object.create方法之间的区别在于它们用于在非常基本的层面实现不同的结果。

另外,请记住,当您直接将bird对象分配给eagle时,您并未存储其值,而是存储了它的实际引用。

birdeagle变量都指向内存中的同一对象,这就是为什么更改一个对象中的属性将反映在另一个对象中的原因。现在,如果您希望在eagle变量中存储bird对象的新副本,我建议使用以下方法:

let bird = {
  hasWings: true,
  canFly: true,
  hasFeathers: true
};

let eagle = { ...bird };

这样做将让您拥有两个独立的对象,修改一个对象中的值将不会影响另一个对象。

英文:

I believe there are a lot of details that we need to explain here, so let us start one by one.

The Object.create by definition creates an another object and sets its prototype to the object that you have passed as the first argument.

Essentially in your case when you created the penguin object, you retrieved an empty object and set its prototype to the bird object.
Try logging the penguin object and take a look at its properties, you will be much surprised.

This is a mechanism that Javascript uses in order to manage inheritance called prototype chaining.

As you can see the Object.create method is not as straight forward as it seems and I would encourage you to read more about it on the following links.

Object.create

Object prototypes

The difference between using Object Literals and the Object.create method is that they are used to achieve different results in a very fundamental level.

Additionally, keep in mind that when you are assigning the bird object directly to the eagle, you are not storing its value, but its actual reference.

Both the bird, and the eagle variables are pointing out to the same object in memory and that is why changing a property in one of the objects will be reflected in the other one. Now essentially if you want to store a fresh copy of the bird object in the eagle variable I would suggest using the following method:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let bird = {
  hasWings: true,
  canFly: true,
  hasFeathers: true
};

let eagle = {...bird};

<!-- end snippet -->

Doing this, will let you have two independent objects and modifying the values in one object will not affect the other.

答案3

得分: 0

好的,以下是翻译好的部分:

  1. 要充分理解Object.create,你必须了解原型继承。
  2. 当你执行类似 let eagle = bird 的操作时,你并没有创建一个新的对象eagle。你只是创建了一个新的引用eagle,它指向了bird对象。

从你的代码中,我看到你尝试做以下操作:

  1. 创建一个通用的鸟对象。
  2. 创建一个鹰对象,它是一种鸟。
  3. 创建一个企鹅对象,它也是一种鸟。

你希望鹰和企鹅可以'继承'鸟的属性。

  1. 使用对象字面量创建一个通用的鸟对象:

     let bird = {
         hasWings: true,
         canFly: true,
         hasFeathers: true
     };
    
  2. 创建一个鹰对象:

     let eagle = Object.create(bird);
    

通过使用object.create,你正在设置eagle的原型为bird。在控制台中尝试以下代码:

Object.getPrototypeOf(eagle) === bird

它会评估为true。

现在,当你调用eagle.canFly 时,JavaScript运行时会检查eagle对象是否有canFly属性。它没有。因此,它将沿着原型链向上查找并检查bird。bird确实有canFly属性,而且它的值为true。因此,eagle.canFly将评估为true。

老实说,这里有很多需要修复的地方。我实际上写了一系列关于原型继承的文章。我建议你阅读它们:

第1部分 - 理解原型链

第2部分 - 使用Object.create的原型继承

第3部分 - 使用构造函数的原型继承

英文:

Okay, there is a lot missing here.

  1. To fully appreciate Object.create, you must understand prototypal inheritance
  2. When you do something like let eagle = bird, you are not creating a new object, eagle. You are just creating a new reference, eagle, that is pointing to the bird object

From your code, I see that you are trying to do the following:

  1. Create a generic bird
  2. Create an eagle, which is a type of bird
  3. Create a penguin, which is a type of bird

You want eagles and penguins to 'inherit' the properties of birds.

  1. Create a generic bird using an object literal

    let bird = {
        hasWings: true,
        canFly: true,
        hasFeathers: true
    };
    
  2. Create an eagle

    let eagle = Object.create(bird)
    

By using object.create, you are setting the prototype of eagle to be bird.
Try this in the console:

Object.getPrototypeOf(eagle) === bird

It will evaluate to true.

Now, when you call eagle.canFly, the JavaScript runtime will check if the eagle object has a canFly property. It does not. So it'll move up the prototype chain and check bird. bird does have the canFly property, and its set to true. Hence eagle.canFly will evaluate to true.

Honestly, there's a lot to fix here. I actually wrote a series on prototypal inheritance. I recommend going though it:

Part 1 - Understanding the Prototype Chain

Part 2 - Prototypal Inheritance with Object.create

Part 3 - Prototypal Inheritance with Constructor Functions

huangapple
  • 本文由 发表于 2023年6月13日 00:05:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76458429.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定