How to implement such an associative array? - javascript

arr[key] = value;
where key is a jQuery object and value is an array.

Associative arrays don't really exist in JavaScript. However, you can achieve similar functionality using JavaScript objects:
// Create object
var myObject = {
key: value,
helloText: "Hello World!"
};
// Access object in some statement via:
myObject.helloText
// ...or:
myObject["helloText"]
To use an object as a key, you would have to do something like:
var a = {
helloText: "Hello World!"
};
var b = {};
b[a] = "Testing";
alert(b[a]); // Returns "Testing" (at least, in Safari 4.0.4)
Using an object as a key sounds a bit weird, though. Are you sure you need to do this?
Update:
You can't actually use an object as a key in JavaScript. The reason the above code appears to work is that, in the statement b[a] = "Testing";, JavaScript converts a to a string via a.toString(), which results in "[object Object]", and uses this string as the key. So our statement is actually b["[object Object]"] = "Testing"; and our alert statement is exactly the same as alert(b["[object Object]"]);.
Thanks to CMS for pointing this out in the comments!
Update 2:
Tim Down points out that his JavaScript library jshashtable allows you use an object as a key.

You can use jshashtable, which allows any JavaScript object as a key.

Just guessing here, but it seems you're trying to associate some (arbitrary) data with a jQuery object (possibly an element). In that case, why not use the data () method?
$('#el').data (value);

You can't use objects as keys, and assocative arrays are not what they seem in Javascript because all you're doing is setting a property on the array object, when you loop through by the .length it natively doesn't account for the manually defined properties you set.
I suggest storing the elements and arrays inside of object literals, all inside of an array. Eg:
var list = [
{
el:document.body,
arr:[1,2]
}
];
for ( var i = 0, l = list.length; i<l; ++i ) {
alert( list[i]['el'] )
alert( list[i]['arr'][0] )
}
// add elements to the array
list.push({
el:document.body.firstChild,
arr:[3,4]
})
As kprime mentioned in his answer though, it might be better to use .data() if you are using Javascript.
if ( !$(el).data('key') ) {
$(el).data('key', [2,3,4] );
}

I would suggest assigning a unique ID to each element you want to put in the associative container (object in JS) and use the ID as key:
var idCounter = 0;
var container = { };
function storeValue(element, value) {
if (!element.getAttribute('id')) {
element.setAttribute('id', makeID());
}
var id = element.getAttribute('id');
container[id] = value;
}
function makeID() {
return 'unique-id-' + idCounter++;
}
EDIT: This solution assumes that jQuery is not available. If it is, use data('key', value).

every javascript object is an associative array, this is a property build in the language, you do not need to anything special, just use it like that

Related

Print JSON path and variable result in one call in JavaScript

Is it possible to console.log something like this:
myParent.myChildData(5)
(variable literal name + value in brackets)
from a JSON object such as this:
{myParent: {myChildData: 5}}
I would like to do it with referencing the object notation ideally only once. Something like:
console.log(printExpression(myParent.myChildData))
Where printExpression I'm certainly happy to be a generic helper function that could return this. I've searched high and low, but obviously printExpression receives the actual evaluated value and this causes a road block.
You can turn JSON into a JavaScript object by using JSON.parse(jsonString).
You can store that as a variable and then console.log it.
Or you can just directly console.log the passed data like this:
console.log(JSON.parse('{"myparent":{"myChildData": 5}}').myParent.myChildData);
Edit
After understanding what exactly the helper function does, I've created a printExpression function that returns string values based on your example.
function printExpression(object, stringBefore) {
//Recursively make objects with keys as methods
let newObject = {};
for (var key in object) {
//Make sure the key exists on the object
if (object.hasOwnProperty(key)) {
let value = object[key];
//If the value is an object, just add a get method that returns the object
if (typeof(value) == "object") {
let childObject = printExpression(value, key + ".");
newObject[key] = childObject;
}
//If not, make a method that returns the wanted syntax
else {
//Form the string based on specific syntax
let str = key + "(" + value + ")";
//Check if we should add stringBefore
if (stringBefore) {
str = stringBefore + str;
}
newObject[key] = str;
}
}
}
//Return the new object
return newObject;
}
var example = printExpression(JSON.parse('{"myParent": {"myChildData": 5}}'));
console.log(example.myParent.myChildData);
How It Works
When creating the helper object, it recursively reads all the keys of the original object and makes a new object that returns the keys in an organized way. For example if the original object was { greeting: "hello" } then newObject.greeting would be "greeting(hello)" (as you said it should be).
Possible Problems
Doesn't get updated when you change the original object. I don't think this will be much of a problem as you seem to be reading static JSON data, but just letting you know.

