I have an object:
var object = {
string1 : 'hello',
string2 : 'world'
}
And If I want to call the string2 property of the object is it slower to call it multiple times like:
...object.string2...
...object.string2...
or it would be faster to create a reference for it what holds the value of the parameter like:
var string2 = object.string2;
...string2...
...string2...
The reason why I think that the second one could be faster, because I think right now that the first one always scans the whole object to grab the value.
You are correct - the second one is faster, because JavaScript does not need to perform the lookup of string2 each time. The change is even more profound in something like this:
(do stuff with foo.bar.baz.qux)
versus
var property = foo.bar.baz.qux;
(do stuff with property)
In that example, foo must be scanned for bar. Then bar must be scanned for baz. Et cetera.
In your example the gain will be minimal unless you are doing a lot of work with string2, but you are correct in saying that it is faster.
In you case this does not matter . But for big object with big prototype chunks - you right.
But you may win in speed but loose in functionality because var a = obje.property coping by value - not by reference and if obj.property will be change dynamically that variable a will have old value of obj.property
Related
I'm a new learner of JavaScript, and when I get to learn the way of using a function. It sometime confuses me on why we should declare a new variable and add the variable to the action we want to execute. Let's look into the code.
function reverse(word){
Array.from(word);
let reverseWord='';
for(i = word.length-1; i >= 0; i--) {
reverseWord += word[i];
}
return reverseWord;
}
I'm sure you know this one of the way of reversing string in javascript, my question is:
Why do we need to declare a new variable within the function, when should we declare it?
Why can't I just type console.log(word[i]);?
What does it mean by wordLength+=word[i];?
Why should we return the new variable(wordLength), instead of the function(reverse) after the loop?
Why do we need to declare a new variable within the function...
Because you need a place to store the reversed word as you build it. (Note: wordLength isn't a good name for that variable. It doesn't contain the word's length. It contains the characters of the reversed word.)
...when should we declare it?
Any time before you first need it.
Why can't I just type console.log(word[i]);?
Because the goal of the exercise is to build a string containing the reversed word, not just to output it. (And because console.log writes a new line each time you call it.)
What does it mean by wordLength+=word[i];?
That adds the character in word[i] to the end of wordLength. For instance, if the word is "start", wordLength starts out with "", then gets "t" added to it to make it "t", then gets "r" added to it to make "tr", and so on.
(+= is a shorthand way to write wordLength = wordLength + word[i];. There are several of these compound assignment operators, most of them for math: -=, *=, etc.)
Side note: The Array.from call in your code isn't doing anything useful. It's creating an array, but then throwing that array away because nothing uses the return value. The rest of the code is using the string you receive in word.
Why do we need to declare a new variable within the function, when should we declare it?
Vars is a place to store data. If your algorithm requires keeping some data to use it later you need vars. Also well named variables is a good way to create easy-to-understand code
Why can't I just type console.log(word[i]);?
You can, but it will do nothing useful. Your goal is to build a string and return it. Usage of your function will be something like
const word = getSomeText()
const reversedText = reverse(word)
doSomeStuff(reversedText) // whatever, send it online, or render it on screen some fancy way, not in the console.
So you need to return actual string, not to solve a puzzle and show the answer whatever way you like
Why should we return the new variable(wordLength), instead of the function(reverse) after the loop?
Because it contains reversed word and you function supposed to return it. there is rare complicated occasions when a function returning itself is useful, but it has nothing in common with your task
Why do we need to declare a new variable within the function, when should we declare it?
Variable is required to store the data value that can be changed later on. In your case wordLength variable is required to store the reverse string.
It's best to declare variables when you first use them to ensure that they are always initialized to some valid value.
Why can't I just type console.log(word[i])
console.log() is used just to print the output but will not use if you want to return something and as per your statement it will just print the word[i] not a whole reverse string.
What does it mean by wordLength+=word[i]
It means you are concatenating the each iteration word[i] into a wordLength variable.
wordLength+=word[i] is a shorthand for wordLength = wordLength + word[i]. If the left hand side of the + operator is a string, JavaScript will coerce the right hand side to a string.
Why should we return the new variable(wordLength), instead of the function(reverse) after the loop ?
Because this is what you expected from the function. It returns the reversed string and function should return it.
I have a function that would use other variables, depending on what has been passed.
Like this = ActionBar(slot) slot contains "one".
and I would like to create a call inside that like object.slot.name but it should convert it before hand to make the command look like object.one.name. Is there a way to do this in javascript/jquery?
I remember vaguely that some other language does this as {slot} or something like that.
Sorry if this question was already asked, I've checked google and stackoverflow too, but didn't find an answer.
Also I'd like to know what's the proper programming term for this kind of variable passing?
Edited it cause of misunderstandings. I'm looking into OOP js, so object is an object, one is an object, and name is an attribute, but when passing I'm passing "one" as a string to the function.
Tried eval, it doesn't work while dotted with an object.
Source code:
function disableActionButton(slot){
$("#"+slot).attr("disabled","disabled")
gcd = player.slot.gcd*1000
cd = setInterval(function(){
gcd = gcd - 10
$("#"+slot).val(gcd+"ms").css("color","red");
},10)
setTimeout(function(){
window.clearInterval(cd)
$("#"+slot).removeAttr("disabled").css("color","black").val(player.slot.name);
}, player.slot.gcd*1000)
}
It's really unclear what your current structure is (much clearer now you've posted code, see "update" below), but fundamentally the way to do this sort of thing in JavaScript is to have a container object. (If you don't already have one, introduce one.) Then slot can refer to a property of that object, like this:
var container = {
one: "This is one",
two: "This is two"
};
// ...
function foo(slot) {
console.log(container[slot]);
}
// ...
foo("one"); // ends up logging "This is one"
foo("two"); // ends up logging "This is two"
This works because the container object has properties, which in JavaScript can be referred to in two different ways:
Using dot notation and a literal name, e.g. container.one, or
Using bracketed notation and a name in a string, e.g. container["one"].
They're exactly equivalent except where the property name comes from. And of course, in the second case, the property name needn't be a literal string, it can be the result of any expression, including a variable reference (e.g., you can get the name from slot).
This works with all object properties, including properties that refer to functions. I mention this only because you mentioned functions in your question, so if you need to, you can do this:
function foo(slot) {
container[slot]();
}
...which calls the function on container that the property with the name held by the slot argument. So if slot is "one", it does container.one().
Update:
Your source directly echos the container example above, just apply the above to it:
function disableActionButton(slot){
$("#"+slot).attr("disabled","disabled")
// ---------v----v---- here
gcd = player[slot].gcd*1000
cd = setInterval(function(){
gcd = gcd - 10
$("#"+slot).val(gcd+"ms").css("color","red");
},10)
setTimeout(function(){
window.clearInterval(cd)
// ------------------------------------------------------------ and here--v----v
$("#"+slot).removeAttr("disabled").css("color","black").val(player[slot].name);
// ------v----v------- and here
}, player[slot].gcd*1000)
}
Or, rather than looking up the slot data each time, grab it once and reuse it:
function disableActionButton(slot){
// Grab it once...
var slotdata = player[slot];
$("#"+slot).attr("disabled","disabled")
// ---vvvvvvvvv--- then use it
gcd = slotdata.gcd*1000
cd = setInterval(function(){
gcd = gcd - 10
$("#"+slot).val(gcd+"ms").css("color","red");
},10)
setTimeout(function(){
window.clearInterval(cd)
$("#"+slot).removeAttr("disabled").css("color","black").val(slotdata.name);
}, slotdata.gcd*1000)
}
There's no special name for this. You're passing a property name into a function, and the function is looking up the property on the player object using that name. In some other languages this might be called "reflection" but the term doesn't really apply to dynamic languages like JavaScript.
I want to calculate inside the grid,multiple of 2 textBox values, key-press or keyup event.
can u provide me some javascript for this. I use the following code it does not work for me
javascript
var a = document.getElementById(txtlabchrgsNooflab);
var b = document.getElementById(txtlabchrgsTotalCost);
txtlabchrgsTotalCost=a*b;
Firstly - if you want to multiply two things together, they're going to have to be numbers.
At the moment your a and b variables are simply the HTML elements you've identified, and you can't multiply those together. (Though pay attention to Carl's comment; you may need to quote txtlabchrgsNooflab if this is meant to be a literal string and not a variable name.)
So you need to get the value of these elements, as a numeric datatype. Getting the value should be as simple as calling .value() for text inputs; however, this returns a string. This may get automatically coerced to a numeric type as required, but I would be happier (and think it's clearer) to call parseFloat on it definitively.
Once you have your two floats, you can merrily multiply them. So your code should look something like the following:
var elemA = document.getElementById(txtlabchrgsNooflab);
var elemB = document.getElementById(txtlabchrgsTotalCost);
var a = parseFloat(elemA.value());
var b = parseFloat(elemB.value());
txtlabchrgsTotalCost = a * b;
OK, so using this above code results in:
error: Unable to get value of the property 'value': object is null or undefined
What can we infer from this error message? Well, that the runtime wasn't able to compute value because the thing it was being called on was null or undefined.
If you look at the code, it's clear which variable(s) might be null or undefined - and you should be able to inspect your HTML to see why this is, and make the required corrections.
can someone tell me if this is valid javascript? I know you couldnt do this sort of thing in c# but js is a much looser language..
var arrayToUse = "arr" + sender.value;
for (i = 0; i <= arrayToUse.length; i++) {
// something..
}
specifically - the dynamic generation of the array name..
update..
so i have an array called arrMyArray which is initialised on document ready. sender.value = "MyArray" - but could be something else eg MyArray2
I want to dyanimcally iterate over the array that is indicated by the sender.value value.
Yes, this is entirely valid.
arrayToUse will be a string (regardless of the value of sender.value — it will be converted to a string), and i will iterate from 0 to the string's length).
One minor note: it should be for (**var** i = 0; …), otherwise i will be treated as a global variable, which will almost certainly end badly if you've got multiple loops running at the same time.
Edit: you want to get the array based on the name? In that case you've got to look it up in whatever context the array is defined.
If it's a global array, use window.
For example:
var arrayName = "arr" + sender.value;
var array = window[arrayName];
…
To get a variable name defined by a variable, you need to use eval, like so:
var arrayToUse = eval("arr" + sender.value);
However, you must be very careful with this, because controlling sender.value would allow someone to hijack your entire application this way. You should usually try to find another solution.
If the variable is defined at the globally, you can look it up as window["arr" + sender.value] instead. This is still not ideal, but is less of a security risk.
What you need to do is access a variable with the name "arr" + sender.value. Accessing the variable whose contents are "arr + sender.value doesn't do what you want -- that's just a string.
To access the variable with that name, you can look it up as a global (globals are members of the window object in the browser):
window["arr" + sender.value]
This is safer and faster than using eval() because it doesn't run code in a JavaScript execution context to evaluate the string -- it just looks up a variable in the window object with that name.
I'm writing a Javascript function that would manipulate an array written on-the-fly and sent as a parameter.
The function is written as follows:
function returnJourney(animation,clean){
var properties = {};
// loads of other inane stuff
for(i in animation[0]) properties[animation[0][i]] = animation[0].i;
// heaps more inane stuff
}
The animation in question is a set of parameters for a jQuery animation. Typically it takes the format of ({key:value,key:value},speedAsInteger,modifierAsString).
So to kick off initial debugging I call it with:
returnJouney(({'foo':'bar'},3000),1);
And straight off the bat things are way off. As far as I see it this would have returnJourney acknowledge clean === 1, and animation being an array with an object as its first child and the number 3000 as its second.
Firebug tells me animation evaluates as the number 3000. What am I doing wrong?
properties[animation[0][i]] = animation[0].i;
should be
properties[animation[0][i]] = animation[0][i];
.i is the property literally called 'i'. As that (probably) doesn't exist, you'll be assigning undefined to each property.
returnJouney(({'foo':'bar'},3000),1);
also makes little sense — do you mean an array?:
returnJourney([{'foo':'bar'},3000],1);
(there is no ‘tuple’ type in JavaScript.)
Also, use var i in rather than the (typo) in in. Forgetting var gives you an accidental global, with potentially annoying-to-debug side-effects.
There's no tuple type in JavaScript. All you have is either object {} or array []. Both of them can understand any mixture of types. So you can either pass your animation parameter as array ([{'foo':'bar'},3000]), which looks like exactly what you wanted.
Or, as it usually done in JavaScript, use object instead:
returnJourney({props: {foo: "bar"}, speed: 3000}, 1);
function returnJourney(animation, clean) {
var props = animation.props;
var speed = animation.speed;
}
Note that object notation let you ignore things you don't want to pass and makes it very clear what value means what.
As for why your animation resolves as 3000, it is really simple, this is how , operator works. It returns the last thing in braces. So (10, 20, 30) would evaluate to 30, so will (f(1000), "hello", 30). Only last value matters, others just ignored (but run anyway, so any side effects will be there).
It's treating ({'foo':'bar'},3000) as an expression using the comma operator, which returns the right operand as its result. Perhaps you meant [{'foo':'bar'},3000].