Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does changing metadata in JavaScript work?

Tags:

javascript

In the console, I get abc despite setting {writable:false}. Could you explain how changing metadata works?

let portfolio = {
  myFirstName: "Bob",
  myLastName: "Alice",
  myAge: 26,
  aboutMe: function() {
    return ("First Name: " + this.myFirstName + "; Last Name: " + this.myLastName + "; Age: " + this.myAge + ";");
  }
};
Object.defineProperty(portfolio, "myFirstName", { writable: false });
Object.defineProperty(portfolio, "myFirstName", { value: "abc" });
console.log(portfolio.myFirstName);
like image 240
Darkhan10 Avatar asked Jan 07 '21 11:01

Darkhan10


People also ask

What is meta data in Javascript?

Metadata is data (information) about data. <meta> tags always go inside the <head> element, and are typically used to specify character set, page description, keywords, author of the document, and viewport settings. Metadata will not be displayed on the page, but is machine parsable.

How does meta data work?

Metadata is created anytime a document, a file or other information asset is modified, including its deletion. Accurate metadata can be helpful in prolonging the lifespan of existing data by helping users find new ways to apply it. Metadata organizes a data object by using terms associated with that particular object.

What is metadata and why is it important?

Metadata is the data that describes other data. It can be used to identify, locate and describe digital objects, such as files, images, videos, and websites. It is as valuable as data, and experts recognize its ability to assist users in finding, organizing, and using information.

How do you define metadata?

Data that provide information about other data. Metadata summarizes basic information about data, making finding & working with particular instances of data easier. Metadata can be created manually to be more accurate, or automatically and contain more basic information.


2 Answers

in your 2nd line Object.defineProperty(portfolio, "myFirstName", { value: "abc" }); you are defining the property again.

You are not assigning a value. You are tossing out the old property and replacing it with a brand spanking new one. (Technically incorrect, it goes through a lot of steps to evaluate and apply values to property properties, but for simple understanding, I believe this suffices as understanding, as it feels like a new one in this scenario. Please read the link if you wish to have the complex truth)

To assign a new value use portfolio.myFirstName = "value here" and you see it's write protected.

let portfolio = {
  myFirstName: "Bob",
  myLastName: "Alice",
  myAge: 26,
  aboutMe: function() {
    return ("First Name: " + this.myFirstName + "; Last Name: " + this.myLastName + "; Age: " + this.myAge + ";");
  }
};
Object.defineProperty(portfolio, "myFirstName", { writable: false });
portfolio.myFirstName = "Alice";
console.log(portfolio.myFirstName);

to prevent the workaround, call Object.freeze() on the object after modifying its property. This will also have other side effects like not being able to edit the values of other properties.

let portfolio = {
  myFirstName: "Bob",
  myLastName: "Alice",
  myAge: 26,
  aboutMe: function() {
    return ("First Name: " + this.myFirstName + "; Last Name: " + this.myLastName + "; Age: " + this.myAge + ";");
  }
};
Object.defineProperty(portfolio, "myFirstName", { writable: false });
Object.freeze(portfolio);
Object.defineProperty(portfolio, "myFirstName", {value:"abc"});
console.log(portfolio.myFirstName);
like image 196
Tschallacka Avatar answered Oct 01 '22 00:10

Tschallacka


writable: false only has an effect on Object.defineProperty if configurable is also set to false. See step 7 of the ValidateAndApplyPropertyDescriptor algorithm:

Else if IsDataDescriptor(current) and IsDataDescriptor(Desc) are both true, then
  If current.[[Configurable]] is false and current.[[Writable]] is false, then
    If Desc.[[Writable]] is present and Desc.[[Writable]] is true, return false.
    If Desc.[[Value]] is present and SameValue(Desc.[[Value]], current.[[Value]]) is false, return false.
    Return true.

That's likely because as long as a property is configurable, nothing stops you from changing the value of writable back to true, e.g.

Object.defineProperty(
  portfolio,
  "myFirstName",
  {value: "abc", writable: true}
);

Note that any property declared as part of an object literal automatically has {writable: true, configurable: true, enumerable: true}.

Examples

Can't assign because writable and configurable are both false:

var obj = {};
Object.defineProperty(obj, 'test', {
  value: 42,
  configurable: false,
  writable: false,
  enumerable: true,
});
console.log(obj);
Object.defineProperty(obj, 'test', {value: 21});
console.log(obj);

Can assign a value because writable or configurable are true:

var obj = {};
Object.defineProperty(obj, 'test', {
  value: 42,
  configurable: true,
  writable: false,
  enumerable: true
});
console.log(obj);
Object.defineProperty(obj, 'test', {value: 21});
console.log(obj);


var obj = {};
Object.defineProperty(obj, 'test', {
  value: 42,
  configurable: false,
  writable: true,
  enumerable: true
});
console.log(obj);
Object.defineProperty(obj, 'test', {value: 21});
console.log(obj);

Lastly, if writable and configurable are both false but if the new value is the same as the current value, no error will be thrown since no change is actually being made to the property:

var obj = {};
Object.defineProperty(obj, 'test', {
  value: 42,
  configurable: false,
  writable: false,
  enumerable: true,
});
console.log(obj);
Object.defineProperty(obj, 'test', {value: 42});
console.log(obj);

Setting writable: false will work as expected for normal assignments (foo.bar = 42) because such assignments go through OrdinarySetWithOwnDescriptor which check the writable value of an existing property descriptor first.

like image 38
Felix Kling Avatar answered Oct 01 '22 00:10

Felix Kling