Ok, because my initial question sounds unclear, so I decided to edit it. My question is how do you find out who defined a certain property, for example, the parseInt function, how do I know on which object it was definded like if parseInt was definded on the window object or the document object or whatever object it is? Thank you
I know the parseInt was definded the window object, I am just using it as an example in general, I am not specifically asking what object definded the parseInt property.
Also, please don't show me jQuery codes since I don't know jQuery that very good.
There is unfortunately no way to determine using code what the variable environment is of a given variable.
As for object properties, they should be obvious if they are myObj.property. If not obvious, it could be possible to use an exhaustive search to look for their existence in certain places, or certain known recursively.
Overall, it is not possible to know without looking at implementation documentation.
I know that to solve my question, we could use Object.prototype.hasOwnProperty(), but that would be very alot of typing because you have to type it out each time you need to know if a certain property is defined on a object. I have decided to write my own function to make this a little easier even though this is of no good practical use, I just wanted to satisfy my curiosity.
function findOwner(property, ownerObjectArray) {
var result = []; // Array to store the objects that the given property is defined on
for (var i = 1; i < arguments.length; i++)
{
var obj = arguments[i]; // the object currently being inspected
var properyList= Object.getOwnPropertyNames(arguments[i]); // a list of all "Owned" properties by this object
for (var j = 0; j < properyList.length; j++)
{
if (property === properyList[j]) result.push(obj.constructor);
}
}
return result.length > 0 ? result : "undefinded";
}
run this method
window.onload = run;
function run()
{
alert(findOwner("parseInt", Array.prototype, window, document)); // passing 3 objects we want to test against to this method. It printed : [object Window], the given property "parseInt" was found on the "Window" object
}
Related
although it is a very simple code, I would like to get a full understanding of what is happening in my condition:
let getFreqOn = function(string){
//set a variable for object
let object = {}
for (let key = 0; key < string.length; key++){
// if (object.hasOwnProperty(string[key])) {
// if (object[string[key]]) {
// if (object[string[key]] !== undefined) {
if (string[key] in object) {
object[string[key]]++
}
else{
object[string[key]] = 1
}
}
return object
}
My main concern would be the first condition, I understand what it is they do but I cant put in to plain English how it is working. For example if (string[key] in object) is basically telling my that if a specific property is in the empty object I defined, then I will set then it will be set as the property and incremented. But what I'm trying to wrap my head around is that the object is empty, so how can the property be in the object?
Hoping someone can enlighten me on the conditions that I commented out as well. Sorry for the noob question.
First, the in operator returns a boolean result. It checks whether the string on the left is present as a property name in the object on the right.
Thus
if (string[key] in object)
asks whether that single character of the string is in use as a property name in the object. As you observed, the very first time through the loop that cannot possibly be true, because the object starts off empty.
Thus the if test is false, so the else part runs. There, the code still refers to object[string[key]], but it's a simple assignment. An assignment to an object property works whether or not the property name is already there; when it isn't, a new object property is implicitly created.
The key difference is right there in the two different statements from the two parts of the if - else:
object[string[key]]++; // only works when property exists
object[string[key]] = 1; // works always
I have a function that receives a list of JS objects as an argument. I need to store information about those objects in a private variable for future reference. I do not want to stuff a property into the objects themselves, I just want to keep it out of band in a dictionary. I need to be able to lookup metadata for an object in sub-linear time.
For this I need a hash function such that, for any two objects o1 and o2,
hash(o1) !== hash(o2) whenever o1 !== o2.
A perfect example of such a hash function would be the memory address of the object, but I don't think JS exposes that. Is there a way?
Each object reference is different. Why not push the object onto an array? Traversing the array looking for an object reference might still perform better than inspecting each object in a recursive manor to generate a hash key.
function Dictionary() {
var values = [];
function contains(x) {
var i = values.length;
while(i--) {
if (values[i] === x) {
return true;
}
}
return false;
}
function count() {
return values.length;
}
function get(i) {
return (i >= 0 && i < values.length) ? values[i] : null;
}
function set(o) {
if (contains(o)) {
throw new Error("Object already exists in the Dictionary");
}
else {
return values.push(o) - 1;
}
}
function forEach(callback, context) {
for (var i = 0, length = values.length; i < length; i++) {
if (callback.call(context, values[i], i, values) === false) {
break;
}
}
}
return {
get: get,
set: set,
contains: contains,
forEach: forEach,
count: count
};
}
And to use it:
var objects = Dictionary();
var key = objects.set({});
var o = objects.get(key);
objects.contains(key); // returns true
objects.forEach(function(obj, key, values) {
// do stuff
}, this);
objects.count(); // returns 1
objects.set(o); // throws an error
To store metadata about objects, you can use an WeakMap:
WeakMaps are key/value maps in which keys are objects.
Note that this API is still experimental and thus not widely supported yet (see support table). There is a polyfill implementation which makes use of defineProperty to set GUIDs (see details here).
Javascript does not provide direct access to memory (or to the file system for that matter).
You'd probably just want to create your properties/variables within the analysis (hash) function, and then return them to where the function was called from to be stored/persisted for later reference.
Thanks everyone who chipped in to reply. You all have convinced me that what I want to do is currently not possible in JavaScript.
There seem to be two basic compromises that someone with this use case can chose between:
Linear search using ===
=== appears to be the only built-in way to distinguish between two identically-valued objects that have different references. (If you had two objects, o1 and o2, and did a deep comparison and discovered that they were value-identical, you might still want to know if they're reference-identical. Besides === you could do something weird like add a property to o1 and see if showed up in o2).
Add a property to the object.
I didn't like this approach because there's no good reason why I should have to expose this information to the outside world. However, a colleague tipped me off to a feature that I didn't know about: Object.defineProperty. With this, I can alleviate my main concerns: first, that my id would show up, unwanted, during object enumeration, and second, that someone could inadvertently alter my id if there were to be a namespace collision.
So, in case anyone comes here wanting the same thing I wanted, I'm putting it up there for the record that I'm going to add a unique id using Object.defineProperty.
On (document).ready im would like to dynamically generate elements inside a certain parent-element. Lets call them "Candles".
Each "Candle" needs different properties for backgroundImage and color depending on their index().
After creating the page, these attributes need to be changeable via the interface. So its important to save the properties of the "candles" independent from each other.
Thats why I thought it might be useful, to generate for an object for each "Candle" to save their individual properties and to make them editable.
var candleAmount = 3;
for (var i=1; i <= candleAmount; i++) {
$("#container #candles").append("<li><img src=''></img></li>");
var Candle+i = [ "background":"+i+", "color":" - random - (ignore)" ]
};
(please dont mind any failures in the code besides the "Candle+i", I'll figure it out.)
EDIT: Ok, thank you so far. I might not made myself clear enaugh.
Here is an way more reduced example:
$("ul#candles li").each( function(i) {
candle+i = i+" Anything";
});
alert(candle4);
I would love to create an amount of variables depending on the Amount of child-objects.
What would be the correct syntax, or isn't there any?
Thank you
just put them in an array and access them via index. Result is most likely the same for you and is much better than let them floating in your scope
So is there any way, to generate object-names with an index?
Yes, in JavaScript, global variables are defined as properties of the global-object. (Inside a function, variables are defined as properties of the Activation object.) You can reference the global object by window (for browser applications) or just by this.
And because all objects are associative you can give there properties just the name you want. So, setting a global variable is equal to set a property into the global object.
var foo = "bar"; === this["foo"] = "bar";
Now, its just a small step to add a dynamic part to the name:
for(var i=0;i<10;i++) {
this['candle' + i] = i;
}
alert(candle7);
For your specific code:
$("ul#candles li").each( function(i) {
window["candle" + i] = i+" Anything";
});
alert(candle4);
I am completely perplexed. I have an object containing a global "hashed" array of numbers (in objectA) that is referred in a loop that combines the numbers into a new series (in objectB).
var objectB = objectA[arrActive[0]];
for (i=1; i<arrActive.length; i++) {
var _this = arrActive[i];
for (x=0; x<objectB.length; x++) {
objectB[x][1] += objectA[_this][x][1];
}
}
What's weird is that the values in objectA, the source array, are being incremented during the loop - but why? As far as I'm aware, I'm just reading from objectA to write to objectB!
This is frustrating because every time the function is called, the numbers are further inflated!
Working example on JSFiddle is here: http://jsfiddle.net/ZbWGH/ - have I completely misunderstood the += operator? I'm sure this is a simple issue to understand.
Thanks in advance for any help!
You're putting reference to the instance objectA['ONE'] in variable called objectB - any change in that variable will indeed change the actual value.
Instead you might be interested in getting clone or "clean copy" of the array into objectB and this way it won't change the original array.
Simple function that will do this is:
function CopyArray(arr) {
var clone = [];
for (var i = 0; i < arr.length; i++) {
var subArray = [];
for (var j = 0; j < arr[i].length; j++)
subArray.push(arr[i][j]);
clone.push(subArray);
}
return clone;
}
And to use it:
var objectB = CopyArray(objectA[arrActive[0]]);
Updated jsFiddle: http://jsfiddle.net/yahavbr/ZbWGH/1/
Further more A += B is like A = A + B, so you modify objectA.
Do you know C? References/pointers in C are a good way to understand komplex variables in Javascript. "Komplex" meaning everything that is not Number, String, Boolean - everything else is "Object". Variables for the komplex types (Objects) are indeed like pointers. If you know the concepts of "call by reference" and "call by value", in Javascript it's neither, sort of: If you give objects to functions the "pointer" itself is call by value, but the value is a reference to the object (really to the area on the heap where the object is stored, even though JS programmers don't handle heap like in C/C++ it still is where stuff is stored). Example:
function fn (a) {
//changing the argument itself does NOT change the original object
a = null;
//but changing its properties does:
a.foo = 42;
}
var o = { foo:1, bar:2 };
fn(o);
So now it should become clear why you have to clone an object if you want real "call by value". This implementation was chosen for JS because otherwise every single time a function is called with a non-primitive type the heap would have to be copied over, and 99% of the time that just is not necessary. The "true" spirit of functional programming would of course be pure call by value, here we see practical life (performance and memory usage) considerations intruding upon theory :)
Is there a way to get (from somewhere) the number of elements in a Javascript object?? (i.e. constant-time complexity).
I can't find a property or method that retrieves that information. So far I can only think of doing an iteration through the whole collection, but that's linear time.
It's strange there is no direct access to the size of the object, don't you think.
EDIT:
I'm talking about the Object object (not objects in general):
var obj = new Object ;
Although JS implementations might keep track of such a value internally, there's no standard way to get it.
In the past, Mozilla's Javascript variant exposed the non-standard __count__, but it has been removed with version 1.8.5.
For cross-browser scripting you're stuck with explicitly iterating over the properties and checking hasOwnProperty():
function countProperties(obj) {
var count = 0;
for(var prop in obj) {
if(obj.hasOwnProperty(prop))
++count;
}
return count;
}
In case of ECMAScript 5 capable implementations, this can also be written as (Kudos to Avi Flax)
function countProperties(obj) {
return Object.keys(obj).length;
}
Keep in mind that you'll also miss properties which aren't enumerable (eg an array's length).
If you're using a framework like jQuery, Prototype, Mootools, $whatever-the-newest-hype, check if they come with their own collections API, which might be a better solution to your problem than using native JS objects.
To do this in any ES5-compatible environment
Object.keys(obj).length
(Browser support from here)
(Doc on Object.keys here, includes method you can add to non-ECMA5 browsers)
if you are already using jQuery in your build just do this:
$(yourObject).length
It works nicely for me on objects, and I already had jQuery as a dependancy.
function count(){
var c= 0;
for(var p in this) if(this.hasOwnProperty(p))++c;
return c;
}
var O={a: 1, b: 2, c: 3};
count.call(O);
AFAIK, there is no way to do this reliably, unless you switch to an array. Which honestly, doesn't seem strange - it's seems pretty straight forward to me that arrays are countable, and objects aren't.
Probably the closest you'll get is something like this
// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
var i = 0;
for ( var p in this ) i++;
return i;
}
alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3
But this creates problems, or at least questions. All user-created properties are counted, including the _length function itself! And while in this simple example you could avoid it by just using a normal function, that doesn't mean you can stop other scripts from doing this. so what do you do? Ignore function properties?
Object.prototype.length = function()
{
var i = 0;
for ( var p in this )
{
if ( 'function' == typeof this[p] ) continue;
i++;
}
return i;
}
alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2
In the end, I think you should probably ditch the idea of making your objects countable and figure out another way to do whatever it is you're doing.
The concept of number/length/dimensionality doesn't really make sense for an Object, and needing it suggests you really want an Array to me.
Edit: Pointed out to me that you want an O(1) for this. To the best of my knowledge no such way exists I'm afraid.
With jquery :
$(parent)[0].childElementCount