how do javascript get property value - javascript

Through the following code I can get a plugin object in chrome browser:
nav = window.navigator;
detectPlugin = function(pluginName, mimeType) {
return nav.plugins && nav.plugins[pluginName] && nav.mimeTypes && nav.mimeTypes[mimeType] && nav.mimeTypes[mimeType].enabledPlugin ? nav.plugins[pluginName] : false;
};
obj = detectPlugin('Shockwave Flash', 'application/x-shockwave-flash');
And I can see the obj's properties through
Object.keys(obj)
which is
["0", "1", "length", "description", "filename", "name"]
or I can see these through chrome Console:
Plugin {0: MimeType, 1: MimeType, length: 2, description: "Shockwave Flash 13.0 r0", filename: "libpepflashplayer.so", name: "Shockwave Flash", item: function…}
And here is something that I don't understand, if I input
obj['application/x-shockwave-flash']
I get this
MimeType {enabledPlugin: Plugin, description: "Shockwave Flash", suffixes: "swf", type: "application/x-shockwave-flash"}
I know obj[0] is the property of 'MimeType', but I don't know why "obj['application/x-shockwave-flash']" can get this.
Any help would be great!

Object.keys only returns
a given object's own enumerable properties
i.e. if it's inherited or non-enumberable, you won't see it
What does it mean for a property to be enumerable?
In JavaScript, you can think of it as similar to meaning "the property is visible to loops"
What does it mean for a property to be inherited?
An Object inherits properties and methods from it's prototype, this means you can have very generic Objects, e.g. {} instanceof Object; // true and very complicated ones like d = new Date(), where d instanceof Date; // true but it still has everything the from the more generic Object, i.e. d instanceof Object; // true
Consider this (assuming IE 9+)
var o = {};
Object.defineProperty(o, 'foo', {value:"bar", enumerable:false});
Object.keys(o); // []
o.foo; // "bar"
And
navigator.plugins[0].hasOwnProperty('application/x-shockwave-flash'); // true
Object.getOwnPropertyDescriptor(
navigator.plugins[0],
'application/x-shockwave-flash'
);
//Object {value: MimeType, writable: true, enumerable: false, configurable: true}
The MDN page here may be helpful in understanding enumerability and ownership

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

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.

No functions in Object.keys(document) [duplicate]

What's the difference between Object.getOwnPropertyNames and Object.keys in javascript? Also some examples would be appreciated.
There is a little difference. Object.getOwnPropertyNames(a) returns all own properties of the object a. Object.keys(a) returns all enumerable own properties. It means that if you define your object properties without making some of them enumerable: false these two methods will give you the same result.
It's easy to test:
var a = {};
Object.defineProperties(a, {
one: {enumerable: true, value: 1},
two: {enumerable: false, value: 2},
});
Object.keys(a); // ["one"]
Object.getOwnPropertyNames(a); // ["one", "two"]
If you define a property without providing property attributes descriptor (meaning you don't use Object.defineProperties), for example:
a.test = 21;
then such property becomes an enumerable automatically and both methods produce the same array.
Another difference is in case of array Object.getOwnPropertyNames method will return an extra property that is length.
var x = ["a", "b", "c", "d"];
Object.keys(x); //[ '0', '1', '2', '3' ]
Object.getOwnPropertyNames(x); //[ '0', '1', '2', '3', 'length' ]
Literal notation vs constructor when creating object. Here is something that got me.
const cat1 = {
eat() {},
sleep() {},
talk() {}
};
// here the methods will be part of the Cat Prototype
class Cat {
eat() {}
sleep() {}
talk() {}
}
const cat2 = new Cat()
Object.keys(cat1) // ["eat", "sleep", "talk"]
Object.keys(Object.getPrototypeOf(cat2)) // []
Object.getOwnPropertyNames(cat1) // ["eat", "sleep", "talk"]
Object.getOwnPropertyNames(Object.getPrototypeOf(cat2)) // ["eat", "sleep", "talk"]
cat1 // {eat: function, sleep: function, talk: function}
cat2 // Cat {}
// a partial of a function that is used to do some magic redeclaration of props
function foo(Obj) {
var propNames = Object.keys(Obj);
// I was missing this if
// if (propNames.length === 0) {
// propNames = Object.getOwnPropertyNames(Obj);
// }
for (var prop in propNames) {
var propName = propNames[prop];
APIObject[propName] = "reasign/redefine or sth";
}
}
So in my case the foo function didn't work if I gave it objects of the cat2 type.
There are other ways to create objects so there could be other kinks in there as well.
As was already explained, .keys doesn't return non-enumerable properties.
Regarding to examples, one of pitfall cases is an Error object: some of its properties are non-enumerable.
So while console.log(Object.keys(new Error('some msg'))) yields [],
console.log(Object.getOwnPropertyNames(new Error('some msg'))) yields ["stack", "message"]
console.log(Object.keys(new Error('some msg')));
console.log(Object.getOwnPropertyNames(new Error('some msg')));
Another difference is that (at least with nodejs) "getOwnPropertyNames" function does not guarantee keys order, that's why I usually use "keys" function :
Object.keys(o).forEach(function(k) {
if (!o.propertyIsEnumerable(k)) return;
// do something...
});

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