Excuses if this has been posted, not sure how to search for such a thing.
I'm working on a website and I'd like to know what current industry conventions are. I am more concerned if there is a reason to avoid calling a method inside of another method.
Below I've placed a few examples, please let me know which one is best.
First, easy example on two lines:
var formattedRole = HTMLheaderRole.replace("%data%", bio.role);
$("#header").prepend(formattedRole);
What about all on one line?
$("#header").prepend(HTMLheaderRole.replace("%data%", bio.role));
Let's get a little more complicated:
var formattedEmployer = HTMLworkEmployer.replace("%data%", work.jobs[job].employer);
var formattedTitle = HTMLworkTitle.replace("%data%", work.jobs[job].title);
var formattedConcat = formattedEmployer.concat(formattedTitle);
$(".work-entry:last").append(formattedConcat);
How about just condensing one of those lines?
var formattedEmployer = HTMLworkEmployer.replace("%data%", work.jobs[job].employer);
var formattedTitle = HTMLworkTitle.replace("%data%", work.jobs[job].title);
$(".work-entry:last").append(formattedEmployer.concat(formattedTitle));
Thanks tons for the input!
Technically, avoiding the extra variable assignments in both of the first examples is slightly more efficient. However, the amount of resources saved is so trivial that you would have to be running the function thousands of times on a particularly old mobile device to see and difference. That said, readability is king when comparing two segments of code that have nearly identical performance. Choose whichever option is easier for you or some other maintainer to read.
Related
I have an idea for a game where people can type in some simple instructions for their character like player.goLeft() or player.attackInFront() and for that I have people type their code into a text box and then I parse it into eval(). This works well but it also allows people to change their own character object by typing things like player.health = Infinity; or something similar. I have a list of functions I want to allow people to use, but I am unsure how to restrict it to only use them.
I understand that the whole point of not letting people use eval is to avoid accidental cross-site scripting but I am unsure on how else to do this. If you have a suggestion please leave a comment about that.
I asked some people around on what to do and most suggested somehow changing scope(which is something I was not able to figure out) or to add some odd parameter to each function in my code that would be required to be a specific string to execute any function, but that seems hacky and since I am making the game in browser with p5js it would be easy to just inspect element and see what the password is.
basically every character has variable called "instruction" which is just a string of javascript. Then every frame of the game I execute it by doing eval(playerList[i].instruction);
tl;dr, how can I only allow specific function to be executed and not allow any others?
EDIT: I forgot to mention that I also am planning to provide player with information so that people can made code that would adapt to the situation. For example there will be parameter called vision that has vision.front and vision.left etc. These variables would just say if there is an enemy, wall, flower, etc around them in a grid. Some people suggested that I just replace some functions with key words but then it compromises the idea of using if statements and making it act differently.
EDIT 2: Sorry for lack of code in this post, but because of the way I am making it, half of the logic is written on server side and half of it works on client side. It will be a little large and to be completely honest I am not sure how readable my code is, still so far I am getting great help and I am very thankful for it. Thank you to everybody who is answering
Do NOT use eval() to execute arbitrary user input as code! There's no way to allow your code to run a function but prevent eval() from doing the same.
Instead, what you should do is make a map of commands the player can use, mapping them to functions. That way, you run the function based on the map lookup, but if it's not in the map, it can't be run. You can even allow arguments by splitting the string at spaces and spreading the array over the function parameters. Something like this:
const instructions = {
goLeft: player.goLeft.bind(player),
goRight: player.goRight.bind(player),
attackInFront: player.attackInFront.bind(player)
};
function processInstruction(instruction_string) {
const pieces = instruction_string.split(' ');
const command = pieces[0];
const args = pieces.slice(1);
if (instructions[command]) {
instructions[command](...args);
} else {
// Notify the user their command is not recognized.
}
};
With that, the player can enter things like goLeft 5 6 and it will call player.goLeft(5,6), but if they try to enter otherFunction 20 40 it will just say it's unrecognized, since otherFunction isn't in the map.
This issue sounds similar to the SQL Injection problem. I suggest you use a similar solution. Create an abstraction layer between the users input and your execution, similar to using parameters with stored procedures.
Let the users type keywords such as 'ATTACK FRONT', then pass that input to a function which parses the string, looks for keywords, then passes back 'player.attackInFront()' to be evaluated.
With this approach you simplify the syntax for the users, and limit the possible actions to those you allow.
I hope this isn't too vague. Good luck!
From your edit, it sounds like you're looking for an object-oriented approach to players. I'm not sure of your existing implementation needs, but it would look like this.
function Player() {
this.vision = {
left: '',
// and so on
}
}
Player.prototype.updateVisibilities = function() {
// to modify the values of this.visibility for each player
}
Player.prototype.moveLeft = function() {
}
Don't give the user an arbitrary interface (such as an input textfield that uses eval) to modify their attributes. Make a UI layer to control this logic. Things like buttons, inputs which explicitly run functions/methods that operate on the player. It shouldn't be up to the player as to what attributes they should have.
Found some things like in Visual Basic but not Javascript and exactly what I'm trying to do. It's a tad bit different. I'm trying to figured out how to rearrange characters in a string, it's in a for loop as well in order to cut the string in half. Now I need to rearrange that.
First I have:
12345678910111213141516
then in the for loop
12345678
I'm trying fix it so now I get
72648531
But I have to do it in a way so people can't read the code and know that there's 8 characters at this point in the string without hard work and trouble. My for loop is also jumbled up and screwy so it can't be figured out. Something like this. I really cannot post the code though.
var con = "";
for (var i = complex math that equals 0; i < complex math to equal 8; i++) {
var newStr = word[i]; // I need it to come out to the rearranged somewhere close by
var con = con+""+newStr;
}
Two commonly used techniques come to mind:
A common approach to things is by doing some XOR calculations: Look at this unrelated examples:
http://www.javascriptsource.com/passwords/xor-encryption4.html
Extracting information from page with Jsoup
You can use tools like http://www.javascriptobfuscator.com/Default.aspx to make it harder for people to figure your code.
This seems to be a regular pattern for me when using d3.js:
function getAttr(d,i) { ... }
things = container.selectAll("selector").data(data);
things.attr("attr", getAttr);
things.enter().append("selector").attr("attr", getAttr);
Is there a better way to do this?
Yes, in recent versions of D3, the .enter() selection merges into the update selection after you've processed it. That is, instead of
things = container.selectAll("selector").data(data);
things.attr("attr", getAttr);
things.enter().append("selector").attr("attr", getAttr);
you can write
things = container.selectAll("selector").data(data);
things.enter().append("selector");
things.attr("attr", getAttr);
Not that much shorter, but it saves you quite a bit of code if you're setting a large number of different attributes, handlers, etc.
I just wanted to know the differences between the methods of adding html in jquery.
both will do samething right?
$('body').append($("<div><img src='somesource' alt='something'></div>"));
and
var div = $("<div>");
var img = $("<img>").attr({"src" : "somesource", "alt" : "something"});
div.append(img);
$('body').append(div);
which is the best practice to follow?
The second is better. Because you often see people doing this:
var alt = 'This is " the title containing a double quote';
$('body').append($('<div><img src="somesource" alt="' + alt + '"></div>'));
and then wonder why something got eaten :-). Whereas when you use the second you have absolutely nothing to worry about:
var alt = 'This is " the title containing a double quote';
var div = $('<div>');
var img = $('<img>').attr({ src : 'somesource', alt : alt });
div.append(img);
$('body').append(div);
UPDATE:
I was too hasty in saying that you have nothing to worry about with the second approach. As others have already pointed out you have to worry about performance.
The second method looks better and there are lesser chances of error. But performance wise, the second method is slower. So if you're going to be doing a lot of appending, I would recommend going with the the first case - albeit, carefully.
Here's a small test case up on JS-Perf comparing the two methods
Normally I would say DOM-scripting is the better option (the second approach); it's more structured, and easier to catch issues than by inserting a mass of HTML prepared as a string.
That said, there are performance concerns. Inserting loads of elements via DOM-scripting, particularly in a loop, can cause significant slowdown and there are cases where inserting as a string is much quicker.
Also, the fewer inserts you do - by whatever means - the fewer repaints/refreshes you force the browser to make. Again, these all require browser attention, so the fewer the better.
I believe you are better off using template libraries for inserting objects. An example of one such library is here: http://api.jquery.com/category/plugins/templates/
Those libraries are build for performance and ease the burden on parsing HTML blobs.
Adding a string of HTML content is about 10 times faster
than using second method
Here is a reference
See also my answer on When do you use DOM-based Generation vs. using strings/innerHTML/JQuery to generate DOM content?
The difference is that you have two variables pointing to the jQuery instances. You might can need them for eventListener-adding or manipulating them lateron in the code.
Also, DOM-based element generation has the advantage of automatically escaping the strings, which is especially useful when designing functions with parameters and absolutely needed for user input.
Therefore, the second method is most often preferred. You can also nest the appending process to make the structure clear (OK, in this example the one-liner would be clear as well):
var div = $("<div>");
var img = $("<img>", {"src":"somesource", "alt":"something"});
$('body').append(
div.append(
img
)
);
I would prefer the second one as the first one could lead to very long lines and if you need to bind events to certain elements you already have a variable that is pointing to it.
On one page of my website the user has the ability to choose and remove up to 2000 items through selecting multiple string representations of them in a dropdown list.
On page load, the objects are loaded onto the page from a previous session into 7 different drop-down lists.
In the window.onload event, the function looping through the items in the drop-downs makes an internal collection of the objects by adding them to a global array - This makes the page ridiculously slow to load, so, I'm fairly certain probably doing it wrong!
How else am I supposed to store these variables?
This is their internal representation:
function Permission(PName, DCID, ID) {
this.PName = PName;
this.DCID = DCID;
this.ID = ID;
}
where: PName is string. DCID is int. ID is int.
EDIT:
Thanks for the quick replies! I appreciate the help, I'm not great with JS! Here is more information:
'selectChangeEvent' is added to the Change and Click event of the Drop down list.
function selectChangeEvent(e) {
//...
addListItem(id);
//...
}
'addListItem(id)' sets up the visual representation of the objects and then calls :
function addListObject(x, idOfCaller) {
var arIDOfCaller = idOfCaller.toString().split('-');
if (arIDOfCaller[0] == "selLocs") {
var loc = new AccessLocation(x, arIDOfCaller[1]);
arrayLocations[GlobalIndexLocations] = loc;
GlobalIndexLocations++;
totalLocations++;
}
else {
var perm = new Permission(x, arIDOfCaller[1], arIDOfCaller[2]);
arrayPermissions[GlobalIndexPermissions] = perm;
GlobalIndexPermissions++;
totalPermissions++;
}
}
Still not enough to go on, but there are some small improvements I can see.
Instead of this pattern:
var loc = new AccessLocation(x, arIDOfCaller[1]);
arrayLocations[GlobalIndexLocations] = loc;
GlobalIndexLocations++;
totalLocations++;
which seems to involve redundant counters and has surplus assignment operations, try:
arrayLocations[arrayLocations.length] = new AccessLocation(x, arIDOfCaller[1]);
and just use arrayLocations.length where you would refer to GlobalIndexLocations or totalLocations (which fromt he code above would seem to always be the same value).
That should gain you a little boost, but this is not your main problem. I suggest you add some debugging Date objects to work out where the bottleneck is.
You may want to consider a design change to support the load. Some sort of paged result set or similar, to cut down on the number of concurrent records being modified.
As much as we desperately want them to be, browsers aren't quite there yet in terms of script execution speed that allow us to do certain types of heavy lifting on the client.
While I haven't tested this idea, I figured I'd throw it out there - might it be faster to return a JSON string from the server side, where your array is fully calculated on that side?
From that point, I'd wager that eval()'ing it (as evil as this may be) might be fast enough to where you could then write the contents onto the page, and your array setup would already be taken care of.
Then again, I suppose the amount of work it'd take the browser to construct the 2k new objects and inject them into the DOM wouldn't necessarily help the speed side of things in the end. At the end of the day, a design change is probably necessary, but sometimes we're stuck with what we've got, eh?