In reviewing the following article: https://html-online.com/articles/get-url-parameters-javascript/
They show the following example:
var number = getUrlVars()["x"];
Can someone please explain the syntax where the parameter is outside of the function?
If it was written as the following would you have asked the question?
var myVariables = getUrlVars()
var number = myVariables["x"];
The function call getUrlVars is returning an object {x: 123} and the developer is reading a property of the object right away. Instead of writing it in two steps, they wrote it as one.
Doing it that way is great if you are only reading one property from the object, but if you want to read more than one, it would be better to write it out by storing getUrlVars() into a variable and than using that to read the properties. That way you are not executing getUrlVars more than once.
var num = getUrlVars()["x"]; This expression is used when the called function is returning a object and you want to get only desired value out of the returned object. Here ["x"] is not a parameter it used as object property accessor.
function getUrlVars(){
return{
'x': 'This is x',
'y': 'This is y'
}
}
var num = getUrlVars()["x"];
console.log(num)
var number = getUrlVars('["x"]'); In this expression you're passing [x] as parameter to a function.
Related
I have a function:
function hello(param){ console.log('param is '+param); }
And two calls. First:
hello(123)
Second:
var a=123; hello(a);
Is there any possible way to tell, from within the hello function, whether param was passed as a var or as a literal value?
NOTICE: I am not trying to solve a problem by this. There are many workarounds of course, I merely wanted to create a nice looking logging function. And also wanted to learn the boundaries of JavaScript. I had this idea, because in JavaScript we have strange and unexpected features, like the ability to obtain function parameter names by calling: function.toString and parsing the text that is returned.
No, primitives like numbers are passed by value in Javascript. The value is copied over for the function, and has no ties to the original.
Edit: How about using an object wrapper to achieve something like this? I'm not sure what you are trying to do exactly.
You could define an array containing objects that you want to keep track of, and check if its in there:
var registry = [] // empty registry
function declareThing(thing){
var arg = { value: thing } // wrap parameter in an object
registry.push(arg) // register object
return arg; //return obj
}
function isRegistered(thingObj){
return (registry.indexOf(thingObj) > -1)
}
var a = declareThing(123);
hello(a);
function hello(param){
console.log(isRegistered(param));
}
One thing I don't understand is why sometimes you put variables inside of ( ) and sometimes you put them before a keyword with a period. Is there a rule on this? Does it have a name? How do I know and how do I remember? This is causing some confusion for me. Example below:
var myNumber1 = 1234;
var myNumber2 = myNumber.toString(); //variable is before keyword with a period
var myNumber1 = "1234";
var myNumber2 = Number(myNumber); //variable is after keyword and inside of parenthesis
Those are two different synatxes.
The first one calls a method of myNumber - a function (toString()) that is run on the object.
The second one calls a function (Number) with myNumber as a parameter - that goes in the parentheses.
To learn more about function and method calls, i recommend reading some tutorials. ;) Here's one by MDN. It's somewhat advanced, but pretty good.
Case 1
Number(myNumber);
In short this is just a function, and you are passing in a variable. from the way you asked your question it seems like you understand how this works.
Case 2
myNumber.toString();
In case 2 you are not actually passing in a variable, you are calling a method of that object.
Dot notation is one of the two ways you can call methods.
[ object ] . [method of that object]
In javascript almost everything is an object, because of this (like it or not) you inherit the methods of Number.prototype in all your numbers.
You can think of .toString() as a method of all number "objects".
If you are interested in learning more about this or how to add more methods your self give THIS a read.
myNumber.toString();
converts myNumber to a "string of characters". Like "abcd". Is not a number.
As every string is between "",
"1234" is a string, not a number.
So
var myNumber2 = Number(myNumber);
converts that string to the number 1234 . "Number" is a function to convert that what you passed trought parenthesis into a number.
Lets consider this example:-
function X(){
var Y = function(arg1,arg2){
document.write(arguments.length);
document.write(arg2);
};
Y(arguments);
}
x(1,2,3,4,5);
/*Outputs 1 and undefined respectively.
Because here i am actually passing an array like-object to Y. */
By using apply here i am getting the desired results.
function X(){
var Y = function(arg1,arg2){
document.write(arguments.length);
document.write(arg2);
};
Y.apply(this,arguments);
}
x(1,2,3,4,5) //outputs 5 and 2
I want to create an apply like method that takes an Array of argument and invoke that function by passing arguments as seperate parameter values.
Like:
var arr=[1,2,3,4];
Y.apply_like_method(arr);
//and returns like Y(1,2,3,4)
Given this code:
var arr=[1,2,3,4];
Y.apply_like_method(arr);
//and returns like Y(1,2,3,4)
To make that work:
Function.prototype.apply_like_method = function(args) {
return this.apply(this, args);
}
Disclaimer: For illustration purposes only.
In other words, there's no way around .apply().
Just for shits and giggles using eval.
function myApply(fun, ar){
var i, r = [];
for(i=0; i<ar.length; ++i)
r[i] = 'ar['+i+']';
eval('fun('+r.join(',')+');');
}
You want to use the call method instead. See the MDN. What you are describing though is a hybrid of the call method and apply method; you want the ability to supply parameters individually, but to supply them to the function as an array. That, to my knowledge, doesn't exist currently and it would be easier to use apply/call as it was originally intended, or use a javascript object to pass the params into the function.
In ColdFusion, if you want to reference
<cfargument name="x">
then you say:
arguments.x
In JavaScript, if you have a function:
var myFunction = function(x) {
then, is there a way to explicitly reference the arguments scope like maybe:
arguments[0].x
or something so that you're scoping everything.
There is no way to achieve the same functionality by using the arguments variable, as it holds no information on parameter names. To circumvent this, you could switch from using multiple parameters to one compound parameter object that holds actual parameter values in its members.
<script>
function abc(params) {
var x = params.x;
var y = params["y"];
}
abc( { x: 10, y: "hello" });
</script>
This way however you lose some of the readability of the code at the function signature, plus you must provide param names on the calling side.
You can reference the arguments pseudo-variable, but the arguments are indexed by number, not by name. It's a good idea to avoid messing with arguments directly; a common idiom is to convert it to a real array:
var args = Array.slice.call(arguments, 0);
I'm afraid not. You can explicitly use x or arguments[0] but nothing more. Unless, as pointed out from others, you pass an object.
Sorry if this has been answered already, but I could not find an appropriate answer on here.
I've started writing my javascript code in a modular style lately and I have a question regarding how module variable scope works.
The following code gives me a conflicting answer.
I have a module named Base that declares two strings and an array. It also has a function called fetchData that uses the jQuery getJSON shortcut to set these variables with server data. Unfortunately when I ask for Base's string1 or string2, I get undefined. I understand that this is probably due to the fact that I have it set their values two functions deep (inside the AJAX callback and inside fetchData) and the scope limits it from seeing Base.string1 and Base.string2.
However, when I look at Base.array1 from outside the module, it's set to the appropriate data I pulled from the server, even though it's set from the same scope as the strings.
Here's the code:
namespace.Base = (function(){
var string1, string2, array1 = [];
function fetchData(){
$.getJSON('backendScript.php', function(data){
string1 = data.string1;
string2 = data.string2;
arrayCount = data.arr.length;
for(var i = 0; i<arrayCount; i++){
array1[i] = data.arr[i];
}
})
}
return{
fetchData: fetchData,
string1: string1,
string2: string2,
array1: array1
}
})();
If I change
string1 = data.string1;
to
namespace.Base.string1 = data.string1;
it works like I want.
So my question is, why is array1 set correctly when it's set from the same scope as the strings?
Also, what is the remedy for setting module-level variables from within the module's functions without having to give a global path (e.g. namespace.Base.string1)?
The problem is that you actually have two different references, the variable string1 within the closure of the anonymous function that you invoke to create namespace.Base, and namespace.Base.string1, which is on the object returned from that anonymous function. Your assignment of the variable string1 to the object property string1 is a one-time set, not a live reference. Further modification of the variable string1 will not affect the object property. Here's what you want:
namespace.Base = (function() {
var my = {
string1: null,
string2: null,
array1: [],
fetchData: function () {
$.getJSON('backendScript.php', function(data){
my.string1 = data.string1;
my.string2 = data.string2;
var arrayCount = data.arr.length;
for (var i = 0; i < arrayCount; i++){
my.array1[i] = data.arr[i];
}
});
}
};
return my;
})();
Now the local, but public, members of namespace.Base are in the object my. You can create private variables using var within the anonymous function, or create more public properties by adding them to my.
I would be a good idea to get familiar with closures and how they work:
How do JavaScript closures work?
Your "scope" issue is not actually a scope issue. The issue is that arrays are pointers to their data, strings are not.
namespace.Base is set to the results (returned value) of the anonymous function. -- It is set to be an object containing a function ref (fetchData), two empty strings and an array.
If you later call the fetchData function, then it will change the contents of array1.
But it will also create two new strings (from data.string1 and data.string2). The old values of string1 and string2 (which are namespace.Base.string1 and namespace.Base.string2) are not changed. So they are left as empty strings (not what you want).
Example of this. Try it in Firebug--
s1 = "Hi";
s2 = s1; // s2 => "Hi"
s1 = "Bye"
alert(s2); // *** s2 is still "Hi", it was not changed!
// But arrays are different:
a1 = ["Hi"];
a2 = a1;
a1[0] = "Bye";
alert(a2[0]); // a2[0] is now "Bye"
Added: Asynch Timing error
Also, note that your code is wrong as written since you're not giving the caller any way to know when the Ajax call has completed:
namespace.Base.fetchData(); // starts the Ajax call via getJSON method
var a = namespace.Base.array1; // ERROR!! The value of namespace.Base.array1 is
// indeterminate since you don't know if the
// the Ajax request has completed yet or not!
You appear to be trying to convert the asynchronous Ajax call (which invokes a callback function once the answer has been received from the remote server) into a synchronous call which will not return until the results have been received.
This is a really bad idea. (If you want to know more, ask another question in SO.)