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

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'
});

Related

Desciptor values are true

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.

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;
}

Is it possible to declare non enumerable property on javascript constructor?

I need to know if is possible to make instances of a javascript class that has non-enumerable attributes, for example
// Constructor
function MyClass(a) {
Object.defineProperty(this, '_number', {
enumerable: false
});
this.number = a; // Call setter for '_number'
}
// Getters and setters for '_number'
Object.defineProperty(MyClass.prototype, 'number', {
get: function() {
return this._number;
},
set: function(n) {
// Validate 'n' here
this._number = n;
}
});
What I wanted this code to do is to define the property _number on any instance of MyClass, making it not enumerable so that instance private variables such as _number wouldn't be listed in, suppose, a for in structure. You would use the number getter/setter to alter the private variable _number.
I have tried declaring the _number and number properties both inside the constructor and on MyClass.prototype with no success...
Any help would be appreciated!
Your approach is fine, you just need to watch out for the other attribute values which default to false:
function MyClass(a) {
Object.defineProperty(this, '_number', {
value: 0, // better than `undefined`
writable: true, // important!
enumerable: false, // could be omitted
configurable: true // nice to have
});
this.number = a; // Call setter for '_number'
}
// Getters and setters for '_number'
Object.defineProperty(MyClass.prototype, 'number', {
get: function() {
return this._number;
},
set: function(n) {
// Validate 'n' here
this._number = n;
},
enumerable: true, // to get `.number` enumerated in the loop
configurable: true // nice to have
});

TypeError: this.list.push is not a function in ecmascript 6

When calling the add function of my GroceryList class, I get an error:
TypeError: this.list.push is not a function
Why is this?
class GroceryList {
constructor() {
this.list = {
value: [],
writable: false,
enumerable: true
};
}
add(item) {
this.list.push(item);
}
getAll() {
return this.list;
}
getItemIndex(value) {
var index = this.list.length;
while(--index > -1) {
if(this.list[index] === value) {
return index;
}
}
return -1;
}
}
You are confusing
A whole object
vs
A list as an attribute of that object
The list object contains a list, but that does not mean it is a list. You should write list.value.push(x)
It seems you are trying to use a property descriptor. However, those descriptors only work with Object.defineProperty.
this.list = {
value: [],
writable: false,
enumerable: true
};
literally assigns an object with the properties value, writable and enumerable to this.list.
What you seem to want is:
Object.definProperty(this, 'list', {
value: [],
writable: false,
enumerable: true
});
Now this.list returns an array, but it's not possible to assign a new value to the property.

MDN JavaScript Inheritance Revisited - understanding the example

I was looking at the example on the MDN pages about Inheritance Revisited and thought it would be nice to have the doSomething methods actually do something. So I started out with the following code, based on the example:
function A(a) { this.varA = a };
A.prototype = { varA: null, doSomething: function() { console.log('do something with ' + this.varA) } };
function B(a, b) {
A.call(this, a);
this.varB = b;
};
B.prototype = Object.create(new A(), {
varB: { value: null, enumerable: true, configurable: true, writeable: true },
doSomething: { value: function() {
A.prototype.doSomething.apply(this, arguments);
console.log("do something with " + this.varB);
}, enumerable: true, configurable: true, writeable: true}
});
var b = new B('a', 'b');
b.doSomething();
I copy and pasted the code into the Chrome console and expected to be seeing
do something with a
do something with b
but instead I got
do something with a
do something with null
What am I overlooking here? Shouldn't the call to "new B" result in the constructor which was defined above (function B(...)) being called? And if the constructor is called, shouldn't b.varB have a value? How do I need to change the example so the output is as expected?
Accidentally you specified varB as being non-writable and hence the assignment this.varB = b failed (or was ignored).
writeable: true should be spelled writable: true (without e). By default, properties defined using the a property descriptor are non-writable.
So the whole descriptor becomes:
varB: { value: null, enumerable: true, configurable: true, writable: true }
Since you are assigning a value inside the constructor function anyway, you don't really have to use the descriptor though.
More information: MDN - Object.defineProperty.

Categories