During some basic tests of JS usage I have been playing around with object generation / addition to an array. I have so far used two different approaches for this problem:
A single global object which has fields varied and then added.
A factory function which generates the same object with an additional operation to show a slight difference (Addition of 1 to the value field)
While there are no errors at run time the value field on the global object property always outputs a 2 (Where the value is suppose to increment with the loop), while the function approach seemingly works without issue. Do you have any idea why this would be the case?
The final output I generated was "[{"name":"Hello","value":2},{"name":"Hello World","value":1},{"name":"Hello","value":2},{"name":"Hello World","value":2},{"name":"Hello","value":2},{"name":"Hello World","value":3}]" (from the console.log(JSON.stringify(testArray));).
I had expected an output of "[{"name":"Hello","value":0},{"name":"Hello World","value":1},{"name":"Hello","value":1},{"name":"Hello World","value":2},{"name":"Hello","value":2},{"name":"Hello World","value":3}]"
The code for the relevant functions and object can be found below.
Defining the global variable:
var globalVariable =
{
name: undefined,
value: undefined
}
Factory function:
function globalVariableGen(name, valueInput)
{
return output =
{
name: name,
value: valueInput + 1
}
}
Array generation function:
function test2()
{
var i, testArray = [];
for (i = 0; i < 3; i++)
{
alert(i.toString());
globalVariable.name = "Hello";
globalVariable.value = i;
testArray.push(globalVariable);
testArray.push(globalVariableGen("Hello World", i));
}
console.log(JSON.stringify(testArray));
}
Kind regards,
Shadow
This is because javascript is pass-by-reference and you're referring to the same globalVariable which you add to the array multiple times. The array then contains multiple pointers to the globalVariable which is exactly the same.
If you add a console.log(JSON.stringify(testArray) into the loop you will see this behavior.
> "[{"name":"Hello","value":0},{"name":"Hello World","value":1}]"
> "[{"name":"Hello","value":1},{"name":"Hello World","value":1},{"name":"Hello","value":1},{"name":"Hello World","value":2}]"
> "[{"name":"Hello","value":2},{"name":"Hello World","value":1},{"name":"Hello","value":2},{"name":"Hello World","value":2},{"name":"Hello","value":2},{"name":"Hello World","value":3}]"
Related
How change strings in javascript arrays. I want to change array codes to strings.
How change strings in javascript arrays. I want to change array codes to strings.
How to get this;
var _0x1576 = ["SayHello", "GetCount", "Message : ", "You are welcome."];
function NewObject(_0x7aa7x2) {
var _0x7aa7x3 = 0;
this.SayHello = function (_0x7aa7x4) {
_0x7aa7x3++;
alert(_0x7aa7x2 + _0x7aa7x4);
};
this.GetCount = function () {
return _0x7aa7x3
};
}
var obj = new NewObject("Message : ");
obj.SayHello("You are welcome.");
from;
var _0x1576 = ["SayHello", "GetCount", "Message : ", "You are welcome."];
function NewObject(_0x7aa7x2) {
var _0x7aa7x3 = 0;
this[_0x1576[0]] = function (_0x7aa7x4) {
_0x7aa7x3++;
alert(_0x7aa7x2 + _0x7aa7x4);
};
this[_0x1576[1]] = function () {
return _0x7aa7x3
};
}
var obj = new NewObject(_0x1576[2]);
obj.SayHello(_0x1576[3]);
EDIT: So you have some code, where all the variable names have been replaced by numbers or indices into this global array of names, and you would like to be able to read it. There is already an answer to this question, which contains links to a bunch of useful deobfuscation tools.
Your case here looks fairly trivial - it appears that you could just do a string search and replace, substituting in the array value every time it is indexed. The regexp /_0x1576\[(\d+)\]/g should find everything that accesses the variable _0x1576 with an integer index. The inner group (\d+) should give you the index with which it was found. You could use something like this to do deobfuscate your source. However, some of the names have been lost in the obfuscation process; i.e. the name of the parameter 0x7aa7x4 in the SayHello function can't be restored. You will have to read the method, understand what its' purpose is, and try to come up with a meaningful name yourself.
One question though - just how much code do you have like this? If there are only a few names in the array of strings, then #Nina Scholz's suggestion seems fairly reasonable. Just go through them one by one, in a text editor, and use the 'Find and Replace' functionality.
This may not be a good question, but it does makes sense(atleast to me, it does.)
Suppose I have a multi-dimensional array called temporaryFrequency. Now, I want to write a function which will take one argument --> frequencyArray[number]. This will be more clear from the code:
JS:
function getMaxTemporaryFrequency(frequencyArray[number]){
var maxOutofThese = frequencyArray[number][0];
for(var i = 0; i < frequencyArray[number].length; i++){
if(frequencyArray[number][i] > maxOutofThese)
maxOutofThese = frequencyArray[number][i];
}
return maxOutofThese;
}
This is the function which will return the maximum frequency from a sub-array of an array. Now, I will execute the following code to call the function:
//This is to get the max out of the temporary frequencies
for(var n = 0; n < temporaryFrequency.length; n++){
var maximumTempFrequency + (n + 1) = getMaxTemporaryFrequency(temporaryFrequency[n]);
}
Now, I have one more question attached to this. Can variable names be concatenated, like a did here? For example, for each loop count, I want to make variables : maximumTempFrequency1 , maximumTempFrequency2 , maximumTempFrequency3 and so on.
Now, this call of the function passes the nth element of the temporaryFrequency array to the function, which should return the greatest value from that nth sub-array. But, that is not working.
So, to summarise my question:
1) Can we pass an array with a key to function, like I did here? If
no, is there any way to do it?
2) Can we concatenate strings to make a variable name, like I did in
the 'for' loop? If no, is there any other method
*NOTE: For this question, viewers don't need to know the contents of the temporaryFrequency array.
The straight answer to your two questions are No.
The syntax function getMaxTemporaryFrequency(frequencyArray[number]) { ... } is not valid. The parser is expecting an identifier for the parameter name, and identifiers can't have brackets in them [ or ]. This results in the error:
Uncaught SyntaxError: Unexpected token [
Similarly, your variable name is also syntactically invalid. var maximumTempFrequency + (n + 1) = //anything results in
Uncaught SyntaxError: Unexpected token +
To answer your follow up questions of How to make it work, for the first question you can pass the dereferenced array member to the function when you call it (instead of when you declare it).
var frequencyArray = []; // fill it with your values
var number = 0; // or whatever number you want
function getMaxTemporaryFrequency(arr){
var maxOutofThese = arr[0];
for(var i = 0; i < arr.length; i++){
if(arr[i] > maxOutofThese)
maxOutofThese = arr[i];
}
return maxOutofThese;
}
function getMaxTemporaryFrequency(frequencyArray[number]);
For the latter one, you want to store the results to an array, like this:
//This is to get the max out of the temporary frequencies
var maximumTempFrequency = [];
for(var n = 0; n < temporaryFrequency.length; n++){
maximumTempFrequency[n+1] = getMaxTemporaryFrequency(temporaryFrequency[n]);
}
Note that your syntax getMaxTemporaryFrequency(temporaryFrequency[n]) is an example of what I put in the first code block above.
I'm working through the end of the first example in Chapter 4 Eloquent Javascript. Here is the full piece of code (It's the last piece that I have questions regarding but I attached the first portion for reference).
var journal = [];
function addEntry(events, didITurnIntoASquirrel) {
journal.push({
events: events,
squirrel: didITurnIntoASquirrel
});
function phi(table) {
return (table[3] * table[0] - table[2] * table[1]) /
Math.sqrt((table[2] + table[3]) *
(table[0] + table[1]) *
(table[1] + table[3]) *
(table[0] + table[2]));
}
function hasEvent(event, entry) {
return entry.events.indexOf(event) != -1;
}
function tableFor(event, journal) {
var table = [0, 0, 0, 0];
for (var i = 0; i < journal.length; i++) {
var entry = journal[i], index = 0;
if (hasEvent(event, entry)) index += 1;
if (entry.squirrel) index += 2;
table[index] += 1;
}
return table;
}
function gatherCorrelations(journal) {
var phis = {};
for (var entry = 0; entry < journal.length; entry++) {
var events = journal[entry].events;
for (var i = 0; i < events.length; i++) {
var event = events[i];
if (!(event in phis))
phis[event] = phi(tableFor(event, journal));
}
}
return phis;
}
var correlations = gatherCorrelations(JOURNAL);
console.log(correlations.pizza);
My questions are:
What is the purpose of the .events in
var events = journal[entry].events;
Does it call on itself as a recursion? If so why? Couldn't we have just had journal[entry] and the function would run calling on the entry from the tableFor function? Does it call back to the AddEntry function (where the events variable was established) in an important way?
What is the purpose of (!(event in phis)).
I read it as : if event in phis is true then flip it to be not true and then trigger necessary phi calculation. Wouldn't it make more sense to eliminate the ! (does not equal) or that piece of code altogether? If we already have a for loop won't the function run on it's on until the max length of journal and stop?
var events = journal[entry].events; you are getting the events object from the object at index entry in the array journal and assigning it to a temporary variable called events.
This is just done for convenience so you don't have to keep referring to journal[entry].events. For example, later on it has this line:
var event = events[i];
which would become:
var event = journal[entry].events[i];
Without the assignment to a temporary variable.
if(!(event in phis)) it's testing to see if the object phis does not have a property with the name contained in the variable event. If the object doesn't already have that property, it adds it with the next line:
phis[event] = phi(tableFor(event, journal));
See in operator
Here's a very simple snippet of code to help understand the in operator:
var foo = {};
console.log("bar" in foo); // logs "false" because foo doesn't have a "bar" property
foo.bar = 1; // or foo["bar"] = 1;
console.log("bar" in foo); // logs "true" because foo now has a "bar" property
What is the purpose of the .events in
var events = journal[entry].events;
The purpose of this declaration conforms with 2 concepts of scripting convenience and economy. Every level of an object depth adds to the overall recall time when called. Certainly modern browsers have done much to flatten an objects variable stack, but if you think about it logically, any call to say object1.object2["Memeber3"].object4 has to go through 4 steps to get to the value itself. Flattening the value to a local object is more economic. Second, the readability (and therefore maintainability) of the code is enhanced in that you don't have the extra "journal[entry]." clogging up your expressions. As a general rule of thumb, if you are going to use a member of an object more than once in a block, then you should create a local variable of that member.
What is the purpose of
(!(event in phis)).
The purpose of this evaluation is to determine if a particular member(event) is NOT in the object(phis). In this example, the next line creates that member if it is indeed missing.
I am writing a page that collects serial numbers for parts installed in an assembly. I want to validate the user input on the client-side, if I can.
So if I have multiple dense arrarys, how can I refer to them using a varaiable? For instance, say I have three densely packed arrays who's names represent part numbers, and who's values represent serial numbers (that have been consumed in other assemblies).
arr_PN-123-ABC = ('SN0123','SN0124','SN0125')
arr_PN-456-DEF = ('SN00333','SN00334','SN00335')
arr_PN-789-GHI = ('SN-0001','SN-0002','SN-0003','SN-0004')
function fcnValidateSN(_givenPN, _givenSN) {
//make sure the given values are not null or empty...
//derive the array of serial numbers that coorsponds to the given part number...
var vArrName = "arr_" + vGivenPN;
//loop thru the array of serial numbers to determine if the given sn was already used...
for(var x=0; x < vArrName.length(); x++) {
if(vArrName[x]==_givenSN) {
alert("Serial number '" + _givenSN + "' was already used in another assembly.");
theForm.txtPN.focus();
return;
}
} //end 'for' loop
} //end fcnValidateSN()
So the problem is that 'vArrName' is a string with a value of 'arr_' instead of a refernece to an array who's name is 'arr_'.
I tried wrapping it with the eval() function, but eval() treats dashes as minus signs.
One other note: I cannot use jquery for this effort.
Thank you
You cannot generate a reference to a variable declared with var (except see below). You can use dynamic property names to refer to properties of objects, so:
var arrays = {
"arr_PN-123-ABC": ['SN0123','SN0124','SN0125'],
"arr_PN-456-DEF": ['SN00333','SN00334','SN00335'],
// ...
};
Then:
console.log( arrays["arr_PN-" + num + "ABC"][0] ); // SN0123
Note that you cannot use "-" in a variable name, but you can use it in an object property name.
The exception to not being able to access var variables by dynamic name is made for global variables in a browser. Those variables all end up as properties of the window object.
An array in JavaScript is delimitated by [ and ], not ( or ).
A valid JavaScript variable name can't contain '-'
The length property of an array isn't a function
Well, I've done some (actually, a lot of) adjustments in your code, but I think this is what you need:
var serialGroups = {
PN_123_ABC: ['SN0123','SN0124','SN0125'],
PN_456_DEF: ['SN00333','SN00334','SN00335'],
PN_789_GHI: ['SN-0001','SN-0002','SN-0003','SN-0004']
};
function validateSerial(groupName, sn) {
var serials = serialGroups[groupName];
for(var i=0; i < serials.length; i++){
if(serials[i] == sn) {
alert("Serial number '" + sn + "' was already used in another assembly.");
//Do whatever you want here
return;
}
}
}
Use a single object that has the arrays as elements:
var arr_PN = {
'123-ABC': ('SN0123','SN0124','SN0125'),
'456-DEF': ('SN00333','SN00334','SN00335'),
'789-GHI': ('SN-0001','SN-0002','SN-0003','SN-0004')
}
And then reference using:
var vArrName = arr_PN->{vGivenPN};
Hello I'm working on a problem that requires me to change an set array of numbers into an array that returns the original numbers as a function. So we get a return of a2 instead of a[2].
I dont want the answer I just need a hint. I know i can loop through the array and use .pop() to get the last value of the array, but then I dont know how to convert it to a function from there. any hints?
var numToFun = [1, 2, 3];
var numToFunLength = numToFun.length;
for (var i = 0; i < numToFunLength; i++) {
(function(num){
numToFun.unshift(function() {
return num;
});
}(numToFun.pop()))
}
DEMO
basically it pops out a number from the last, builds a function with that number returned, and put back into the first of the array. after one full cycle, all of them are functions.
here's the catch: how this works, it's up to you to research
why the loop does not look like the straightforward pop-unshift:
for (var i = 0; i < numToFunLength; i++) {
numToFun.unshift(function() { //put into first a function
return numToFun.pop() //that returns a number
});
}
and why i did this: (HINT: performance)
var numToFunLength = numToFun.length;
There's three important steps here:
Extract the number value from the array. Within a loop with an iterator of i, it might look like this:
var num = numArray[i];
This is important, because i will not retain its value that it had when you created the new function - it'll end up with the last value it had, once the for loop is finished. The function itself might look like this:
function() { return num; }
There's no reference to i any more, which is important - to understand better, read about closures. The final step would be to add the new function to the array of functions that you want.
...and you're done!
EDIT: See other's answers for good explanations of how to do this right, I will fix mine also though
As others have pointed out, one of the tricky things in javascript that many struggle with (myself included, obviously) is that scoping variables in javascript is dissimilar to many other languages; scopes are almost purely defined by functions, not the {} blocks of, for example, a for loop, as java/C would be.
So, below you can see (and in other answers here) a scoping function can aid with such a problem.
var numArray = [12, 33, 55];
var funcArray = [];
var numArrLength = numArray.length; // Don't do this in for loop to avoid the check multiple times
for(var j=0; j < numArrLength; j++) {
var scopeMe = function() {
var numToReturn = numArray[j];
console.log('now loading... ' + numToReturn);
var newFunc = function() {
return numToReturn;
};
return newFunc;
}();
funcArray.push(scopeMe);
};
console.log('now me');
console.log(funcArray);
console.log(funcArray[0]());
console.log(funcArray[1]());
console.log(funcArray[2]());
console.log(funcArray[1]()); // To ensure it's repeatable
EDIT my old bad answer below
What you'll want to do is something like
var funcArray = [];
for(...) {
var newFunc = function() {
return numArray.pop();
}
funcArray.push(newFunc);
}
The key here is that functions in javascript can be named variables, and passed around as such :)