detecting object-reference duplication across JavaScript files - javascript

I have a number of files with contents like this:
function hello() {
...
element1.text = foo.locale.lorem;
element2.text = foo.locale.ipsum;
...
elementn.text = foo.locale.whatever;
...
}
function world() {
...
var label = bar.options.baz.blah;
var toggle = bar.options.baz.use_toggle;
...
}
This could be written more efficiently, and also be more readable, by creating a shortcut to the locale object:
function hello() {
var loc = foo.locale;
...
element1.text = loc.lorem;
element2.text = loc.ipsum;
...
elementn.text = loc.whatever;
...
}
function world() {
var options = bar.options.baz;
...
var label = options.blah;
var toggle = options.use_toggle;
...
}
Is there a simple way to detect occurrences of such duplication for any arbitrary object (it's not always as simple as "locale", or foo.something)?
Basically, I wanna know where lengthy object references appear two or more times within a function.
Thanks!

Are you talking about something like LINT? e.g. something externally that can report such object references or internally like looping over the window object

Javascript minifiers will do this for you. Not sure if thats what you're looking for. Heres a good js minifier http://jscompress.com/

Related

Why such way of object creation has been used in Java Script?

Could some one please explain to me, why in d3-tip library (https://github.com/Caged/d3-tip), the object constructor looks like this:
d3.tip = function() {
var direction = d3_tip_direction,
offset = d3_tip_offset,
html = d3_tip_html,
node = initNode(),
svg = null,
point = null,
target = null
function tip(vis) {
svg = getSVGNode(vis)
point = svg.createSVGPoint()
document.body.appendChild(node)
}
tip.show = function() {
// some function
}
//...
return tip
}
To explain my confusion, I'm trying to replicate this library with different behaviour and can't make a decision, should I left this pattern as it is or change it into more standard creation function.
The function returns the tip function/object. at the bottom of the function it return tip; which is the new tip function.
by doing this the variables var direction = d3_tip_direction // etc are protected and are not accessible outside of the functions scope.
To understand further, you should look into design patterns, there is an excellent resource here

Separate a Javascript function to reuse it, how?

I see some javascript and try to implement the function seperated to reuse it.
This is the old code:
var ListRenderRenderWrapper = function(itemRenderResult, inCtx, tpl)
{
var iStr = [];
iStr.push('<li>');
iStr.push(itemRenderResult);
iStr.push('</li>');
return iStr.join('');
}
And I would like to make something like this:
function wrapItems(itemRenderResult, inCtx, tpl)
{
var iStr = [];
iStr.push('<li>');
iStr.push(itemRenderResult);
iStr.push('</li>');
return iStr.join('');
}
var ListRenderRenderWrapper = wrapItems(itemRenderResult, inCtx, tpl);
is this ok or do I need to do it in another way?
If you just want to assign that function to a new variable so you can call it with a different name, simply do:
var ListRenderRenderWrapper = wrapItems;
The confusion may be coming from the fact that in JavaScript a function can be stored inside a variable and called as a function later.
This means that:
function thing() { /* code */ }
is the same as:
var thing = function() { /* code */ }
(Aside: I know there are subtle differences with hoisting etc, but for the purposes of this example they are the same).

Create a string (text) that declares variable and its value, for use in Javascript

I am messing with Javascript code that needs to have variable dynamic part.
I am trying to substitute this piece of Javascript code:
var data = document.getElementById('IDofSomeHiddenField').value;
var print = document.getElementById('IDofOutputField');
print.value = data;
with something like:
var encapsulatedData = "var data = document.getElementById('IDofSomeHiddenField').value;";
var encapsulatedPrint = "var print = document.getElementById('IDofOutputField');";
so that when I use somewhere in Javascript code:
encapsulatedData;
encapsulatedPrint;
this will work:
print.value = data;
But it does not work.
Is there a way how to declare:
var encapsulatedData
var encapsulatedPrint
in similar manner like I wrote above, so that:
print.value = data;
works?
Do you mean magically create global variables?
function encapsulatedData() {
window.data = document.getElementById('IDofSomeHiddenField').value;
}
function encapsulatedPrint() {
window.print = document.getElementById('IDofOutputField');
}
encapsulatedData();
encapsulatedPrint();
print.value = data;
This is not very sanitary code, and what you want is probably not what you should be doing. Could you step back and say what your goal is, rather than the means to that goal? I suspect what you really want to be using are closures or returning first-class functions for delayed evaluation.
For example:
function makePrinter(id) {
var outputfield = document.getElementById(id);
return function(value) {
outputfield.value = value;
}
}
function getValue(id) {
return document.getElementById('IDofSomeHiddenField').value;
}
var data = getValue('IDofOutputField');
var print = makePrinter('IDofOutputField');
print(data);
You have a syntax error I think. You're not closing the parentheses on the first and second lines.
var data = document.getElementById('IDofSomeHiddenField').value;
var print = document.getElementById('IDofOutputField');
print.value = data;
It is also bad form to use JS evaluation like you're attempting to do. If anything you really want to create a function for each of the page elements that returns the page element. ECMAScript 5 has properties which I think is sort of what you're looking for with what you're trying to do but that isn't how ECMAScript 3 JS can work.

Passing references in javascript

This is my first SO post. I'm eternally grateful for the information this community has and shares. Thanks.
I'm coming from Flash and I'm not even sure what the right question to ask is. All I can do is lay out my code example and then explain what I am trying to do. I do not fully grasp the terms that I am trying to illustrate here so I feel it is best to omit them.
The code below is incomplete as it only includes the parts that I feel are relevant to my question. Please refer to the comments in my code to see my issue.
EDIT: Full source file here: [link removed] The console.log outputs the issue in question.
<script type="text/javascript">
var a_chests = [];
var chestID = 0;
//I'm creating a plugin to be able to make multiple instances
(function ($) {
$.fn.chestPlugin = function (option) {
//This function creates a master sprite object which many of my sprites will use
//I've simplified the features to get to the heart of my question
var DHTMLSprite = function (params) {
var ident = params.ident,
var that = {
getID: function(){
return ident;
}
};
return that;
};
//ChestSprite inherits DHTMLSprites properties and then adds a few of its own
var chestSprite = function(params) {
var ident = params.ident,
that = DHTMLSprite(params);
that.reveal=function(){
console.log(ident);
};
return that;
};
//Here I create multiple instances of the chests
var treasure = function ( $drawTarget,chests) {
for (i=0;i<chests;i++){
var cs = chestSprite({
ident: "chest"+chestID
})
console.log(cs.reveal())
//This logs "chest0", "chest1", "chest2" as the for loop executes
//This behavior is correct and/or expected!
a_chests[chestID]={id:i,ob:cs};
//I add a reference to the new chestSprite for later
chestID++;
//increment the chestID;
}
console.log(a_chests[1].ob.reveal());
//This always logs "chest2" (the last chest that is created), even though
//the logs in the for loop were correct. It seems it is referencing the
//DHTML object (since the DHTMLSprite function returns that;) and since
//there is no reference to which chest I need, it passes the last one.
//Is there any way I can pass a reference to DHTMLSprite in order to retain
//the reference to the three individual chests that are created?
//Is there another solution altogether? Thanks!!!
};
//The rest of the code.
return this.each(function () {
var $drawTarget = $(this);
treasure($drawTarget,3);
});
};
})(jQuery);
</script>
You forgot to declare `that' as a local variable, so it's being overwritten on each iteration.
var chestSprite = function(params) {
var that;
var animInterval;
...
When you write:
a_chests[chestID]={id:i,ob:cs};
You are assigning the cs object itself, not an instance of this object. If later you modify cs, this will also modify what you stored in the ob property.
I guess what you need is a closure:
for (i=0;i<chests;i++){
(function(){
var cs = chestSprite({ident: "chest"+chestID});
a_chests[chestID]={id:i,ob:cs};
})();
}
This way, each loop creates a different cs object.

Stacking up methods in Javascript

I have an object I created with this snip-it that looks like this:
...
var steps = new Array();
this.createStep = function(){steps.push(new step()); return steps[steps.length-1];};
this.getSteps = function(){return steps;}; //returns Array
this.removeStep = function(pos){steps.splice(parseInt(pos), 1);}; // integer possition zero base
this.insertStep = function(pos){steps.splice(parseInt(pos),0, new step());};
And this works fine:
...
var newStep = wfObj.createStep();
newStep.setTitle('Step-'+i);
newStep.setStatus('New');
but this does not
var newStep = wfObj.createStep().setTitle('Step-'+i).setStatus('New');
Could someone please tell me how to fix this or even what to call it when you chain methods like this?
This is called a fluent interface. The way to make it work is to have every function return this.
As Ned said, this is sometimes called fluent interface. It's also sometimes called method chaining, as you have heard.
You probably have some code somewhere that looks like this:
this.setTitle = function(newTitle) {
title = newTitle;
};
Change that to this:
this.setTitle = function(newTitle) {
title = newTitle;
return this;
};
Do the same for setStatus.

Categories