Please, help to understand why is the line obj['prop'] = 'zzz'; doesn't work and even shows error when "use strict"; is on and works fine when Object.defineProperty(obj, 'prop', {value:'zzz'}); is used? (While delete works absolutely fine)
//"use strict";
var obj = Object.defineProperties({}, {
prop: {
value: 'aaa',
writeable: true,
enumerable: true,
configurable: true
}
});
console.log(obj.prop);
obj['prop'] = 'zzz';
//Object.defineProperty(obj, 'prop', {value:'zzz'});
console.log(obj.prop);
//delete obj.prop;
//console.log(obj.prop);
Its writable, not writeable (notice no e in the middle).
See MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperties#Parameters
Related
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.
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'
});
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;
}
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
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.