See if variables refer to the same object in chrome devtool - javascript

Assume I have code :
var a = {};
var b = {};
var c = a;
Obviously a !== b and a === c however it is very hard to see at a glance which variables refer to the same object. Is there a way to get the Chrome devtool to show something akin to a reference hash or similar so we can, at a glance, determine which variables refer to the same object?
I am aware of the rules regarding equality of JavaScript objects, my question is whether Chrome devtools offers any help in debugging so we don't have to do things like write manual a === b in the console to determine what equals what but rather see equal variables through visual inspection of watches or when hovering over variables.

I've not seen anything in Chrome that does something like that,.
But if you don't mind installing a simple utility method, you could implement your own referencing system.
You could also easily extend this to show referencing on Objects using Object.entries etc.
const refs = new WeakMap();
let count = 0;
function showRef(obj) {
const g = refs.get(obj);
if (!g) {
count++;
refs.set(obj, count);
return count;
};
return g;
}
const a = {};
const b = {};
const c = a;
const z = {a,b,c: {}};
console.log(`a = ${showRef(a)}`);
console.log(`b = ${showRef(b)}`);
console.log(`c = ${showRef(c)}`);
console.log(`z.a = ${showRef(z.a)}`);
console.log(`z.b = ${showRef(z.b)}`);
console.log(`z.c = ${showRef(z.c)}`);

Related

Is there any way to init BOTH key and value at the same time in javascript objects with ternary operator?

for example, I want a javascript object having different key-value according to a==0:
var v=a==1?{
"a":"1",
}:{
"b":"2",
};
I want to simplify to something like:
var v={
a==1?("a":"1"):("b":"2"),
};
and hence for more conditions:
var v={
a==1?("a":"1"):("b":"2"),
c==1?("c":"3"):("d":"4"),
.
.
.
"commonKey1":"commonValue1",
"commonKey2":"commonValue2"
};
Which init both key and value using ternary operator, but I tried the syntax above and it is not working, is there any correct syntax to do this?
When there are multiple conditions and common values, Object.assign is probably the clearest way to do it:
const a = 2;
const c = 1;
const v = Object.assign({ commonKey1: 'commonValue1', commonKey2: 'commonValue2' },
a==1?{"a":"1"}:{"b":"2"},
c==1?{"c":"3"}:{"d":"4"}
);
console.log(v);
Another possibility (that looks uglier IMO) is to spread the object returned by the conditional operator into the parent object:
const a = 1;
const v = {
foo: 'bar',
...(a==1? {"a":"1"}:{"b":"2"})
};
console.log(v);
I'm afraid there is not. Because an object can be used as a key, if you write it like this, the computer cannot recognize what you really want. For example:
var t = {name:'y'};
var m = {t};
Have you missed the value?
var m = {t:'expert'}
Or you just want m = t
var m = {name:'y'}
It may be confused.

Why is there an extra variable in this javascript function?

