0

Is there a way I can change a property in an object from one of it's own methods?

let dog = {
  name: 'shar-pei',
  changeName: () => {
    // reassign name property
  }
}
nandesuka
  • 699
  • 8
  • 22
  • 2
    `dog.name = "any name";` – DecPK Jun 22 '21 at 22:58
  • 2
    @decpk That would be a fixed reference though - if `dog` is then used as a `prototype` later on it wouldn't work. You could use `this` instead of `dog` but because `changeName` is a `=>` function it has different binding rules. – Dai Jun 22 '21 at 22:59

2 Answers2

0

You might think this would work...

let dog = {
  name: 'shar-pei',
  changeName: () => {
    dog.name = "foobar";
  }
}

console.log( dog.name ); // "shar-pei"

dog.changeName();

console.log( dog.name ); // "foobar"

And this does work - provided you only ever have one dog value.

It doesn't work if you clone dog (using Object.create) or use the dog value as prototype:

let dog = {
  name: 'shar-pei',
  changeName: () => {
    dog.name = "foobar";
  }
}

console.log( dog.name ); // "shar-pei"
dog.changeName();
console.log( dog.name ); // "foobar"

// Reset dog's name:
dog.name = "shar-pei";

// Clone a new dog with a different name:
let gromit = Object.create( dog );
gromit.name = "Gromit";

console.log( dog.name ); // "shar-pei"
console.log( gromit.name ); // "Gromit"

// Q: What do you think happens if we do this?
gromit.changeName();

// A: Gromit's name didn't change...
console.log( "gromit's name: " + gromit.name ); // "Gromit"
// ...but `dog`'s did!
console.log( "dog's name: " + dog.name ); // "foobar"

Unfortunately you can't use this inside a =>-style function when used with an object-initializer because it has a fixed, immutable this-binding.

The solution is to use a normal function, like so:

let dog = {
    name: 'shar-pei',
    changeName: function() {
        this.name = "foobar";
    }
};

console.log( dog.name ); // "shar-pei"
dog.changeName();
console.log( dog.name ); // "foobar"

// Reset dog's name:
dog.name = "shar-pei";

// Clone a new dog with a different name:
let gromit = Object.create( dog );
gromit.name = "Gromit";

console.log( dog.name ); // "shar-pei"
console.log( gromit.name ); // "Gromit"

// Q: What do you think happens if we do this?
gromit.changeName();

// A: Gromit's name now changes to "foobar"
console.log( "gromit's name: " + gromit.name ); // "gromit's name: foobar"
// ...and `dog`'s name remains unchanged:
console.log( "dog's name: " + dog.name ); // "dog's name: shar-pei"

Though consider using a class or prototype instead:

/** Dog constructor: */
function Dog() {
    this.name = "";
}
Dog.prototype.changeName = function() {
    this.name = "foobar";
};

// Usage:

let sharPei = new Dog();
sharPei.changeName();

let gromit = new Dog();
gromit.changeName();
Dai
  • 141,631
  • 28
  • 261
  • 374
0

The reason why is not working is that you're using arrow functions. I recommend you have a read on arrow functions and this to understand a bit better where in the context you are when using arrow functions.

If you can change your function to a normal method and then use this should be enough to get it working.

Something like this:

let dog = {
  name: 'shar-pei',
  changeName: function() {
    // reassign name property
    this.name = 'other-name';
  }
}
console.log(dog.name);
dog.changeName();
console.log(dog.name);
gugateider
  • 1,983
  • 2
  • 13
  • 17