Accessing plugin prototype function using array square [] brackets

I am very new to JS and I was just going through the syntax of modal.js. Basically I have a small difficulty, a lot of classical JS plugins use the below skeleton code for the plugin:
var Modal = function(element , options){
this.options = options
this.$body = $(document.body)
this.$element = $(element)
this.isShown = null
this.$backdrop =
this.scrollbarWidth = 0
}
Modal.prototype.toggle = function (_relatedTarget) {
// do something
}
Modal.prototype.show = function (_relatedTarget) {
// do something
}
var data = new Modal(somthing , radnom);
// now if we assume that option is "show",
//the show function in Modal will be executed
// but my question is data is not an array, so how can we use
// [] square brackets to access the properties of Modal/data ??
data[option](_relatedtarget);
Now my question is about accessing the properties of a plugin, see how a function is being called using the following syntax:
data[option](_relatedtarget);
See my comment in the code. How can we access the properties of data using []; it's not an array, right?
[] are not just for arrays
You can use [] to access properties on an object too.
You can use
data["show"] to access the show method
OR
data.show which is the same thing
One advantage of the [] is that you can use a variable within the brackets
var option = "show";
data[option](something); // call the `show` method on `data`
If you know the method you want to call, using the . is much nicer looking in the code
data.show(something); // much quicker (to type), and prettier
JavaScript has arrays:
var anArray = [ 1, 2, 3, 4 ];
and associative arrays (also known as maps):
var anAssociativeArray = { first: "No. 1", second: 2, somethingElse: "Other" };
both of these data structures can be accessed via []:
anArray[3] // will get the element of the array in position 3
// (starting counting frrom 0).
anAssociativeArray['first'] // will get the element of the associative array with the
// key 'first'.
Associative arrays can also be accessed via the .key notation:
anAssociativeArray.first // will also get the property with key 'first'.
The . notation can be used if you know the key you want to access but if you want to dynamically select which key then you need to use the [] notation.
var whichOptionToPick = 'somethingElse';
var value = anAssociativeArray[ whichOptionToPick ]; // will get the value "Other".

javascript get json inner value

Let's I have next object
var o = { "foo" : {"bar" : "omg"} };
I can get value of key foo using
o["foo"] // return {"bar" : "omg"}
and I can get value of key bar inside foo using
o["foo"]["bar"] // return "omg"
Can I get value of key bar inside foo using brackets [] single time.
Somethong like
o["foo.bar"] // not working(
or
o["foo/bar"] // not working(
It is fairly common to create a getter function to do something like this. From the comment:
I have object o and string 'foo.bar', and i want get "omg".
var getProp = function (theObject, propString) {
var current = theObject;
var split = propString.split('.');
for (var i = 0; i < split.length; i++) {
if (current.hasOwnProperty(split[i])) {
current = current[split[i]];
}
}
return current;
};
http://jsfiddle.net/MXu2M/
Note: this is a thrown together example, you'd want to bullet proof and buff it up before dropping it on your site.
No, you must use o["foo"]["bar"] because it's an object inside another object. If you want to access it with "foo.bar", it means you must create the first object like this:
var o = {"foo.bar": "omg"}
o["foo.bar"] or o["foo/bar"] are not valid for your example. You could use this notation that is cleaner:
var bar = o.foo.bar // bar will contain 'omg'
there is a way, but I'm not sure this is what you asked for:
eval("o.foo.bar");
it is dangerous though, and doesn't use [] , but if what you want is to use a string for accessing any object it works
Unfortunately, you can only use o["foo"]["bar"] or o.foo.bar

Retrieve by value from an Object?

