I made an object in my chrome extension and added a constant to it
const myObj = {};
Object.defineProperty(myObj , "DATABASES", { value: {}, writable: true, configurable: true });
Then I tried to add a value to that constant
myObj.DATABASES["key1"] = new Set(
{ a: "aaaa", b: "bbbb" }
);
The last line results in the following error, which doesn't make it clear to me which part of the statement is a problem:
Uncaught TypeError: object is not iterable (cannot read property Symbol(Symbol.iterator))
Can somebody tell me what's wrong with that last part?
Set expects an iterable object, like array, and you're passing it an object: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Syntax
I corrected the syntax with Clarity's link. It should be done as follows:
myObj.DATABASES["key1"] = new Set();
myObj.DATABASES["key1"].add({ a: "aaa", b: "bbbb" });
Related
I was playing with below javascript code. Understanding of Object.defineProperty() and I am facing a strange issue with it. When I try to execute below code in the browser or in the VS code the output is not as expected whereas if I try to debug the code the output is correct
When I debug the code and evaluate the profile I can see the name & age property in the object
But at the time of output, it only shows the name property
//Code Snippet
let profile = {
name: 'Barry Allen',
}
// I added a new property in the profile object.
Object.defineProperty(profile, 'age', {
value: 23,
writable: true
})
console.log(profile)
console.log(profile.age)
Now expected output here should be
{name: "Barry Allen", age: 23}
23
but I get the output as.
Note that I am able to access the age property defined afterwards.
I am not sure why the console.log() is behaving this way.
{name: "Barry Allen"}
23
You should set enumerable to true. In Object.defineProperty its false by default. According to MDN.
enumerable
true if and only if this property shows up during enumeration of the properties on the corresponding object.
Defaults to false.
Non-enumerable means that property will not be shown in Object.keys() or for..in loop neither in console
let profile = {
name: 'Barry Allen',
}
// I added a new property in the profile object.
Object.defineProperty(profile , 'age', {
value: 23,
writable: true,
enumerable: true
})
console.log(profile)
console.log(profile.age)
All the properties and methods on prototype object of built-in classes are non-enumerable. Thats is the reason you can call them from instance but they don't appear while iterating.
To get all properties(including non-enumerable)Object.getOwnPropertyNames()
.
let profile = {
name: 'Barry Allen',
}
// I added a new property in the profile object.
Object.defineProperty(profile , 'age', {
value: 23,
writable: true,
enumerable: false
})
for(let key in profile) console.log(key) //only name will be displayed.
console.log(Object.getOwnPropertyNames(profile)) //You will se age too
By default, properties you define with defineProperty are not enumerable - this means that they will not show up when you iterate over their Object.keys (which is what the snippet console does). (Similarly, the length property of an array does not get displayed, because it's non-enumerable.)
See MDN:
enumerable
true if and only if this property shows up during enumeration of the properties on the corresponding object.
Defaults to false.
Make it enumerable instead:
//Code Snippet
let profile = {
name: 'Barry Allen',
}
// I added a new property in the profile object.
Object.defineProperty(profile, 'age', {
value: 23,
writable: true,
enumerable: true
})
console.log(profile)
console.log(profile.age)
The reason you can see the property in the logged image is that Chrome's console will show you non-enumerable properties as well - but the non-enumerable properties will be slightly greyed-out:
See how age is grey-ish, while name is not - this indicates that name is enumerable, and age is not.
Whenever you use".defineProperty" method of object. You should better define all the properties of the descriptor. Because if you don't define other property descriptor then it assumes default values for all of them which is false. So your console.log checks for all the enumerable : true properties and logs them.
//Code Snippet
let profile = {
name: 'Barry Allen',
}
// I added a new property in the profile object.
Object.defineProperty(profile, 'age', {
value: 23,
writable: true,
enumerable : true,
configurable : true
})
console.log(profile)
console.log(profile.age)
In javascript, is there anyway to set a value equal to a previous key that was declared during initialization?
for example,
const object = {
a: "test",
b: a
}
console.log(object)
or
const object = {
a: "test",
b: object.a
}
console.log(object)
How can I achieve this result in the console?
{ a: 'test', b: 'test' }
I understand that this is redundant, so let me explain what I'm trying to achieve.
I want to be able to set a url in one value, and then add to it using a previous value. The reason for this is to clean up the code and set formulas into one object.
Example
const object = {
base_url: "www.google.com",
images_url: `${base_url}/images`,
maps_url: `${base_url}/maps`
}
console.log(object)
The closest thing I can think of in Javascript is to use a getter.
const object = {
a: "test",
get b(){
return this.a+"something else";
}
}
console.log(object)
Getter/Setters will save your day
const object = {
a: "test",
get b(){return this.a}
}
console.log(object)
I'm fiddling around with a library called bcoin for node. Running the following code:
chain.on('block', function(block) {
console.log('Connected block to blockchain:');
block.txs.forEach(function(t) {
t.inputs.forEach(function(i) {
console.log(typeof i, i);
console.log(JSON.stringify(i));
});
});
});
This is the response I'm getting:
Connected block to blockchain:
object { type: 'coinbase',
subtype: null,
address: null,
script: <Script: 486604799 676>,
witness: <Witness: >,
redeem: null,
sequence: 4294967295,
prevout: <Outpoint: 0000000000000000000000000000000000000000000000000000000000000000/4294967295>,
coin: null }
{"prevout":{"hash":"0000000000000000000000000000000000000000000000000000000000000000","index":4294967295},"script":"04ffff001d02a402","witness":"00","sequence":4294967295,"address":null}
Notice that even though the attribute type for example, is shown when we print i, that attribute does not exist when we JSON.stringify the object. If I tried to console.log(i.type) I'd get undefined.
How is that possible? And what is a good way of debugging what's going on with an object?
JSON.stringify will only includes enumerable properties that are not functions.
So if you define a property and set as non-enumerable, it will not be a part of JSON string.
var obj = {
a: 'test'
};
// Non-enumerable property
Object.defineProperty(obj, 'type', {
enumerable: false,
value: 'Test'
});
// Get property
Object.defineProperty(obj, 'type2', {
get: function(){
return 'Test 2'
}
});
console.log(JSON.stringify(obj), obj);
console.log(obj.type, obj.type2)
Im trying to learn about object.create and prototypal inheritance and have the following:
var Employee = {
'attributes': {},
getAttributes: function() {
return this.attributes;
},
addAttribute: function(attribute) {
if (! this.attributes.hasOwnProperty(attribute)) {
this.attributes.extend(attribute);
}
}
};
var OfficeEmployee = Object.create(Employee);
var OfficeEmployeeInstance = Object.create(OfficeEmployee, {'attributes': {'id': 123, 'name': 'Bob'}});
console.log(OfficeEmployeeInstance.attributes);
OfficeEmployeeInstance.addAttribute({'salary': '100'});
console.log(OfficeEmployeeInstance.getAttributes());
It doesnt work as i expect it should though and throws errors:
console.log(OfficeEmployeeInstance.attributes);
is undefined
and
console.log(OfficeEmployeeInstance.getAttributes());
gives error:
Uncaught TypeError: Cannot call method 'hasOwnProperty' of undefined tester.js:39
Employee.addAttribute tester.js:39
(anonymous function)
What am i doing wrong here?
The second argument of Object.create has to be a properties object. That's an object with a defined structure and specific properties:
var OfficeEmployeeInstance = Object.create(OfficeEmployee, {
'attributes': {
value: {'id': 123, 'name': 'Bob'},
writeable: true,
enumerable: true
}
});
You can find the supported properties here.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
When using .create you should pass it an argument of someObject.prototype, rather than a constructor name. The documentation above should help.
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...
});