2

A bit of a JavaScript newbie here. I have the following 2 JavaScript code snippets here which does not do what I am expecting. The examples create an instance of the object "Person" in Example #1 using the "new" operator, and creates a prototype of "Person" in Example #2 using the ES5 Object.create() property.

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

// Using 'new' operator (working)
let person1 = new Person("Jack Rabit", 40, "Seattle");
Object.values(person1); // Shows "Jack Rabit", 40, "Seattle"

But, doing the following using the Object.create() property...does not show the first value of the Property (in this case "name"):

let person2 = Object.create(Person);
person2.name = "Will"; 
person2.age=41; 
person2.city="San Jose";

Object.values(person2); // Shows 41, "San Jose" (Does NOT show the value of the "name" property)

What is that I am missing?

5
  • Is there a reason you are adding those as properties to the b object? Where was b defined? Commented May 25, 2020 at 22:46
  • Seems like you want to add it to the person2 object. Commented May 25, 2020 at 22:46
  • Just corrected the variable assignments. Sorry! Commented May 25, 2020 at 22:49
  • 3
    It's probably because functions such as Person have a name property which is not enumerable, and therefore doesn't show up in Object.values. I'm not quite sure what happens when you assign the property on an object that inherits from it, though - or even what you're trying to do by using Object.create with a function object. Commented May 25, 2020 at 22:53
  • Yes, you are right. There seems to be a conflict with the property "name". Any other property name seems to work fine. Commented May 25, 2020 at 23:00

4 Answers 4

2

So usually when I use Object.create() I pass an object to be used at the prototype. You are currently passing a function as an argument. This way works

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

const person2 = Object.create(new Person());
person2.name = "Will"; 
person2.age=41; 
person2.city="San Jose";

Object.values(person2);

It probably has something to do with the fact that functions have their own name property for the function itself? But I'm not too sure

Edited:

Confirmed it is just because of the name property, changed name to title to avoid confusion:


const Person = function(title, age, city) {
    this.title = title;
    this.age = age; 
    this.city = city
}

const person2 = Object.create(Person);
person2.title = "Will"; 
person2.age=41; 
person2.city="San Jose";

Object.values(person2);
// ["Will", 41, "San Jose"]

Sign up to request clarification or add additional context in comments.

7 Comments

Better to use Person.prototype rather than new Person().
Agreed. Using Object.create() is outdated as well. Just stick to using the syntatic sugar that comes with classes and the new keyword.
Yes, there seems to a conflict between the property "name"....
I've had some trouble with using name in the past as well. Many people don't know but the window object has a name property that has an empty string for the value. Open up your console and just type window.name. Lead to a weird bug for me once.
@UzairAshraf outdated is a strong claim there. I don't know if I'd agree that class syntax is meant to replace classical JavaScript prototypal syntax. There seems to be a pretty large amount of people that seem to hate the new class syntax and see it as backwards and for people whose backgrounds are not "real" JavaScript programmers.
|
1

Object.create creates a new object with the given object as its [[prototype]].

You are trying to inherit the properties wrongly here. You are creating the person2 object with the constructor function Person as its prototype. All functions have a non-enumerable and non-writable property called name. You can see that by

Object.getOwnPropertyDescriptor(Person, "name")

The line person2.name = "Will"; is effectively trying to overwrite this property and does nothing. Also person2 has effectively become a function.

Here the correct usage would be

let person2 = Object.create(new Person()); 

2 Comments

Not sure if that is correct. Please see: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
"Also person2 has effectively become a function." - not quite, it might be instanceof Function, but it's not callable (person2()).
0

Object.create needs an object to create another object. So use the Person function to return an object. It should look like this:

 let Person = function(name, age, city) {
  return {
    name,
    age,
    city
  };
}

// Using 'new' operator (working)
let person1 = new Person("Jack Rabit", 40, "Seattle");

let person2 = Object.create(Person());
person2.name = "Will"; 
person2.age=41; 
person2.city="San Jose";

Comments

0

Object.create needs an object to create another object, as a result since Person while being a function(a function constructor to be exact) is also an object in javaScript. Therefore Object.create will not complain, but what is happening under the hood when its done this way:

let person2 = Object.create(Person);

person2 ends up being assigned some of the properties of a function named 'Person' (which in itself is not a function, it can t be called) this can be seen here:

// person2.name = 'Person'

// person2() Uncaught TypeError: person2 is not a function at <anonymous>:1:1

As one of the inherited properties of a Function, its name is read-only, therefore person2.name = 'some name' will have no effect. Function.name MDN docs

The new operator will call the constructor which will return an object while inheriting the prototype of the constructor function

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.