I have a problem in my javascript code, i need to create an object with variables and those variables being objects too. Explanation:
I need this in my javascript code (similar to a Json structure):
var myObj = {
variableOne: {
variableOneA: 'someValue',
variableOneB: 'someValue'
}
variableTwo: {
variableTwoA: 'someValue',
variableTwoB: 'someValue'
}
variableThree: {
variableThreeA: 'someValue',
variableThreeB: 'someValue'
}
}
Now, my problem with this is that in Js i cannot do a 'push' method to an object and i can only add one level of variables to my object doing this:
myObj.variableOne = 'someValue';
Can anyone help me please? i believe the resolution could be easy but i am new to Js.
There are different ways to access your object in Javascript.
var myObj = {
variableOne: {
variableOneA: 'oneA',
variableOneB: 'oneB'
}
variableTwo: {
variableTwoA: 'twoA',
variableTwoB: 'twoB
}
variableThree: {
variableThreeA: 'threeA',
variableThreeB: 'threeB'
}
}
You can use "dot" to access a particular level of your object.
const valueVariableOneA = myObj.variableOne.variableOneA
console.log(valueVariableOneA) // output => "oneA"
You can use the square brackets in replacement of dot. Square brackets are usefull when you want to create an object's key with dash (eg: "cool-key")
const valueVariableThreeB = myObj['variableThree']['variableThreeB']
console.log(valueVariableThreeB) // output => "threeB"
You can also use the destructuration to access particular value
// Get value of variableTwoA key
const { variableTwoA } = myObj.variableTwo // first way
const { variableTwo : { variableTwoA } } = myObj // second way
console.log(variableTwoA) // output => "twoA"
Now to add a key to a nested object you can use either dot or square brackets method. Here's how to add key on the first level.
myObj.variableFour = { variableFourA: 'fourA', variableFourB: 'fourB' }
myObj['variableFour'] = { variableFourA: 'fourA', variableFourB: 'fourB' }
// add key on nested object
myObj.variableOne.variableOneC = 'oneC'
myObj['variableOne']['variableOneC'] = 'oneC'
// you can mix both
myObj['variableOne'].variableOneC = 'oneC'
myObj.variableOne['variableOneC'] = 'oneC'
Use this code:
myObj.variableOne['someValue'] = 'new value';
Related
Let's say I have this:
const something = {
someProp: {
moreProp = 5
}
}
with destructuring we get moreProp:
const { moreProp } = something.someProp
to get moreProp without destructuring:
const morePropAlias = something.someProp.moreProp
In order to access moreProp in the original object we need 2 accesses. My question essentially is that do we also need 2 accesses with the destructuring way or none at all?
Edit: Perhaps I wasn't clear enough, I meant accessing 1) the destructured moreProp and 2) the morePropAlias. In other words, the alias var doesn't do any access (with dots) when we access it, because we access it directly. On the other hand, is destructuring just syntax sugar for us, so behind the scenes it still gets accessed like something.someProp.moreProp?
In either case two accesses happen. The destructuring notation is not skipping steps somehow.
In the following snippet I replaced the properties with getters, so that we can log when an access is performed:
const something = {
get someProp() {
console.log("get someProp");
return {
get moreProp() {
console.log("get moreProp");
return 5;
}
};
}
};
// Using blocks to get local scopes
{
const moreProp = something.someProp.moreProp;
}
console.log("----");
{
const { moreProp } = something.someProp;
}
console.log("----");
{
const { someProp: { moreProp } } = something;
}
In all these different notations, the number of accesses is the same.
when You wrote [some variable = access to data in object] you created variable with variable (created dynamically or not) from object if you want some action everytime you have to use getter or simple function everytime, it's clear and logical... or maybe I don't understand ur question.
I come cross this redux-actions tutorial, and I noticed a unusual syntax to create an object method:
const stringArray = ["STRING_ARRAY"];
const strangeObject = {
[stringArray]() {
console.log(stringArray);
}
};
Can someone name or explain the syntax feature in use?
It's a mix of two features of ES6.
You can have computed property in an object:
const b = "foo";
const a = {
[b]: true
};
// same as
const a = {};
a[b] = true;
There is also a shorthand for functions:
const a = {
b() { console.log("foo");}
};
// same as
const a = {
b: function() { console.log("foo");}
};
If you mix the two, you get what you have: a method whose name is a computed value. Here your object will be the same as
const strangeObject = {
STRING_ARRAY: function() {
console.log("STRING_ARRAY");
}
};
Whenever a computed value for an object is not a string, as in your case, it will be converted to a string.
In your case
["STRING_ARRAY"].toString() === "STRING_ARRAY"
so it does not change much.
I am knew to javascript, please excuse my rather basic question.
How can I use a property from within my class, as in the sample code below?
function MyClass() {
// nothing special
}
MyClass.prototype.myProperty = {
key1: 'some value 1',
key2: 'some value 2',
};
My Class.prototype.myFunction = function myFunction() {
// I need to retrieve the first value of myProperty
const x = myProperty[Object.keys(myProperty)[0]] + 10; // won't work
return x;
};
module.exports = MyClass;
Using this.myProperty throws the error Cannot convert undefined or null to object
Use this.:
MyClass.prototype.myFunction = function myFunction() {
const x = this.myProperty[Object.keys(this.myProperty)[0]] + 10;
// -------^^^^^-----------------------^^^^^
return x;
};
That will get the property from the object. If the object doesn't have its own copy of the property, it will get it from the object's prototype.
Or if you want to get it from the prototype every time, be explicit:
MyClass.prototype.myFunction = function myFunction() {
const p = MyClass.prototype.myProperty;
const x = p[Object.keys(p)[0]] + 10;
return x;
};
Side note: const is a new thing, as of ES2015. If you're using ES2015 (and it looks like you're using NodeJS, which means you can if you're using v6 or later), you can write your class more simply using class notation:
class MyClass {
constructor() {
// nothing special
}
myFunction() {
const x = this.myProperty[Object.keys(this.myProperty)[0]] + 10;
return x;
}
}
MyClass.prototype.myProperty = {
key1: 'some value 1',
key2: 'some value 2',
};
module.exports = MyClass;
Note that if you want myProperty to be on the prototype, you do still need to assign it the "clunky" way. But you may want to create that property in the constructor instead.
Side note 2: Unless you change myProperty later, I strongly recommend using this.myProperty.key1 or this.myProperty.key2 and not using this.myProperty[Object.keys(this.myProperty)[0]], which is hard to read, chaotic (undefined behavior, the order of the keys returned by Object.keys is not specified, not even in ES2015), and extra work.
I'm trying to merge objects together, or add new objects to existing objects.
I've already got it working as for merge using jQuery, but it's the name of the property that wont work dynamically.
The parameter filters is an object, such as {test:123}.
When invoking filter({test:123});, I want the filter function to dynamically add objects to a global object. (and of course can't use push() since its not an array)
this.filter = function(filters) {
for (var key in filters) {
$.extend( settings.filter, {key:filters[key]} );
}
};
The problem is that "key" turns into "key" as the name of the property. When it should be "test" as the property name; I can not get the property name to be created dynamically.
The goal would be to allow the user to fire the function like this:
filter({test:123,test2:1321,test55:4})
and dynamically add objects to the global settings object without the user meddling with the object itself.
Your code does not work because key is not being interpreted as a variable when being directly set in the object.
$.extend( settings.filter, {key:filters[key]} );
Considering:
var keyName = "Test";
var badObj = { keyName: "Hello World" };
You would get undefined when calling newObj.Test because it is actually newObj.keyName.
In order to use a variable to create a property name, you need to use different syntax.
var keyName = "Test";
var newObj = {};
newObj[keyName] = "Hello World";
You could then reference and use newObj.Test to get "Hello World"
To fix the method you provided, you can adjust it to:
this.filter = function(filters) {
for (var key in filters) {
if (filters.hasOwnProperty(key)) {
var newObj = {};
newObj[key] = filters[key];
$.extend(settings.filter, newObj);
}
}
};
Keep in mind you can simplify this and just use the extend method. This would be better, unless you are looking to do your own filtering as the method name suggests.
this.filter = function(filters) {
$.extend(settings.filter, filters);
};
Demos
You should create temp obj before extend :
this.filter = function(filters) {
for (var key in filters) {
var obj = {};
obj[key] = filters[key];
$.extend( settings.filter, obj );
}
};
I have the following code:
Javascript:
slideShow = {
ImgsFolder: "images/",
ImgsSrc: ['img.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg', 'img5.jpg'],
MainElem: document.getElementById('SlideShow'),
ImgElem: (this.MainElem.firstElementChild) ? this.MainElem.firstElementChild : this.MainElem.firstChild
doit: function(){
for (i = 0; i < this.ImgsSrc.length; i++) {
document.writeln(this.ImgsFolder + this.ImgsSrc[i] + "<br/>");
}
}
}
When print the value of ImgElem variable , gives me error message this.MainElem is undefined, and the problem in the last line.
I don' know what's the problem in this part of code
As I mentioned in a comment, it is not possible to refer to the object being created via object literal notation from within the notation itself.
You need to fully create the object before you can reference it.
slideShow = {
ImgsFolder: "images/",
ImgsSrc: ['img.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg', 'img5.jpg'],
MainElem: document.getElementById('SlideShow')
}
slideShow.ImgElem = slideshow.MainElem.firstElementChild ||
slideshow.MainElem.firstChild
To refer to the object during creation, you need a constructor function.
function SlideshowMaker() {
this.ImgsFolder = "images/",
this.ImgsSrc = ['img.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg', 'img5.jpg'],
this.MainElem = document.getElementById('SlideShow')
this.ImgElem = this.MainElem.firstElementChild ||
this.MainElem.firstChild
}
// use "new"----v----to create a new object
var slideshow = new SlideshowMaker()
In order to use the this keyword you have to instantiate object with the new keyword. Otherwise the this keyword will point to the window object in this case.
When you use the object literals such as { key: value, ... }, the object is actually created after the whole block is parsed/executed.
var a = {
// a is not defined here
key: value
};
// it is defined here
Also, you cannot use this as a reference to the object you are about to create. this can only be used in methods of an object (functions bound to the object or executed in their context).
You have two options:
1.) You need to either create a getter function such as
var a = {
b: value,
c: function () { return this.b.c; }
};
and call it in order to access b.c: a.c()
2.) The better way in your case is to define the property ImgElem after the object is actually created:
var slideShow = {
MainElem: document.getElementById('SlideShow')
};
slideShow.ImgElem = slideShow.MainElem.firstElementChild || slideShow.MainElem.firstChild;
Notice the usage of slideShow instead of this.
Maybe you have missplaced some parentheses?
var slideShow = {
ImgsFolder: "images/",
ImgsSrc: ['img.jpg', 'img2.jpg', 'img3.jpg', 'img4.jpg', 'img5.jpg'],
MainElem: document.getElementById('SlideShow'),
ImgElem: (this.MainElem.firstElementChild ? this.MainElem.firstElementChild : this.MainElem.firstChild)
}