Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript properties with setter methods aren't real properties?

function Name(first, last) {
  this.first = first;
  this.last = last;
  this.fullName = first + " " + last
}

Name.prototype = {
  get fullName() {
    return this.first + " " + this.last;
  },

  set fullName(name) {
    var names = name.split(" ");
    this.first = names[0];
    this.last = names[1];
  }
};

var person = new Name("Foo", "Bar");
// person.fullName = "Foo Bar"
person.hasOwnProperty("fullName") // false

Is there a way to return the properties?

like image 356
iksose Avatar asked Dec 28 '14 02:12

iksose


People also ask

Are getters and setters bad in JavaScript?

Getter and setter methods (also known as accessors) are dangerous for the same reason that public fields are dangerous: They provide external access to implementation details.

What is the difference between getter and setter in JavaScript?

Getters and setters allow us to define Object Accessors. The difference between them is that the former is used to get the property from the object whereas the latter is used to set a property in an object.

How do setters work in JavaScript?

In JavaScript, a setter can be used to execute a function whenever a specified property is attempted to be changed. Setters are most often used in conjunction with getters to create a type of pseudo-property. It is not possible to simultaneously have a setter on a property that holds an actual value.

What is the purpose of getter and setter methods in JavaScript?

Getters and setters allow you to define Object Accessors (Computed Properties).


2 Answers

hasOwnProperty does not check down the object's prototype chain, in your case person get and set are inherited through the prototype chain

hasOwnProperty

Every object descended from Object inherits the hasOwnProperty method. This method can be used to determine whether an object has the specified property as a direct property of that object; unlike the in operator, this method does not check down the object's prototype chain.

function Name(first, last) {
    this.first = first;
    this.last = last;
    this.fullName = first + " " + last;
}
var person = new Name("Foo", "Bar");
console.log(person.fullName);
console.log(person.hasOwnProperty("fullName")); // true
console.log(Name.prototype.hasOwnProperty("fullName")); // false

for (var prop in person) {
    console.log(prop);
}

console.log('');

Name.prototype = {
    get fullName() {
        return this.first + " " + this.last;
    },

    set fullName(name) {
        var names = name.split(" ");
        this.first = names[0];
        this.last = names[1];
    }
};
var person2 = new Name("Foo", "Bar");
console.log(person2.fullName);
console.log(person2.hasOwnProperty("fullName")); // false
console.log(Name.prototype.hasOwnProperty("fullName")); // true

Quote @JLRishe

When you use this.fullName = "..."; in your constructor, you are invoking the inherited setter, not adding a new property.

If you want to find such properties, you can just use a for... in statement:

for (var prop in person) {
    console.log(prop);
}
like image 80
alessandro Avatar answered Sep 28 '22 08:09

alessandro


As InvernoMuto points out, Object.hasOwnProperty("fullName") returns false because it is not person's own property; it is inherited via the prototype chain. When you use this.fullName = "..."; in your constructor, you are invoking the inherited setter, not adding a new property.

If you want to find such properties, you can:

  1. Use a for..in loop:
for (var prop in person) {
    // this will iterate over EVERY property in person's prototype chain
}
  1. Attach the properties in your constructor:

function Name(first, last) {
  this.first = first;
  this.last = last;

  Object.defineProperty(this, "fullName", {
    get: function() {
      return this.first + " " + this.last;
    },
    set: function(name) {
      var names = name.split(" ");
      this.first = names[0];
      this.last = names[1];
    }
  });
}

var person = new Name("Ronald", "McDonald");
console.log(person.hasOwnProperty("fullName")); // true
  1. Create a whole new object in your constructor, using the get/set syntax that you have there. In this case, we wouldn't use the new keyword but just call the function:

function Name(first, last) {
    return {
        first: first,
        last: last, 

        get fullName() { return this.first + " " + this.last; },
        set fullName(name) { 
            var names = name.split(" ");
            this.first = names[0];
            this.last = names[1];
        }
    };
};

var person = Name("Ronald", "McDonald");
console.log(person.hasOwnProperty("fullName")); // true
like image 44
JLRishe Avatar answered Sep 28 '22 08:09

JLRishe