Desciptor values are true - javascript

let obj = {windows : 10,wheels : 100,seats : 99};
console.log(Object.getOwnPropertyDescriptor(obj, 'wheels'))
Output:
Object { value: 100, writable: true, enumerable: true, configurable: true }
I read on an article that the default values of an object's descriptor are false, but the following code shows otherwise. Can someone tell me the mistake?

I read on an article that the default values of an object's descriptor are false...
That's only when you call Object.defineProperty or its cousin defineProperties (or use the second argument of Object.create), the defaults for the flags in the descriptor object are all false:
let obj = {};
Object.defineProperty(obj, "wheels", {
value: 100,
});
console.log(Object.getOwnPropertyDescriptor(obj, "wheels"))
When you create a property via direct assignment as you are in the question, they all default to true.

Related

Why I cant delete getters/setters defined in Object.defineProperties?

Somehow I can read the property of a getter, but I can't delete it.
(I can delete getters/setters defined w/o using Object.defineProperties)
var hello = {
get num() {
return 123;
}
}
delete hello.num;
// returns true
However,
var hello = {};
Object.defineProperties(hello, {
num: {
get() {
return 123;
}
}
}
delete hello.num;
// returns false
The problem is that using the .defineProperties their is a property called writable
By default, it is set to False set it to true there is also a property called configurable
set it to true as well You can see the following code example to achieve this
'use strict'
Object.defineProperty(window, 'hello',{
get: ()=>"hello to you!",
configurable: true //make this true
and for the writeable property you can set it like this:
Object.defineProperty(obj, 'key', {
enumerable: false,
configurable: True,
writable: True,
value: 'static'
});

Delete an object within an outer object not working

Currently trying to delete an object within another object using the delete keyword as I've seen all around the web. The object I'm using is similar to the one below:
object = { NAME: {hello: 3838383, goodbye: 3474737}, NAME2: {hello: 3838383, goodbye: 3474737} }
Trying:
delete object.NAME
But I continually get: Cannot delete property 'NAME' of [object Object]. Any ideas?
It sounds like NAME is a non-configurable property. That means you can't delete it I'm afraid, as deleting (removing) a property counts as "configuring" it (as does changing the configurable flag on the property).
You can see what the configuration of the property is by using Object.getOwnPropertyDescriptor. In your case it probably will either not show a configurable property at all (because false is the default) or more likely it'll show configurable: false.
Here's an example which shows using getOwnPropertyDescriptor and demonstrates the error you're getting:
"use strict";
const object = { };
Object.defineProperty(object, "NAME", {
value: {hello: 3838383, goodbye: 3474737},
configurable: false,
writable: true
});
console.log(Object.getOwnPropertyDescriptor(object, "NAME"));
delete object.NAME;
If the property is writable, you can assign some other value to itm, such as null or undefined:
object.NAME = null;
But if it's also non-writable, you can't do that, either.
As a final resort, you could create a new object and only copy the properties to it that you want, and assign that new object to the variable or property you're using to refer to the object. For instance:
object = Object.fromEntries(
Object.entries(object)
.filter(([key]) => key !== "NAME")
);
Live Example:
"use strict";
let object = {
NAME2: {hello: 3838383, goodbye: 3474737}
};
Object.defineProperty(object, "NAME", {
value: {hello: 3838383, goodbye: 3474737},
configurable: false, // Just here for emphasis, false is the default
writable: false // same
});
console.log(Object.getOwnPropertyDescriptor(object, "NAME"));
// Can't do this: delete object.NAME;
object = Object.fromEntries(
Object.entries(object)
.filter(([key]) => key !== "NAME")
);
console.log(object);
.as-console-wrapper {
max-height: 100% !important;
}

Only custom object properties are shown during for-in loop

Array.prototype.myFeature = function() {};
var arr = ['some', 'items'];
for (var prop in arr) {
console.log(prop);
}
The output for that code will be: 0, 1, myFeature.
The question is: why only custom added function to the Array prototype is outputed, instead of all the function that exists in prototype?
This is because built-in array methods are defined to be non-enumerable, while properties created by ordinary assignment are enumerable. Internally, properties have behavioral features specified by their associated property descriptor which is defined at property-creation time. One feature supplied in this way is the property's enumerability.
Compare
> Object.getOwnPropertyDescriptor(Array.prototype, "join")
{value: ƒ, writable: true, enumerable: false, configurable: true}
and
> Object.getOwnPropertyDescriptor(Array.prototype, "myFeature")
{value: ƒ, writable: true, enumerable: true, configurable: true}
The first property descriptor object has enumerable: false while the second has enumerable: true. Non-enumerable properties are not enumerated in for-in loops.
You can define your own non-enumerable property with Object.defineProperty:
Object.defineProperty(Array.prototype, "myFeature", { value: function() {}, enumerable: false });
Per the docs:
The for...in statement iterates over the enumerable properties of an object. For each distinct property, statements can be executed.
Seems, only these three properties are enumerable. So for...in only iterates over them.

Javascript : How to keep defined object descriptor of original objects after mixing them up?

let say i have thoses two objects for wich i set descriptor on each props :
var readonly = {
libName: _libName,
libVersion: _libVersion,
createStage: _createStage,
renderer: _renderer
};
Object.keys(readonly).forEach(function (prop) {
Object.defineProperty(readonly, prop, {
writable: false
});
});
and
var writable = {
rendererOptions: _rendererOptions
};
Object.keys(writable).forEach(function (prop) {
Object.defineProperty(writable, prop, {
writable: false
});
});
I then want to merge the two object with assign, but the descriptor are not kept. I don't know if its normal, as a third object is created. If so, how could i work that up to keep the descriptor? Here is what i am getting (this is only an example BTW) :
console.log(Object.getOwnPropertyDescriptor(writable, "rendererOptions"));
//gives Object {value: Object, writable: false, enumerable: true, configurable: true}
var o = Object.assign(readonly, writable);
console.log(Object.getOwnPropertyDescriptor(o, "rendererOptions"));
//gives Object {value: Object, writable: true, enumerable: true, configurable: true}
Thanks for any help you can give. And if you have a better solution, 'am all for it.
Here's my comment as an answer:
Seems like you're looking for something like the completeAssign example under MDN's article on Object.assign. The article should also help explain the behavior that you're seeing from the code above

why don't javascript object property descriptors always default to false (as per spec)

According to the spec when adding a javascript object property, the following defaults will be applied to property descriptors:
configurable: false
enumerable: false
writable: false
However when assigning an object property using the following (very popular) dot notation method they all default to true.
myObject = {};
myObject.a = 1;
Why is this?
Apparently - again according to a non-obvious part of the spec - it is due to the way the object property is defined.
See here
If an object property is defined using the dot notation method:
var myObject={};
myObject.a=1;
then all property descriptors default to true
If an object property is defined using the bracket notation method:
var myObject = {};
myObject["a"] = 1;
then all property descriptors default to true
However if an object property is defined using the defineProperty method:
var myObject={};
Object.defineProperty(myObject, 'a', { value: 1 });
any undefined descriptors default to false.
See an example in this jsfiddle
This is an issue that confuse a lot of new developers/programmers/engineers. There are two methods that contribute to this issue in the MDN. If you look at the Object.getOwnPropertyDescriptor() method in the MDN. It says that writable, enumerable, and configurable all default to false, but when you use the method all will return true (Yes, they are false by default).
Example:
let user = {
name: "John"
};
let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
console.log( JSON.stringify(descriptor, null, 2 ) );
/* property descriptor:
{
"value": "John",
"writable": true,
"enumerable": true,
"configurable": true
}
*/
Now, If you use the Object.defineProperty() method then you will see that the special property attributes are set to false by default. In the example below you will notice, because I didn't set an special attributes all of the properties are false by default.
Example:
let user = {};
Object.defineProperty(user, "name", {
value: "John"
});
let descriptor = Object.getOwnPropertyDescriptor(user, 'name');
console.log( JSON.stringify(descriptor, null, 2 ) );
/*
{
"value": "John",
"writable": false,
"enumerable": false,
"configurable": false
}
*/
I know this is confusing for most people that are new to JavaScript, but I wouldn't try to overthink it. Keep it Simple...

Categories