I'm a javascript newbie, and I can't figure out why the variable o exists in the following code:
var data = [ {"name":"alice", "group":1}, {"name":"bob", "group":2} ];
function getGroup(n) { return n.group; }
function network(nodes, index) {
var gc = {};
nodes.forEach(function(n) {
var i = index(n), o;
if (condition) {
o = gc[i] || (gc[i] = {x:0,y:0,count:0});
o.x += n.x;
o.y += n.y;
o.count += 1;
}
});
}
var net = network(nodes, getGroup)
It seems to me that the iterator in the network function would be better written this way:
function network(data, index) {
var gc = {};
nodes.forEach(function(n) {
var i = index(n);
if (condition) {
gc[i] = gc[i] || (gc[i] = {x:0,y:0,count:0});
gc[i].x += n.x;
gc[i].y += n.y;
gc[i].count += 1;
}
});
}
I think the second loop is equivalent and it eliminates a variable (and it's easier for me to read). Is the first version following some recommended practice in javascript? I can imagine that it would be good practice to have var o; inside the iterator to reduce its scope, but in this case o only refers to an object that's already referenced by gc[i]. Why not just eliminate it?
Likely because g[i] requires indexing into an array repeatedly looking up a property of an object, whereas storing the value in o caches the value once and provides for faster access subsequently.
This is a (minor) performance enhancement. It replaces three subscripting operations with a local variable assignment and three local variable accesses. I have my doubts whether the performance improvement would be noticeable. See this thread for more info on the performance of various array operations. (Actually, that info is somewhat irrelevant because gc is an object, not an array. These are plain old property look-ups being saved, not array indexing, so the performance increase might be a little more significant.)
Even simpler
change
gc[i] = gc[i] || (gc[i] = {x:0,y:0,count:0});
to
gc[i] = gc[i] || {x:0,y:0,count:0};
Because it has to keep re-seeking the item in the array via the index. o is storing the reference to the location in memory so it's quicker to access later.

is there a way to automatically create a javascript object by just assigning a property?

I am doing a project which requires to pass Perl objects to javascript via JSON. I am facing a problem in terms of "intermediate" object definition.
In Perl, object is represented by hash, and programmers don't have to define anything "in the middle". Once a property is created, all intermediate objects are automatically created as hash references. e.g.
$graph{chart}{yAxis}{title} = "Temperature Tracking";
However, once this object is passed to Javascript, if I want to add any new properties in the "intermediate" object, like:
graph.chart.xAxis.title = "Time Sequence";
I'll have an "undefined graph.chart.xAxis" error. Unlike Perl, Javascript doesn't automatically create objects if we simply assign a property for it.
At the moment I have to use below solution:
if (!graph.chart.xAxis) {
graph.chart.xAxis = {};
graph.chart.xAxis.title = "Time Sequence";
}
Unfortunately, in our project the objects passed from Perl are pretty dynamic and there are plenty of other objects that Javascript may not know. Above way makes JS code pretty lengthy and "ugly looking". Are there any better solutions to make Javascript behave like Perl, which means I don't have to create intermediate objects manually?
I'm not sure whether this meets your requirements but a simple function to create the missing objects could look like this:
function insertNode(obj, node, value) {
var segments = node.split('.');
var key = segments.pop();
var ref = obj;
while (segments.length > 0) {
var segment = segments.shift();
if (typeof ref[segment] != 'object') {
ref[segment] = {};
}
ref = ref[segment];
}
ref[key] = value;
};
var x = {};
insertNode(x, 'foo.bar.baz', 'hello world');
alert(x.foo.bar.baz); // "hello world"
Demo: http://jsfiddle.net/sNywt/1/
You may be interested in a library called steeltoe
steelToe(graph).set('chart.xAxis.title', 'Time Sequence');
not sure, if its suitable in your case, but you could check for property existence and create it if does not exist, like:
function use_or_create(obj, prop) {
return (obj.hasOwnProperty(prop)) ? true : (obj[prop] = {});
}
var graph.chart = {}; //your object
//function call to check if property exist before trying to use it
use_or_create(graph.chart, 'xAxis'); //check if xAxis exists and creates one if doesnot
graph.char.xAxis.title = "tested";
Maybe this Object extension will do:
Object.prototype.val = function(prop,val){
prop = /\./i.test(prop) ? prop.split('.') : prop;
if (prop.constructor === Array){
var objnow = this, pr;
while (pr = prop.shift()){
if (!objnow[pr]){
objnow[pr] = {};
}
if (!prop.length) {
objnow[pr] = val;
}
objnow = objnow[pr];
}
for (var l in objnow){
this[l] = objnow[l];
}
} else {
this[prop] = val;
}
}
// usage
var myO = {};
myO.val('a.b.c',3); //=> myO.a.b.c = 3
myO.val('someprop',3); //=> myO.someprop = 3
myO.val('a.b.someprop',5); //=> myO.a.b.someprop = 3

Get anonymous function name

How to get the the variable name from within a function in this example:
// it should return A
var A = function(){ console.log(this.name); }
Is there something like this?
That function is anonymous; it has no name. You could, however, give it a name:
var A = function a() {};
Then its name is accessible via Function.name:
var A = function a() {};
A.name
> 'a'
I know this is an old thread, but still in search results. so just for reference:
a solution could simply be using the stacktrace.
var stack = new Error().stack;
use trim and split to get to the desired values.
No, there is nothing like that in Javascript. That function is anonymous, so it has no name, and what you want is ambiguous because the function could just as easily have any number of variables referencing it like:
var a, b, c, d;
a = b = function(){ console.log(this.name); };
c = b;
d = c;
a = b = 5;
// a and b no longer refer to the function, but c and d both do
What is it you are actually trying to accomplish? I'm sure there is another way to achieve it.
It is possible in recent versions of Chrome and Firefox as follows. I only recommend this for debugging purposes (e.g. javascript tracing in non-production)
var myNameInChrome = /.*Object\.(.*)\s\(/.exec(new Error().stack)[0];
var myNameInFF = new Error().stack.split("#")[0];

Duplicate object in javascript

I see two ways to duplicate objects
1.
var a={c:1}
var b=a;
alert(b.c);//alert 1
2.
var a={c:2};
var b={};
for (i in a)
{b[i]=a[i];}
alert(b.c);//alert 1
The first are shorter than the second so what is the efficiency in the second example?
In the first version you don't duplicate/clone the object you simply make a extra reference to it:
var a = { a: 1 };
var b = a;
b.a = 2;
console.log(a.a); // 2;
To clone an object there is numbers of libraries that can do that for you:
var b = $.extend({}, a); // Make a shallow clone (jQuery)
var b _.extend({}, a); // Make a shallow clone (underscore.js)
var b = $.extend(true, {}, a); // Make a deep clone (jQuery);
Or you can do it natively:
Simple clone:
var b = {};
var prop;
for (prop in a) {
b[prop] = a[prop];
}
Scratch of a deep clone function:
function deepClone(obj) {
var r;
var i = 0,
var len = obj.length;
// string, number, boolean
if (typeof obj !== "object") {
r = obj;
}
// Simple check for array
else if ( len ) {
r = [];
for ( ; i < len; i++ ) {
r.push( deepClone(obj[i]) );
}
}
// Simple check for date
else if ( obj.getTime ) {
r = new Date( +obj );
}
// Simple check for DOM node
else if ( obj.nodeName ) {
r = obj;
}
// Object
else {
r = {};
for (i in obj) {
r[i] = deepClone(obj[i]);
}
}
return r;
}
The first does not create a copy, but just copies the reference, so a and b point towards the same object after the operation.
In the second case, however, each attribute is copied separately, thus creating a "real" copy of the object in a (as long as there are just primitive types in the properties, else you got the same problem at a deeper level).
So in the first case if you change b.c then a.c will also change, while in the second case it wont.
As others have stated here: the first assignment, assigns a new reference to an existing object, the second performs a shallow copy.By shallow I mean: only the base object will be copied, there is no recursion:
var a = {some:'propery',
another:{might:'be',
an: 'object, too'}
};
var b = {};
for(var p in a)
{
b[p] = a[p];
}
b.some = 'b\'s own property';
console.log(a.some);//property -> unaltered
console.log(b.some);//b's own property --> separate entities
b.another.might = 'foo';
console.log(a.another.might);//foo ==> b.another references a.another
To solve this issue, you would be forgiven to think that a simple recursive function would suffice:
var cloneObj = function(o)
{
var p,r = {};
for (p in o)
{//omitting checks for functions, date objects and the like
r[p] = (o[p] instanceof Object ? cloneObj(o[p]) : o[p]);
}
};
But be weary of circular references!
//assume a is the same object as above
a._myself = a;//<- a references itself
This will produce endless recursion, aka a deadlock scenario, unless you add a check for just such cases:
var cloneObj = function(o)
{
var p,r = {};
for (p in o)
{//Needs a lot more work, just a basic example of a recursive copy function
switch(true)
{
case o[p] instanceof Function:
r[p] = o[p];
break;
case o[p] instanceof Date:
r[p] = new Date(o[p]);
break;
case o === o[p]:
//simple circular references only
//a.some.child.object.references = a; will still cause trouble
r[p] = r;
break;
case o[p] instanceof Array:
r[p] = o[p].slice(0);//copy arrays
break;
default:
r[p] = o[p] instanceof Object ? cloneObj(o[p]) : o[p];
}
}
return r;
};
Now, this is quite verbose, and in most cases utter overkill, if all you want are two objects with the same data, but can be altered independently (ie don't reference the same object in memory), all you need is 1 line of code:
var a = {some:'propery',
another:{might:'be',
an: 'object, too'}
};
var b = JSON.parse(JSON.stringify(a));
Bottom line: assigning a reference is certainly more efficient: it doesn't require the object constructor to be called a second time, nor does it require an additional copy of any of the constants. The downside is: you end up with a single object and might inadvertently change/delete something that you assume is still there when you're using the other reference (delete b.some;/*some time later*/a.some.replace(/p/g,'q');//<--error)
The first copies the reference and does not duplicate the object, the second creates a new reference and then copies the members (which, in turn, if they are references will just copy the references only).
You might want to look at this other SO - Does Javascript equal sign reference objects or clones them?
It's not a question of efficiency it's ultimately about correctness. If you need to share a reference to an object between different code blocks (e.g. so that multiple pieces of code can share the same object) - then you simply rely on the fact that javascript passes by reference.
If, however, you need to copy an object between methods - then you might be able to use your simple example in your second code block (if your objects don't have other 'objects' in them), otherwise you might have to implement a deep-clone (see How to Deep clone in javascript, and pay attention to the answer(s) there - it's not a trivial business).

Categories