I have a Mongoose result object that I'd like to loop through, but it seems to behave differently than a classic object.
Usually, you can't loop through nonenumerable properties with for…in loop, but that seems to work here. Hence, that doesn't work with Object.keys though it's supposed to loop through the same properties as for…in…
Furthermore, Object.getOwnPropertyNames(obj) which is supposed to loop through every properties (enumerable or not) doesn't return any of the fetched values. I don't really get what's happening here.
Here is some sample code and its output to illustrate this:
MediaModel.findById('558d0b3a5fa02e7e218b470c', function (err, media) {
if (err) {
return console.error(err);
}
console.log(media);
console.log("\n --- \n");
console.log(Object.getOwnPropertyNames(media));
console.log("\n---\n");
for (var prop in media) {
console.log(prop + ' -- Enumerable : ' + media.propertyIsEnumerable(prop) + ' -- hasOwnProperty : ' + media.hasOwnProperty(prop) + "\n");
}
});
This it the output in the console:
{ _id: 558d0b3a5fa02e7e218b470c,
name: '54ae5d587860b4.61272171',
cover: true,
size: 144,
audio:
{ es: '54ae5ec1e31c68.83020900',
en: '54ae5ec240dd98.65329366',
fr: '54ae5ec2950737.15028179',
pt: '54ae5ec2e3bcf5.08479198',
ar: '54ae5ec33ab8f5.67860635',
ru: '54ae5ec393d300.66214842' },
comments: [] }
---
[ '$__',
'isNew',
'errors',
'_doc',
'$__original_save',
'save',
'_pres',
'_posts' ]
---
$__ -- Enumerable : true -- hasOwnProperty : true
isNew -- Enumerable : true -- hasOwnProperty : true
errors -- Enumerable : true -- hasOwnProperty : true
_doc -- Enumerable : true -- hasOwnProperty : true
$__original_save -- Enumerable : true -- hasOwnProperty : true
save -- Enumerable : true -- hasOwnProperty : true
_pres -- Enumerable : true -- hasOwnProperty : true
_posts -- Enumerable : true -- hasOwnProperty : true
db -- Enumerable : false -- hasOwnProperty : false
discriminators -- Enumerable : false -- hasOwnProperty : false
__v -- Enumerable : false -- hasOwnProperty : false
id -- Enumerable : false -- hasOwnProperty : false
_id -- Enumerable : false -- hasOwnProperty : false
comments -- Enumerable : false -- hasOwnProperty : false
size -- Enumerable : false -- hasOwnProperty : false
length -- Enumerable : false -- hasOwnProperty : false
cover -- Enumerable : false -- hasOwnProperty : false
imdbId -- Enumerable : false -- hasOwnProperty : false
imdbRating -- Enumerable : false -- hasOwnProperty : false
year -- Enumerable : false -- hasOwnProperty : false
actors -- Enumerable : false -- hasOwnProperty : false
writers -- Enumerable : false -- hasOwnProperty : false
director -- Enumerable : false -- hasOwnProperty : false
genre -- Enumerable : false -- hasOwnProperty : false
name -- Enumerable : false -- hasOwnProperty : false
schema -- Enumerable : false -- hasOwnProperty : false
collection -- Enumerable : false -- hasOwnProperty : false
$__handleSave -- Enumerable : false -- hasOwnProperty : false
$__delta -- Enumerable : false -- hasOwnProperty : false
$__version -- Enumerable : false -- hasOwnProperty : false
increment -- Enumerable : false -- hasOwnProperty : false
$__where -- Enumerable : false -- hasOwnProperty : false
remove -- Enumerable : false -- hasOwnProperty : false
model -- Enumerable : false -- hasOwnProperty : false
on -- Enumerable : false -- hasOwnProperty : false
once -- Enumerable : false -- hasOwnProperty : false
emit -- Enumerable : false -- hasOwnProperty : false
listeners -- Enumerable : false -- hasOwnProperty : false
removeListener -- Enumerable : false -- hasOwnProperty : false
setMaxListeners -- Enumerable : false -- hasOwnProperty : false
removeAllListeners -- Enumerable : false -- hasOwnProperty : false
addListener -- Enumerable : false -- hasOwnProperty : false
$__buildDoc -- Enumerable : false -- hasOwnProperty : false
init -- Enumerable : false -- hasOwnProperty : false
$__storeShard -- Enumerable : false -- hasOwnProperty : false
hook -- Enumerable : false -- hasOwnProperty : false
pre -- Enumerable : false -- hasOwnProperty : false
post -- Enumerable : false -- hasOwnProperty : false
removePre -- Enumerable : false -- hasOwnProperty : false
_lazySetupHooks -- Enumerable : false -- hasOwnProperty : false
update -- Enumerable : false -- hasOwnProperty : false
set -- Enumerable : false -- hasOwnProperty : false
$__shouldModify -- Enumerable : false -- hasOwnProperty : false
$__set -- Enumerable : false -- hasOwnProperty : false
getValue -- Enumerable : false -- hasOwnProperty : false
setValue -- Enumerable : false -- hasOwnProperty : false
get -- Enumerable : false -- hasOwnProperty : false
$__path -- Enumerable : false -- hasOwnProperty : false
markModified -- Enumerable : false -- hasOwnProperty : false
modifiedPaths -- Enumerable : false -- hasOwnProperty : false
isModified -- Enumerable : false -- hasOwnProperty : false
isDirectModified -- Enumerable : false -- hasOwnProperty : false
isInit -- Enumerable : false -- hasOwnProperty : false
isSelected -- Enumerable : false -- hasOwnProperty : false
validate -- Enumerable : false -- hasOwnProperty : false
validateSync -- Enumerable : false -- hasOwnProperty : false
invalidate -- Enumerable : false -- hasOwnProperty : false
$markValid -- Enumerable : false -- hasOwnProperty : false
$isValid -- Enumerable : false -- hasOwnProperty : false
$__reset -- Enumerable : false -- hasOwnProperty : false
$__dirty -- Enumerable : false -- hasOwnProperty : false
$__setSchema -- Enumerable : false -- hasOwnProperty : false
$__getArrayPathsToValidate -- Enumerable : false -- hasOwnProperty : false
$__getAllSubdocs -- Enumerable : false -- hasOwnProperty : false
$__registerHooksFromSchema -- Enumerable : false -- hasOwnProperty : false
$__handleReject -- Enumerable : false -- hasOwnProperty : false
$toObject -- Enumerable : false -- hasOwnProperty : false
toObject -- Enumerable : false -- hasOwnProperty : false
toJSON -- Enumerable : false -- hasOwnProperty : false
inspect -- Enumerable : false -- hasOwnProperty : false
toString -- Enumerable : false -- hasOwnProperty : false
equals -- Enumerable : false -- hasOwnProperty : false
populate -- Enumerable : false -- hasOwnProperty : false
execPopulate -- Enumerable : false -- hasOwnProperty : false
populated -- Enumerable : false -- hasOwnProperty : false
$__fullPath -- Enumerable : false -- hasOwnProperty : false
In the end, I'd like to loop through media.audio but I can't figure out how.
It works by doing var audio = (JSON.parse(JSON.stringify(media.audio))); and then loop through it with a for…in, but I don't find this to be the proper way of doing it!
Well, question is not fresh, but this situation may still become a piece of pain. You may use toJSON or toObject method to get normal, iterable object. Just like this:
media = media.toJSON()
Object.keys(media.audio).forEach(...)
See this post for details about toJSON an toObject
I think you can do it with:
var media = {
_id: '558d0b3a5fa02e7e218b470c',
name: '54ae5d587860b4.61272171',
cover: true,
size: 144,
audio: {
es: '54ae5ec1e31c68.83020900',
en: '54ae5ec240dd98.65329366',
fr: '54ae5ec2950737.15028179',
pt: '54ae5ec2e3bcf5.08479198',
ar: '54ae5ec33ab8f5.67860635',
ru: '54ae5ec393d300.66214842'
},
comments: []
};
for (var property in media.audio) {
if (media.audio.hasOwnProperty(property)) {
console.log(property);
}
}
Related
I have a CustomEvent object that I need to retrieve specific properties for. This object is not a plain object, but rather is the result of new CustomEvent();. When I output this object in the [Chrome] browser console, I see the following:
CustomEvent{
bubbles: false
cancelBubble: false
cancelable: false
composed: false
currentTarget: Window {...}
defaultPrevented: false
detail: {...}
eventPhase: 0
isTrusted: false
path: [Window]
returnValue: true
srcElement: Window {...}
target: Window {...}
timeStamp: 4979.4150000670925
type: "resize_element"
}
When I use Object.keys(custom_event_obj), I get only one key, isTrusted. This would mean that isTrusted is the only enumerable key.
I use the following code to make sure:
for(var key_str in custom_event_obj)
{
console.log(key_str, 'property is enumerable =', custom_event_obj.propertyIsEnumerable(key_str))
}
And I get the following result:
isTrusted is enumerable = true
detail is enumerable = false
initCustomEvent is enumerable = false
NONE is enumerable = false
CAPTURING_PHASE is enumerable = false
AT_TARGET is enumerable = false
BUBBLING_PHASE is enumerable = false
type is enumerable = false
target is enumerable = false
currentTarget is enumerable = false
eventPhase is enumerable = false
bubbles is enumerable = false
cancelable is enumerable = false
defaultPrevented is enumerable = false
composed is enumerable = false
timeStamp is enumerable = false
srcElement is enumerable = false
returnValue is enumerable = false
cancelBubble is enumerable = false
path is enumerable = false
composedPath is enumerable = false
stopPropagation is enumerable = false
stopImmediatePropagation is enumerable = false
preventDefault is enumerable = false
initEvent is enumerable = false
Object.getOwnPropertyNames gives me only one key as well: isTrusted.
This list contains keys that don't appear in the browser console result.
I'd like to get just the keys that appear in the browser console. How do I filter those keys out from the full list above?
Object.getOwnPropertyNames gives me only one key as well: isTrusted.
Not for me:
let CustomEvent = {
bubbles: false,
cancelBubble: false,
cancelable: false,
composed: false,
currentTarget: null,
defaultPrevented: false,
detail: null,
eventPhase: 0,
isTrusted: false,
path: [],
returnValue: true,
srcElement: null,
target: null,
timeStamp: 4979.4150000670925,
type: "resize_element"
}
console.log(Object.getOwnPropertyNames(CustomEvent));
But, while that does get you the property names, you'll still have to loop over the object and get the values for the properties.
You can also use .hasOwnProperty to only enumerate the properties that are not inherited.
let CustomEvent = {
bubbles: false,
cancelBubble: false,
cancelable: false,
composed: false,
currentTarget: null,
defaultPrevented: false,
detail: null,
eventPhase: 0,
isTrusted: false,
path: [],
returnValue: true,
srcElement: null,
target: null,
timeStamp: 4979.4150000670925,
type: "resize_element"
}
for(var prop in CustomEvent){
if(CustomEvent.hasOwnProperty(prop)){
console.log(prop, CustomEvent[prop]);
}
}
I am trying to discover the getters and setters on an object in typescript. I've tried Object.entries() and Object.keys() and neither of these return getters and setters. How can I enumerate these?
Edit: Here is some code that shows the problem:
class ThingWithGetter{
myProperty = 22;
get myGetter() {return 1;}
}
const thing = new ThingWithGetter()
// Does not show getter
console.log(Object.keys(thing));
// Does not show getter
const descriptors = Object.getOwnPropertyDescriptors(thing);
console.log(Object.keys(descriptors));
// Does not show getter
console.log(Object.entries(thing))
The reason this doesn't work is that the getter is on the class's prototype, which is on the instance's prototype chain, rather than on the instance itself.
To illustrate:
class A {
get x() { return 1 }
}
aInstance = new A()
// A {}
Object.getOwnPropertyDescriptors(aInstance)
// {}
Object.getOwnPropertyDescriptors(A.prototype)
// { constructor:
// { value: [Function: A],
// writable: true,
// enumerable: false,
// configurable: true },
// x:
// { get: [Function: get x],
// set: undefined,
// enumerable: false,
// configurable: true } }
Object.getOwnPropertyDescriptors(Object.getPrototypeOf(aInstance))
// { constructor:
// { value: [Function: A],
// writable: true,
// enumerable: false,
// configurable: true },
// x:
// { get: [Function: get x],
// set: undefined,
// enumerable: false,
// configurable: true } }
There a few good blog posts by Axel Rauschmayer on this topic:
https://2ality.com/2011/06/prototypes-as-classes.html
https://2ality.com/2012/11/property-assignment-prototype-chain.html
Note that if you are trying to enumerate all the properties, accessors, and methods on an object you will need to recursively walk the prototype chain until an object has a null prototype.
You can enumerate the getter name with this function:
function listGetters (instance) {
return Object.entries(
Object.getOwnPropertyDescriptors(
Reflect.getPrototypeOf(instance)
)
)
.filter(e => typeof e[1].get === 'function' && e[0] !== '__proto__')
.map(e => e[0]);
}
It will returns an array containing the getters names.
The function Object.getOwnPropertyDescriptors is in the ECMAScript latest draft specification, but is implemented in popular browsers. It returns the property descriptors belonging to an object.
Your use-case is a bit more difficult because the getter is defined on the class, not the object itself. So, you need to walk the prototype chain and build it that way. It's not enough to look at just the object's prototype, because the getter could be inherited from any superclass of the object's class.
Here's a recursive function which does it:
function getAllPropertyDescriptors(obj) {
if (!obj) {
return Object.create(null);
} else {
const proto = Object.getPrototypeOf(obj);
return {
...getAllPropertyDescriptors(proto),
...Object.getOwnPropertyDescriptors(obj)
};
}
}
The output for JSON.stringify(getAllPropertyDescriptors(thing)) is below. myGetter is the third property descriptor; the actual output if you don't JSON.stringify it also includes references to the actual functions, so you can see if they have get/set properties.
{
"myProperty": {"value": 22, "writable": true, "enumerable": true, "configurable": true},
"constructor": {"writable": true, "enumerable": false, "configurable": true},
"myGetter": {"enumerable": false, "configurable": true},
"__defineGetter__": {"writable": true, "enumerable": false, "configurable": true},
"__defineSetter__": {"writable": true, "enumerable": false, "configurable": true},
"hasOwnProperty": {"writable": true, "enumerable": false, "configurable": true},
"__lookupGetter__": {"writable": true, "enumerable": false, "configurable": true},
"__lookupSetter__": {"writable": true, "enumerable": false, "configurable": true},
"isPrototypeOf": {"writable": true, "enumerable": false, "configurable": true},
"propertyIsEnumerable": {"writable": true, "enumerable": false, "configurable": true},
"toString": {"writable": true, "enumerable": false, "configurable": true},
"valueOf": {"writable": true, "enumerable": false, "configurable": true},
"__proto__": {"enumerable": false, "configurable": true},
"toLocaleString": {"writable": true, "enumerable": false, "configurable": true}
}
You could convert this into an iterative version, but that's probably unnecessary since most prototype chains are short, and the iterative version would need some wrangling to get overrides in the right order.
You can try something like:
var obj = {
get foo() {
return Math.random() > 0.5 ? 'foo' : 'bar';
}
};
Object.keys(obj).forEach(key => {
console.log("Getter:", Object.getOwnPropertyDescriptor(obj, key).get);
console.log("Setter: ", Object.getOwnPropertyDescriptor(obj, key).set);
})
Hope this works for you.
Do anybody know how to turn back on console log and alerts in Adminator (webpack based, link below). Have tried to turn off each plugin one by one, both production and development mode, unsuccessfully.
I assume that uglifyJsPlugin is responsible, but even changing compress parameters to false didn't work.
https://github.com/puikinsh/Adminator-admin-dashboard
in webpack.config.js
// ---------------------------
// #Merging Production Plugins
// ---------------------------
if (manifest.IS_PRODUCTION) {
plugins.push(
new webpack.optimize.UglifyJsPlugin({
compress: {
comparisons : true,
conditionals : true,
dead_code : false,
drop_debugger : false,
evaluate : true,
if_return : true,
join_vars : true,
screw_ie8 : true,
sequences : true,
unused : true,
warnings : false,
},
output: {
comments: false,
},
})
);
}
Can you please disable drop_console attribute to false and check with below config.
Reference : compress-options
// ---------------------------
// #Merging Production Plugins
// ---------------------------
if (manifest.IS_PRODUCTION) {
plugins.push(
new webpack.optimize.UglifyJsPlugin({
compress: {
comparisons : true,
conditionals : true,
dead_code : false,
drop_debugger : false,
evaluate : true,
if_return : true,
join_vars : true,
screw_ie8 : true,
sequences : true,
unused : true,
warnings : false,
drop_console : false
},
output: {
comments: false,
},
})
);
}
Can someone explain to me what is going on here? I am playing around with the Firefox WebExtensions API, and I am running into some rather strange behavior. Here is some very simple to code to illustrate the issue.
I am querying for all pinned tabs in all windows and I am expecting that the global array var pinned = []; will be populated with the tab data/objects. However, things are a little screwy to say the least. The array seems to be populated but the individual elements are not accessible using standard array notation pinned[0] returns undefined. I am absolutely perplexed by this.
So what is going on here? Is this an issue about scope or permissions?
Now the code ...
[manifest.json]
{
"manifest_version": 2,
"name": "test",
"version": "1.0",
"description": "test",
"icons": {
"48": "icons/page-48_white.png"
},
"permissions": [
"tabs",
"<all_urls>"
],
"background": {
"scripts": ["background.js"]
},
"devtools_page": "test.html",
"browser_action": {
"default_icon": { "48": "icons/page-48_white.png"},
"default_title": "Test",
"browser_style": true
}
}
[background.js]
function createExtPage(){
browser.tabs.create({ "url": "test.html" });
}
browser.browserAction.onClicked.addListener(createExtPage);
[test.js]
var pinned = [];
browser.tabs.query({pinned: true})
.then(tabs => {
for (let [key, value] of tabs.entries() ) {
console.log("Object " + key, value);
pinned.push(value);
}
});
console.debug("All Pinned Tabs", pinned);
console.debug("First Pinned Tab", pinned[0]);
Now take a look at this output from the Firefox developer tools console.
All Pinned Tabs
[]
0: {…}
active: false
audible: false
discarded: false
favIconUrl: "http://www.crunchyroll.com/favicon.ico?v=1"
height: 800
hidden: false
highlighted: false
id: 149
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522229700160
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Crunchyroll - Watch Naruto Shippuden, Bleach, Anime Videos and Episodes Free Online"
url: "http://www.crunchyroll.com/"
width: 1440
windowId: 3
__proto__: Object { … }
1: {…}
active: false
audible: false
discarded: false
favIconUrl: "https://www.pandora.com/favicon.ico"
height: 800
hidden: false
highlighted: false
id: 145
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522447564848
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "All Along The Watchtower Radio - Now Playing on Pandora"
url: "https://www.pandora.com/station/play/3395036678172411653"
width: 1440
windowId: 67
__proto__: Object { … }
2: {…}
active: false
audible: false
discarded: false
height: 800
hidden: false
highlighted: false
id: 171
incognito: false
index: 1
isArticle: false
isInReaderMode: false
lastAccessed: 1522398347238
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Debugging with Firefox Developer Tools"
url: "about:debugging"
width: 1440
windowId: 67
__proto__: Object { … }
length: 3
__proto__: Array []
First Pinned Tab undefined
Object 0
{…}
active: false
audible: false
discarded: false
favIconUrl: "http://www.crunchyroll.com/favicon.ico?v=1"
height: 800
hidden: false
highlighted: false
id: 149
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522229700160
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Crunchyroll - Watch Naruto Shippuden, Bleach, Anime Videos and Episodes Free Online"
url: "http://www.crunchyroll.com/"
width: 1440
windowId: 3
__proto__: Object { … }
Object 1
{…}
active: false
audible: false
discarded: false
favIconUrl: "https://www.pandora.com/favicon.ico"
height: 800
hidden: false
highlighted: false
id: 145
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522447564848
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "All Along The Watchtower Radio - Now Playing on Pandora"
url: "https://www.pandora.com/station/play/3395036678172411653"
width: 1440
windowId: 67
__proto__: Object { … }
Object 2
{…}
active: false
audible: false
discarded: false
height: 800
hidden: false
highlighted: false
id: 171
incognito: false
index: 1
isArticle: false
isInReaderMode: false
lastAccessed: 1522398347238
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Debugging with Firefox Developer Tools"
url: "about:debugging"
width: 1440
windowId: 67
__proto__: Object { … }
Here is the really screwy thing. If I type pinned[0] in the firefox developer tools console I get this result
pinned[0]
{…}
active: false
audible: false
discarded: false
favIconUrl: "http://www.crunchyroll.com/favicon.ico?v=1"
height: 800
hidden: false
highlighted: false
id: 149
incognito: false
index: 0
isArticle: false
isInReaderMode: false
lastAccessed: 1522229700160
mutedInfo: Object { muted: false }
pinned: true
sharingState: Object { camera: false, microphone: false }
status: "complete"
title: "Crunchyroll - Watch Naruto Shippuden, Bleach, Anime Videos and Episodes Free Online"
url: "http://www.crunchyroll.com/"
width: 1440
windowId: 3
__proto__: Object { … }
What gives? Why can I access the array's elements from the console but not the code?
As you can see the array pinned is populated but I can't access the individual elements inside using the array. Does anyone know why this is happening?
This is actually an issue of asynchronous code and array reference.
Let's try and see how this goes, step by step :
You call browser.tabs.query. It returns a promise, which is not resolved immediately. Therefore you don't go into the then part for the time being, so the code execution goes on to the next part...
Which is console.debug("All Pinned Tabs", pinned);. You're logging an array, so you're giving console.debug a reference to the array, which is really important here. This reference won't change over time : when you declared the pinned array and when the script ends, the array reference will still be the same.
Then you move on to console.debug("First Pinned Tab", pinned[0]);. At this point, the promise handler has not been executed yet, thererefore pinned is still empty and pinned[0] actually is undefined. That's why undefined gets logged.
The promise resolves: you go through the then handler, receive the tabs list as argument and push the tabs to your pinned array.
Remember, your first console.debug logged the array based on the array reference, that didn't change over time. When you're viewing the array in the console afterwards, the array has since been populated and what you access in the console is the array in its final state. That's why the log of the whole array does print the array itself.
Let's make sure of this
...with a little test: at step 2, instead of logging the pinned array itself, let's log the id of all elements currently in pinned.
var pinned = [];
browser.tabs.query({pinned: true})
.then(tabs => {
for (let [key, value] of tabs.entries() ) {
console.log("Object " + key, value);
pinned.push(value);
}
});
// will log an empty array since pinned tab is still empty,
// therefore, mapping tab ids will return an empty array
console.warn("All Pinned Tabs", pinned.map((t) => t.id));
// still undefined, nothing changed here
console.warn("First Pinned Tab", pinned[0]);
Here's what you should get:
All Pinned Tabs : Array []
First Pinned Tab undefined
How to deal with it?
A solution is to chain another promise at the end of the first one (which is made possible because each then handler returns a new promise, so you can chain them), like this :
var pinned = [];
browser.tabs.query({pinned: true})
.then(tabs => {
for (let [key, value] of tabs.entries() ) {
console.log("Object " + key, value);
pinned.push(value);
}
}).then( () => {
// ✓ [1,4,3,2] or anything matching your tabs ids
console.debug("All Pinned Tabs", pinned.map((t) => t.id));
// ✓ First tab object: { ... }
console.debug("First Pinned Tab", pinned[0]);
});
And now you do get the expected result:
All Pinned Tabs Array(4) [ 1, 4, 3, 2 ]
First Pinned Tab Object { id: 1, index: 0, windowId: 3, highlighted: false … }
Note that instead of manipulating a global variable for the array, you could make the first promise return an array that would be the argument for the second promise.
From the node repl:
foo = { bar: 'baz'};
console.log (Object.getOwnPropertyDescriptor(foo, 'bar'))
Returned value:
{ value: 'baz',
writable: true,
enumerable: true,
configurable: true }
How do you change the writable enumerable, and configurable to false? What are these values called? Are they part of ES5.1? Are there more that the repl didn't output?
"How do you change the writable enumerable, and configurable to false?"
Object.defineProperty(foo, 'baz', {
enumerable:false,
writable:false,
configurable:false
});
There's also Object.defineProperties, which is the same, except you can set multiple properties, and Object.create, which let's you create a new object, and set its prototype object, and its descriptors.
"What are these values called?"
They're property descriptors.
"Are they part of ES5.1?"
Yes, ES5.
"Are there more that the repl didn't output?"
More what, property descriptors? No.
squint:I think there is like a little typing error in your answer.
Your code:
Object.defineProperty(foo, 'baz', {
enumerable:false,
writable:false,
configurable:false
});
but the second argument must be the name of the property and not the value, so the correct code is:
Object.defineProperty(foo, 'bar', {
enumerable:false,
writable:false,
configurable:false
});
Just wanted to add this in
You can change the attributes when first creating an object like so:
var newObj = Object.defineProperty({}, 'aPropertyName', {
enumerable:false,
writable:false,
configurable:false
});
You can also, you can alter multiple properties at once:
var newObj = Object.defineProperties({}, {
aPropertyName: {enumerable: false, writable: false, configurable: false},
anotherPropertyName: {enumerable: true, writable: true, configurable: false},
finalPropertyName: {enumerable: true, writable: false, configurable: true},
});
And of course passing in the object name with the previous method:
Object.defineProperties(objectName, {
aPropertyName: {enumerable: false, writable: false, configurable: false},
anotherPropertyName: {enumerable: true, writable: true, configurable: false},
finalPropertyName: {enumerable: true, writable: false, configurable: true},
});