This must be a duplicate, but I've been Googling "retrieve by value from object javascript" and "javascript lookup object by value" and every variant and got nowhere, so apologies and here goes.
Say I have a JavaScript object like this:
var options = {"ford": "red", "citroen": "blue"};
How do I do look up value blue to get citroen back?
There's always the 'write your own function' route, I guess:
function returnbyValue(options, v):
for (var prop in options) {
if (options.hasOwnProperty(v)) {
if (options[prop] === v) {
return prop;
}
}
}
return null;
but does JavaScript have anything inbuilt, or is there a neater way to do this?
The property of an object can be accessed just like an associative array!
This worked like a charm!
var obj = {
'key': 'val'
};
alert( obj['key'] );
Alternatively, if you wish to use a method you can create a prototype method.
Object.prototype.getPropertyByString = function( str ) {
return this[str];
};
alert( obj.getPropertyByString( 'key' ) );
Edit: Wow I just noticed I failed to answer your question, my apologies! Allow me to get a second chance.
There is no built in function, but my script below works!
var obj = {
'key': 'val'
};
Object.prototype.getKeyByValue = function( object ) {
for(var key in this) {
if(this.key === object) {
return key;
}
}
return null;
};
alert( obj.getKeyByValue( 'val' ) );
It loops through the object and returns the key if it matches a value. This wil work, no matter if the value is an int, string, object, anything. This is because I've used the strict equal comparison ("===") which also checks if the object type is the same.
Also, please note that checking if the property exists is silly if you're looping through all keys of the object anyway. Obviously, when you're looping through all keys, they exist.
There is no such built-in method. And your own function looks good to me. I can't figure out any improvement of it.

JavaScript: Get first and only property name of object

If I want to enumerate the properties of an object and want to ignore prototypes, I would use:
var instance = { ... };
for (var prop in instance) {
if (instance.hasOwnProperty(prop)) {
...
}
}
What if instance only has one property, and I want to get that property name? Is there an easier way than doing this:
var instance = { id: "foobar" };
var singleMember = (function() {
for (var prop in instance) {
if (instance.hasOwnProperty(prop)) {
return prop;
}
}
})();
Maybe Object.keys can work for you. If its length returns 1, you can use yourObject[Object.keys[0]] to get the only property of the object. The MDN-link also shows a custom function for use in environments without the keys method1. Code like this:
var obj = {foo:'bar'},
kyz = Object.keys(obj);
if (kyz.length === 1){
alert(obj[kyz[0]]); //=> 'bar'
} else {
/* loop through obj */
}
1 Some older browsers don't support Object.keys. The MDN link supplies code to to make it work in these browsers too. See header Compatibility in the aforementioned MDN page
Shortest form:
instance[Object.keys(instance)[0]];
ES6+ function:
let first = v => v[Object.keys(v)[0]];
Use the function:
first({a:'first', b:'second'}) // return 'first'
var foo = {bar: 1};
console.log(Object.keys(foo).toString());
which will print the string
"bar"
Though my answer is downvoted, it's still worth to know that there is no such thing as order of keys in javascript object. Therefore, in theory, any code build on iterating values can be inconsistent. One approach could be creating an object and to define setter which actually provides counting, ordering and so on, and provide some methods to access this fields. This could be done in modern browsers.
So, to answer you question, in general you approach is still most closs-browser. You can iterate using lodash or any other modern framework wich will hide "hasOwnProperty" complexity from you. As of August'15 Object.keys can be accepted as cross-browser and universal. After all IE8 happened years ago. Still there are some cases when you just don't wont store all set of keys in array. But I'd go with Object.keys - it's more flexible compared to iteration.
Unfortunately, there is no, "list properties" function built in, and there certainly isn't a "getFirstProperty" (especially since there is no guarantee that any property will consistently be "first").
I think you're better off writing a function like this one:
/**
* A means to get all of the keys of a JSON-style object.
* #param obj The object to iterate
* #param count maximum length of returned list (defaults to Infinity).
*/
function getProperties( obj, count )
{
if( isNaN( count ) ) count = Infinity
var keys = []
for( var it in obj )
{
if( keys.length > count ) break;
keys.push( it );
}
return keys;
}
Then, you could access the name though:
instance = {"foo":"bar"}
// String() on an array of < 2 length returns the first value as a string
// or "" if there are no values.
var prop = String(getProperties(instance, 1));
This is an old post, but I ended up writing the following helper function based on Object.keys().
It returns the key and value of the first property.
getFirstPropertyKeyAndValue(sourceObject) {
var result = null;
var ownProperties = Object.keys(sourceObject);
if (ownProperties.length > 0) {
if (ownProperties.length > 1) {
console.warn('Getting first property of an object containing more than 1 own property may result in unexpected results. Ordering is not ensured.', sourceObject);
}
var firstPropertyName = ownProperties[0];
result = {key: firstPropertyName, value: sourceObject[firstPropertyName]};
}
return result;
}
Answers in here all good, and with the caveat that the order may be unreliable (although in practice it seems the order the properties are set tends to stay that way), this quick and dirty method also works:
var obj = {foo: 1, bar: 2};
for(var key in obj) {
//you could use key here if you like
break;
}
//key now contains your first key
or a shorter version should also do it:
for(var key in obj) break;
//key now contains your first key

Categories

Resources