This question already has answers here:
Get property of object in JavaScript
(3 answers)
Closed 6 years ago.
I am trying to access a property within an object and return it.
Note the name of the object can change, so accessing it using title_can_change.property will not work.
Take the following object:
{
"title_can_change":{
property: 1
}
}
How do I return the value of 'property'?
MORE INFO:
This object is being returned from a search which contains an array of results from several API's. This object is returned to detail the API the result has come from (the search goes through several API's).
So this would be more like:
apiData:{
"apiName":{
price: 500
}
}
"apiName" is not fixed and changes to say the name of the API. So it cannot be referenced by "apiName' in any of the code.
You could create a function to return the value of the property of whatever object you pass to it:
var getProperty = function(obj) {
return obj.property;
};
If you have an object and you want to access it's first key's value you can go with something like this (dirty example):
var myObj = {
"title_can_change"{
property: 1
}
}
myObj[Object.keys(myObj)[0]];
I home this helps.
So I think I know what you are wanting and here is a low-level solution that may prove valuable and show you some neat things about the language.
https://jsfiddle.net/s10pg3sh/1/
function CLASS(property) {
// Set the property on the class
this.property = property || null;
}
// Add a getter for that property to the prototype
CLASS.prototype.getProperty = function() {
return this['property'];
}
var obj = new CLASS(9);
alert(obj.getProperty());
What you are doing in the above is creating a "class" for your new variable. When you create your object with the new keyword as show you still get your normal JS object (everything is an object anyways), but you get the convenience of the getProperty method. This being on the prototype insures that any new CLASS variables you create will have that method. You can change the variable names and you will always have access to that property by having access to the instance (variable). This is a very common OO paradigm and is the strength of a prototypical language so while it may be over the top for your needs I figured I would add it as an answer here...
If this object is global, then you can use window['title_can_change']['property']. If it's just another property of another object (called another_one) you can access it with another_one['title_can_change']['property'].
Furthermore: You can have a variable (let's call it title_name) to ease the call:
....
var title_name = "title_can_change";
var myObj = window[title_name]['property'];
title_name = "title_has_changed";
var anotherObj = window[title_name]['property'];
.....
OR
....
var title_name = "title_can_change";
var myObj = another_one[title_name]['property'];
title_name = "title_has_changed";
var anotherObj = another_one[title_name]['property'];
.....
Kind of a guess here since the question is still somewhat unclear. I am assuming that you want to iterate over an objects properties whose names are unknown.
This might be a solution.
for (var property in object) {
if (object.hasOwnProperty(property)) {
// check objects properties for existence
// do whatever you want to do
}
}
Use for...in to iterate over the keys of the object and check if your inner object contains your property
var o = {
"title_can_change":{
property: 1
}
};
for (var k in o) {
if (o.hasOwnProperty(k) && o[k].property) {
return o[k].property;
}
}
Related
This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 6 years ago.
I have a namespace and class declared in the client. In fact, I have a whole bunch of classes declared in several namespaces. I just need to get an instance of one of them when I get a string from the server on page load that contains the "dotted" namespace.class names.
Currently I use eval to do that but this causes a memory leak, so I'm trying to find an alternative way of instantiating a declared object by knowing only its name. Things like var obj = "myNamespace.myObjectName"(); won't work, obviously.
If I have an object name as a string variable I can use the eval() function to create an instance of that object:
window["myNamespace"] = {};
myNamespace.myObjectName = function() { /* blah */ };
var name = "myNamespace.myObjectName";
var obj = eval("new " + name + "()");
But for several reasons I don't want/cannot to use the eval. How can I create an object by its name without using the eval?
It sounds like you don't control the content of the name variable, so you're stuck with the . being part of the string.
Therefore, you can .split() the string into its name parts, and use .reduce() to traverse from the base object.
window["myNamespace"] = {};
myNamespace.myObjectName = function() {
this.foo = "bar"
};
var name = "myNamespace.myObjectName";
var obj = newObjectFromStringPath(name);
document.querySelector("pre").textContent = JSON.stringify(obj, null, 4);
function newObjectFromStringPath(path, base) {
return new (name.split(".").reduce(function(obj, name) {
return obj != null ? obj[name] : null
}, base || window))
}
<pre></pre>
The newObjectFromStringPath is coded to specifically target a function and call it as a constructor. You can easily make this work to fetch any value by simply removing the new in that function.
I'm working on an AngularJS SPA and I'm using prototypes in order to add behavior to objects that are incoming through AJAX as JSON. Let's say I just got a timetable x from an AJAX call.
I've defined Timetable.prototype.SomeMethod = function() and I use https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/setPrototypeOf in order to set the prototype of x to TimeTable.prototype. I have the polyfill in place too.
If I call x.SomeMethod() this works in IE > 9, FF, Chrome etc. However, IE 9 gives me a headache and says throws an error stating 'x does not have property or member SomeMethod'.
Debugging in IE shows me that the _proto_ of x has SomeMethod() in the list of functions, however, calling x.SomeMethod() gives the same error as described.
How can I make this work in IE9 ?
More comment than answer
The main problem with "extending" a random object retrieved from some other environment is that javascript doesn't really allow random property names, e.g. the random object may have a property name that shadows an inherited property. You might consider the following.
Use the random object purely as data and pass it to methods that access the data and do what you want, e.g.
function getName(obj) {
return obj.name;
}
So when calling methods you pass the object to a function that acts on the object and you are free to add and modify properties directly on the object.
Another is to create an instance with the methods you want and copy the object's properties to it, but then you still have the issue of not allowing random property names. But that can be mitigated by using names for inherited properties that are unlikely to clash, e.g. prefixed with _ or __ (which is a bit ugly), or use a naming convention like getSomething, setSomething, calcLength and so on.
So if obj represents data for a person, you might do:
// Setup
function Person(obj){
for (var p in obj) {
if (obj.hasOwnProperty(p)) {
this[p] = obj[p];
}
}
}
Person.prototype.getName = function(){
return this.name;
};
// Object generated from JSON
var dataFred = {name:'fred'};
// Create a new Person based on data
var p = new Person(dataFred);
You might even use the data object to create instances from various consructors, e.g. a data object might represent multiple people, or a person and their address, which might create two related objects.
This is how I solved it at the end:
Object.setPrototypeOf = Object.setPrototypeOf || function (obj, proto) {
if (!isIE9()) {
obj.__proto__ = proto;
} else {
/** IE9 fix - copy object methods from the protype to the new object **/
for (var prop in proto) {
obj[prop] = proto[prop];
}
}
return obj;
};
var isIE9 = function() {
return navigator.appVersion.indexOf("MSIE 9") > 0;
};
I am trying to get the first object within an object.
I have something like
var object = {
task:{
config:'auto',
title :'test'
},
prop:'switch',
time:'5min'
}
My problem is task object could be named differently. so it could be
var object = {
task2:{
config:'manual',
title :'test2'
},
prop:'switch',
time:'5min'
}
I can't use object.task1.config because task name could changed. The task object will always be the first object though.
I want to get the task object no matter what name it has. How do I accomplish that? Thanks!
To get the first property value of an object in modern browsers you could use the Object.keys method:
var myObject = {
whoTheHellKnows: 'foo',
notUsed: 'whatever'
};
var firstProperty = myObject[Object.keys(myObject)[0]];
Working example
Edit: if you do not trust the ordering of the properties (which you should not) AND the task object is the only nested object in your objects, you can rely on type interrogation to find it:
var myObject = {
task123215452: { dahKey: 'foo' },
notUsed: 'whatever',
somethingElse: 42
};
var taskObject;
for (var key in myObject) {
if (typeof myObject[key] === 'object' && !(myObject[key] instanceof Array)) {
taskObject = myObject[key];
break;
}
}
Working example
If you need to access the first key and you don't know the key name, you should really be using an array instead of an object. Objects don't have the concept of a "first" key.
If that's not an option, you're left with for..in or Object.keys, which may fail on some JavaScript implementations because the language specification does not enforce the order of object key enumerations. However, in practice, it will work on current browsers, as they all iterate the keys in the order they were declaredcitation needed thanks to jbabey.
I've been using dean edwards base.js (http://dean.edwards.name/weblog/2006/03/base/) to organise my program into objects ( base.js is amazing btw, if you havent used it before !).Anyway, my question is generic and you don't have to know base.js to know my answer.
I have a property in one of my objects called ref which is a reference to a DOM element, and this object is meant to be saved as JSON using JSON.stringify, but as you can imagine since DOM elements are circular structure, I won't be able to convert the object into JSON.
Now to get around this problem I have a method called html() which is meant to return the ref property, but I need to have ref as a private property which is only accessible from within the object, and hence won't be sent to stringify.
What's the best way to do that?
You probably know that you cannot have private properties in JavaScript.
Interestingly, if you pass an object to JSON.stringify which has a method toJSON, JSON.stringify will automatically call that method to get a JSONable representation of that object. So all you have to do is implement this method.
For example you can create a shallow copy of the object which only contains the properties you want to copy:
MyConstructor.prototype.toJSON = function() {
var copy = {},
exclude = {ref: 1};
for (var prop in this) {
if (!exclude[prop]) {
copy[prop] = this[prop];
}
}
return copy;
};
DEMO
Another way would be to use a custom replacer function, but it might be more difficult to control which ref to exclude and which one to keep (if different objects have ref properties):
JSON.stringify(someInstance, function(key, value) {
if(key !== 'ref') {
return value;
}
});
DEMO
here is sample to to set variable visibility
function Obj(){
this.ref = 'public property'; // this property is public from within the object
var ref = 'private proerty'; // this property is private.
var self = this;
this.showRef = function(){
alert(ref);
alert(self.ref);
};
}
var obj = new Obj();
obj.showRef();
What does assigning a variable to {}, mean? Is that initializing it to a function? I have code in a javascript file that says this
GLGE.Wavefront = function(uid) {
GLGE.Assets.registerAsset(this,uid);
this.multimaterials = [];
this.materials = {}; // <---
this.instances = [];
this.renderCaches = [];
this.queue = [];
};
how is that assignment different from an array? Is it a type of array?
What does assigning a variable to {}, mean?
It is an object literal (with no properties of its own).
Is that initializing it to a function?
No, that would be = function () { }.
how is that assignment different from an array?
An array has a bunch of features not found in a basic object, such as .length and a bundle of methods.
Objects are often used to store arbitrary key/value pairs. Arrays are for ordered values.
This is javascript object notation. Particularly {} means empty object, the same as new Object();. See json.org.
That would be an empty JavaScript object.
Using {} creates an object. You can use the object like a hash-map or similar to how you can use arrays in PHP.
var obj = {};
obj['test'] = 'valuehere';
obj.secondWay = 'secondValue';
and you could access them by calling obj.test and obj['secondWay'].
It's an initialized empty object, eg. an object of no particular type. It serves to provide a definition for this.materials so that the code won't have to check it for null or being defined later.
It does create an empty object.
var myObj = {};
Within an object you can define key/value pairs, e.g.:
myObj.color = 'red';
A value can be a function, too:
myObj.getColor = function() { return this.color };
It's JON (Javascript Object Notation) for creating a new empty object. Almost equal in idea to how you'd normally do Object x = new Object() in java, minus the initialization part...