Variable is not changing value - javascript

So, I'm designing a code that will enable the user to create pseudo-custom operations that one can use under a special eval() function (as JavaScript is not an extendable language). My problem is that only the first variable created seems to register and be evaluated.
I am posting here a large snippet of the code.
var CMD = function(){
var objs = gAO() /* gets all of the objects */;
// testing for other instances of the CMD object.
this .bool = 0;
for(obj in objs) this .bool ^= !objs[obj]["_aqz39"] // boolean
if(this .bool){
// DEFINING VARS
this .objs = objs;
this["_aqz39"] = true;
this .ops = []; this .eqs = [];
}
}
{ /* init */
var cmd = new CMD();
}
// USER INPUT FOR CREATING 'NEW VARIABLES'
var Operator = function(op,input){
// SYNTAX: "<operator>","x <operator> y = <result, using 'x' and 'y'>"
// EXAMPLE: "#","x # y = 3 * x - y"
this .op = op;
this .eq = input.split("=")[1].trim();
}
// FUNCTION FOR ACTIVATING THE VARIABLE TO BE
// ...RECOGNIZED BY THE CMD's 'EVAL' FUNCTION
activate = function(ind){
cmd.ops.push(ind.op);
cmd.eqs.push(ind.eq);
}
CMD.prototype.eval = function(equ){
// DECLARING VARS
var t = cmd,oper,equation,x,y,i=0;
// LOOPS THROUGH ALL OF THE CHILDREN OF cmd.ops
while (i < t["ops"].length){
// CHECKS TO SEE IF THE INPUT CONTAINS THE SYMBOL
if(equ.search(oper) !== -1){
// the operator
oper = t["ops"][i];
// the equation
equation = t["eqs"][i];
// from the first index to the beginning of the operator
x = equ.slice(0,equ.search(oper)).trim(),
// from right after the operator to the end of the thing
y = equ.slice(equ.search(oper)+1,equ.length).trim();
/* INFORMATION LOGGING */
console.log({x:x,y:y,oper:oper,equation:equation,i:i,t:t,bool: equ.search(oper),len:t["ops"].length})
// RESULT
return eval(eval(equation));
}
// INCREMENTS 'i'
i++;
}
// ELSE
return false;
}
Testing #1
var hash = new Operator("#","x # y = 3 * x - y");
var dash = new Operator("q","x q y = y");
activate(dash);
activate(hash);
console.log(cmd.eval("3 q -2")); // RETURNS -2
console.log(cmd.eval("3 # -2")); // RETURNS NOTHING
Testing #2
var hash = new Operator("#","x # y = 3 * x - y");
var dash = new Operator("q","x q y = y");
activate(hash); // HASH IS CALLED FIRST THIS TIME
activate(dash);
console.log(cmd.eval("3 q -2")); // RETURNS NaN
console.log(cmd.eval("3 # -2")); // RETURNS 11
I've been troubleshooting this thing for about an hour, and I have no idea what's going wrong. Help is highly appreciated.

Here you are using the variable oper before you have assigned anything to it:
if(equ.search(oper) !== -1){
oper = t["ops"][i];
The undefined value will be converted into an empty regular expression, so it will always return a match, that's why the first operator works. In the next iteration the variable will be assigned the wrong operator.
Assign the operator to it before using it to look for the operator:
oper = t["ops"][i];
if(equ.search(oper) !== -1){

Related

Why does RegExp exec() not work properly in my case? [duplicate]

This question already has answers here:
Why does a RegExp with global flag give wrong results?
(7 answers)
Closed 3 years ago.
If the RegExp is defined global and I use the vals array like I do, the result of exec will be the same everytime, so the code below is an infinity loop.
var regex = RegExp(/<(.*?)>.*?<\/\1>/, "g");
function readXml(xmlString) {
var obj = {};
var vals;
for (var i = 0;
(vals = regex.exec(xmlString)) !== null; i++) {
if (!obj[vals[1]]) obj[vals[1]] = [];
obj[vals[1]].push(readXml(vals[0].slice(vals[1].length + 1, -vals[1] - length - 3)));
}
if (i == 0) return xmlString;
return obj;
}
console.log(readXml("<a>a</a><b>b</b>"));
If the RegExp is defined in function, the result of exec will be the next match everytime, so the code below logs a and b.
function readXml(xmlString) {
var regex = RegExp(/<(.*?)>.*?<\/\1>/, "g");
var obj = {};
var vals;
for (var i = 0;
(vals = regex.exec(xmlString)) !== null; i++) {
if (!obj[vals[1]]) obj[vals[1]] = [];
obj[vals[1]].push(readXml(vals[0].slice(vals[1].length + 1, -vals[1] - length - 3)));
}
if (i == 0) return xmlString;
return obj;
}
console.log(readXml("<a>a</a><b>b</b>"));
If I do something else with vals arrray in the loop, the result of exec will be the next match everytime, so the code below logs an empty object.
var regex = RegExp(/<(.*?)>.*?<\/\1>/, "g");
function readXml(xmlString) {
var obj = {};
var vals;
for (var i = 0;
(vals = regex.exec(xmlString)) !== null; i++) {
vals = [2]
}
if (i == 0) return xmlString;
return obj;
}
console.log(readXml("<a>a</a><b>b</b>"));
I think it should be an object with a and b in the first case too.
Why doesn't it just do the same thing in all cases?
Global regexes (ie. using the g flag) keep track of the position of the last match in order to successfully get the next one the next time you call exec. It makes the assumption that you're passing the same input string each time, but if you go and change the input then it goes weird.
const regex = RegExp(/./,'g'); // should match each character, one at a time.
let input1 = 'test', match;
match = regex.exec(input1);
console.log(match[0]);
// now let's "re-use" the regex object...
let input2 = 'another test';
match = regex.exec(input2);
console.log(match[0]);
console.log("Where did the `a` go??");
You can access and modify the property responsible for this behaviour via regex.lastIndex, although in this case your best solution is to create a new RegExp object within the function, since you're working recursively.

Sort function that uses an integer array argument doesnt work

I'm a beginner trying to learn JS, I've got some basic knowledge.
I wrote a function to realize insertion sort on a given array (the array is passed on to the function as a parameter).
When I initialize the array and give it value, e.g,
sampleArray = [1,35,73,234,1,1,356];
and pass that to my function, it works perfectly.
however, if I try to pass on an array filled by user input - or an array that was merged out of two given arrays (my original assignment),
it doesn't work - no exceptions or errors, it just... doesn't sort as expected.
I've been racking my mind over this, maybe I don't know where to look?
function sortArray(arrT) {
for (let i = 1; i < arrT.length; i++){
var tempMax = arrT[i];
var j = i - 1;
while ((j >= 0) && (arrT[j] > tempMax)) {
console.log(arr1 + "\nj=" + j + " i=" + i);
arrT[j+1] = arrT[j];
j--;
}
arrT[j+1] = tempMax;
}
console.log("sorted array is (inside loop) :\n" +arrT);
return arrT;
}
for an array that was filled by a while loop of prompts such as
it's equal to the above sample array, the result is
1,1,1,234,35,356,73
for reference, though it's far from elegant, I'm using this to fill the array:
for (let i = 0, x = ""; x !== "x"; i++) {
x = prompt("press x to finish, enter to continue");
if (x == "x") { break }
arr1[i]=prompt("enter");
}
As per my understanding.
The mistake is here
Original Code:
for (let i = 0, x = ""; x !== "x"; i++) {
x = prompt("press x to finish, enter to continue");
if (x == "x") { break }
arr1[i]=prompt("enter");//do not use prompts while unnecessary. Just replace it with x;
}
Corrected One:
for (let i = 0, x = ""; x !== "x"; i++) {
x = prompt("press x to finish, enter to continue");
if (x == "x") { break }
/*
you can also improve your code by applying few checks
if(!isNaN(x)) continue; // --- to skip when input value isn't a number
*/
arr1[i]=x;
}
for (let i = 0, x = ""; x !== "x"; i++) {
x = prompt("press x to finish, enter to continue");
if (x == "x") { break }
arr1[i]=prompt("enter");
}
prompt actually returns a string, hence your input is an array of strings instead. You should use Number to ensure the provided value is numeric.
I would rewrite the above in this way:
// stores all the values.
var arr1 = [];
// Stores the current value.
var input;
do {
var _ = prompt("press x to finish, enter to continue"); // <-- not sure why you're doing that every time, I would suggest you to move it outside of the loop.
input = prompt("enter");
var n = Number(input);
if (!isNaN(n)) arr1.push(n); // <-- checks whether the provided value is actually numeric and a valid number. If it is, the value is added to the collection.
}
while (input !== 'x');
console.log(arr1);
I would suggest you to move the first prompt outside of the loop, but since you did it in your code, I suspect there is a reason for that, though I don't get it.
In any case, the above sample will check whether the value passed is valid; if it is, it push the item to the collection, otherwise it continues until 'x' is met.

javascript return units, if present when multiplying 2 numbers

2 numbers input to my function values are a, "0.045u" and b, "3"
function mult2nums(a,b) {
var c = null;
var unitsFora = null;
var unitsForb = null;
var cUnits = null;
//--> issue - unitsFora = ??; // how to strip off units designator
//--> issue - unitsForb = ??; // how to strip off units designator
a = isFloat(a); // also works if int
b = isFloat(b); //
c = a*b;
// add logic to compare unit designators and convert as needed
return(c+cUnits); // need to return the units, returns a string type
}
You can use regex to filter out the units:
function mult2nums(a,b) {
var c = null;
var cUnits = null;
var unitRegex = /[A-Za-z].*/g
var unitsForA = a.match(unitRegex);
var unitsForB = b.match(unitRegex);
a = parseFloat(a.replace(unitsForA, ''));
b = parseFloat(b.replace(unitsForB, ''));
c = a*b;
// add logic to compare unit designators and convert as needed
return c + cUnits;
}
Note that the code uses the first encounter of character as the start position of the unit. It can handle upper/lower case differences, and units with number in it (e.g. m/s^2). You can modify the code further to suit your specific needs.
jsFiddle sample:
https://jsfiddle.net/ywafx1be/

Can't convert Javascript array to object properly

I have been struggling with this problem the entire day. I feel like it's super solvable, and I'm not sure where I'm going wrong. Each time I go to post this, I feel like I come up with a different solution that doesn't end up working.
I'm looking to do the following:
var someObj = {};
// #param key - string - in the form of "foo-bar-baz" or "foo-bar".
// (i won't know the number of segments ahead of time.)
// #param value - string - standard, don't need to act on it
function buildObject( key, value ) {
var allKeys = key.split("-");
// do stuff here to build someObj
}
Essentially the key will always take the format of key-key-key where i want to build someObj[key1][key2][key3] = value.
This JSFiddle contains a longer example with a sample layout of the data structure I want to walk away with.
Thanks so much for any help you can give.
var someObj = {};
// #param key - string - in the form of "foo-bar-baz" or "foo-bar".
// (i won't know the number of segments ahead of time.)
// #param value - string - standard, don't need to act on it
function buildObject( key, value ) {
var allKeys = key.split("-");
var container, i, n;
for (container = someObj, i = 0, n = allKeys.length; i < n - 1; ++i) {
var keyPart = allKeys[i];
container = Object.hasOwnProperty.call(container, keyPart)
? container[keyPart] : (container[keyPart] = {});
}
container[allKeys[n - 1]] = value;
}
I came up with http://jsfiddle.net/XAn4p/ before i saw Mike's answer. I'm posting just for another way.
var newObj = function ()
{};
newObj.prototype =
{
addToObject: function (keys, value)
{
var keySplit = keys.split("-",2);
if (keySplit.length > 1)
{
if(this[keySplit[0]] == null)
{
this[keySplit[0]] = new newObj();
}
var newKeys = keys.substr(keySplit[0].length +1);
this[keySplit[0]].addToObject(newKeys, value);
}
else
{
this[keySplit[0]] = value
}
}
};
var obj = new newObj();

Parse query string in JavaScript [duplicate]

This question already has answers here:
How can I get query string values in JavaScript?
(73 answers)
Closed 3 years ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Duplicate This question has been answered, is not unique, and doesn’t differentiate itself from another question.
I need to parse the query string www.mysite.com/default.aspx?dest=aboutus.aspx.
How do I get the dest variable in JavaScript?
Here is a fast and easy way of parsing query strings in JavaScript:
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
Now make a request to page.html?x=Hello:
console.log(getQueryVariable('x'));
function parseQuery(queryString) {
var query = {};
var pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&');
for (var i = 0; i < pairs.length; i++) {
var pair = pairs[i].split('=');
query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || '');
}
return query;
}
Turns query string like hello=1&another=2 into object {hello: 1, another: 2}. From there, it's easy to extract the variable you need.
That said, it does not deal with array cases such as "hello=1&hello=2&hello=3". To work with this, you must check whether a property of the object you make exists before adding to it, and turn the value of it into an array, pushing any additional bits.
You can also use the excellent URI.js library by Rodney Rehm. Here's how:-
var qs = URI('www.mysite.com/default.aspx?dest=aboutus.aspx').query(true); // == { dest : 'aboutus.aspx' }
alert(qs.dest); // == aboutus.aspx
And to parse the query string of current page:-
var $_GET = URI(document.URL).query(true); // ala PHP
alert($_GET['dest']); // == aboutus.aspx
Me too! http://jsfiddle.net/drzaus/8EE8k/
(Note: without fancy nested or duplicate checking)
deparam = (function(d,x,params,p,i,j) {
return function (qs) {
// start bucket; can't cheat by setting it in scope declaration or it overwrites
params = {};
// remove preceding non-querystring, correct spaces, and split
qs = qs.substring(qs.indexOf('?')+1).replace(x,' ').split('&');
// march and parse
for (i = qs.length; i > 0;) {
p = qs[--i];
// allow equals in value
j = p.indexOf('=');
// what if no val?
if(j === -1) params[d(p)] = undefined;
else params[d(p.substring(0,j))] = d(p.substring(j+1));
}
return params;
};//-- fn deparam
})(decodeURIComponent, /\+/g);
And tests:
var tests = {};
tests["simple params"] = "ID=2&first=1&second=b";
tests["full url"] = "http://blah.com/?third=c&fourth=d&fifth=e";
tests['just ?'] = '?animal=bear&fruit=apple&building=Empire State Building&spaces=these+are+pluses';
tests['with equals'] = 'foo=bar&baz=quux&equals=with=extra=equals&grault=garply';
tests['no value'] = 'foo=bar&baz=&qux=quux';
tests['value omit'] = 'foo=bar&baz&qux=quux';
var $output = document.getElementById('output');
function output(msg) {
msg = Array.prototype.slice.call(arguments, 0).join("\n");
if($output) $output.innerHTML += "\n" + msg + "\n";
else console.log(msg);
}
var results = {}; // save results, so we can confirm we're not incorrectly referencing
$.each(tests, function(msg, test) {
var q = deparam(test);
results[msg] = q;
output(msg, test, JSON.stringify(q), $.param(q));
output('-------------------');
});
output('=== confirming results non-overwrite ===');
$.each(results, function(msg, result) {
output(msg, JSON.stringify(result));
output('-------------------');
});
Results in:
simple params
ID=2&first=1&second=b
{"second":"b","first":"1","ID":"2"}
second=b&first=1&ID=2
-------------------
full url
http://blah.com/?third=c&fourth=d&fifth=e
{"fifth":"e","fourth":"d","third":"c"}
fifth=e&fourth=d&third=c
-------------------
just ?
?animal=bear&fruit=apple&building=Empire State Building&spaces=these+are+pluses
{"spaces":"these are pluses","building":"Empire State Building","fruit":"apple","animal":"bear"}
spaces=these%20are%20pluses&building=Empire%20State%20Building&fruit=apple&animal=bear
-------------------
with equals
foo=bar&baz=quux&equals=with=extra=equals&grault=garply
{"grault":"garply","equals":"with=extra=equals","baz":"quux","foo":"bar"}
grault=garply&equals=with%3Dextra%3Dequals&baz=quux&foo=bar
-------------------
no value
foo=bar&baz=&qux=quux
{"qux":"quux","baz":"","foo":"bar"}
qux=quux&baz=&foo=bar
-------------------
value omit
foo=bar&baz&qux=quux
{"qux":"quux","foo":"bar"} <-- it's there, i swear!
qux=quux&baz=&foo=bar <-- ...see, jQuery found it
-------------------
Here's my version based loosely on Braceyard's version above but parsing into a 'dictionary' and support for search args without '='. In use it in my JQuery $(document).ready() function. The arguments are stored as key/value pairs in argsParsed, which you might want to save somewhere...
'use strict';
function parseQuery(search) {
var args = search.substring(1).split('&');
var argsParsed = {};
var i, arg, kvp, key, value;
for (i=0; i < args.length; i++) {
arg = args[i];
if (-1 === arg.indexOf('=')) {
argsParsed[decodeURIComponent(arg).trim()] = true;
}
else {
kvp = arg.split('=');
key = decodeURIComponent(kvp[0]).trim();
value = decodeURIComponent(kvp[1]).trim();
argsParsed[key] = value;
}
}
return argsParsed;
}
parseQuery(document.location.search);
Following on from my comment to the answer #bobby posted, here is the code I would use:
function parseQuery(str)
{
if(typeof str != "string" || str.length == 0) return {};
var s = str.split("&");
var s_length = s.length;
var bit, query = {}, first, second;
for(var i = 0; i < s_length; i++)
{
bit = s[i].split("=");
first = decodeURIComponent(bit[0]);
if(first.length == 0) continue;
second = decodeURIComponent(bit[1]);
if(typeof query[first] == "undefined") query[first] = second;
else if(query[first] instanceof Array) query[first].push(second);
else query[first] = [query[first], second];
}
return query;
}
This code takes in the querystring provided (as 'str') and returns an object. The string is split on all occurances of &, resulting in an array. the array is then travsersed and each item in it is split by "=". This results in sub arrays wherein the 0th element is the parameter and the 1st element is the value (or undefined if no = sign). These are mapped to object properties, so for example the string "hello=1&another=2&something" is turned into:
{
hello: "1",
another: "2",
something: undefined
}
In addition, this code notices repeating reoccurances such as "hello=1&hello=2" and converts the result into an array, eg:
{
hello: ["1", "2"]
}
You'll also notice it deals with cases in whih the = sign is not used. It also ignores if there is an equal sign straight after an & symbol.
A bit overkill for the original question, but a reusable solution if you ever need to work with querystrings in javascript :)
If you know that you will only have that one querystring variable you can simply do:
var dest = location.search.replace(/^.*?\=/, '');
The following function will parse the search string with a regular expression, cache the result and return the value of the requested variable:
window.getSearch = function(variable) {
var parsedSearch;
parsedSearch = window.parsedSearch || (function() {
var match, re, ret;
re = /\??(.*?)=([^\&]*)&?/gi;
ret = {};
while (match = re.exec(document.location.search)) {
ret[match[1]] = match[2];
}
return window.parsedSearch = ret;
})();
return parsedSearch[variable];
};
You can either call it once without any parameters and work with the window.parsedSearch object, or call getSearch subsequently.
I haven't fully tested this, the regular expression might still need some tweaking...
How about this?
function getQueryVar(varName){
// Grab and unescape the query string - appending an '&' keeps the RegExp simple
// for the sake of this example.
var queryStr = unescape(window.location.search) + '&';
// Dynamic replacement RegExp
var regex = new RegExp('.*?[&\\?]' + varName + '=(.*?)&.*');
// Apply RegExp to the query string
var val = queryStr.replace(regex, "$1");
// If the string is the same, we didn't find a match - return false
return val == queryStr ? false : val;
}
..then just call it with:
alert('Var "dest" = ' + getQueryVar('dest'));
Cheers
I wanted a simple function that took a URL as an input and returned a map of the query params.
If I were to improve this function, I would support the standard for array data in the URL, and or nested variables.
This should work back and for with the jQuery.param( qparams ) function.
function getQueryParams(url){
var qparams = {},
parts = (url||'').split('?'),
qparts, qpart,
i=0;
if(parts.length <= 1 ){
return qparams;
}else{
qparts = parts[1].split('&');
for(i in qparts){
qpart = qparts[i].split('=');
qparams[decodeURIComponent(qpart[0])] =
decodeURIComponent(qpart[1] || '');
}
}
return qparams;
};
I wanted to pick up specific links within a DOM element on a page, send those users to a redirect page on a timer and then pass them onto the original clicked URL. This is how I did it using regular javascript incorporating one of the methods above.
Page with links: Head
function replaceLinks() {
var content = document.getElementById('mainContent');
var nodes = content.getElementsByTagName('a');
for (var i = 0; i < document.getElementsByTagName('a').length; i++) {
{
href = nodes[i].href;
if (href.indexOf("thisurl.com") != -1) {
nodes[i].href="http://www.thisurl.com/redirect.aspx" + "?url=" + nodes[i];
nodes[i].target="_blank";
}
}
}
}
Body
<body onload="replaceLinks()">
Redirect page
Head
function getQueryVariable(variable) {
var query = window.location.search.substring(1);
var vars = query.split('&');
for (var i = 0; i < vars.length; i++) {
var pair = vars[i].split('=');
if (decodeURIComponent(pair[0]) == variable) {
return decodeURIComponent(pair[1]);
}
}
console.log('Query variable %s not found', variable);
}
function delayer(){
window.location = getQueryVariable('url')
}
Body
<body onload="setTimeout('delayer()', 1000)">

Categories