Does the original string always stay unmodified? - javascript

var name = 'naGeoExit';
var name = name.substring(2,5);
console.log(name); //output: Geo
Is the first name variable and the second name variable are two different variables being allocated in the different parts of the memory or value of the original variable is being changed ?

If they have the same name and are in the same scope then they're the same variable.

At line 1, there is a string in memory containing "naGeoExit". There is a variable in scope, called name that points to it.
At the second line, there is a copy of the subsequence of the string in memory. The variable name now points to that. There is no reference to the original string object, so it is garbage collected at some point.
Using the var keyword means "create a variable in the current scope (rather than the global scope)". The current scope is a closure, for example a function definition (although it could also be the global scope if you are not in a function).
It is not a syntax error to use var twice, but its purpose is to create a new variable and you should only use it once per scope. Second time round will have no effect.

Yes, the original string is unmodified. In your example, though, it's immediately available for garbage collection.
Here's an example that shows that the string is unmodified more clearly:
var n1 = 'naGeoExit';
var n2 = n1.substring(2,5);
console.log(n1); //output: naGeoExit
console.log(n2); //output: Geo
In your original code, you had only one variable called name, and you assigned the result of the substring operation to it, which is why the original string was immediately available for garbage collection. Re-declaring the same variable in the same scope has no effect. So the code:
var name = "foo";
var name = "bar";
...is exactly the same as:
var name = "foo";
name = "bar";
...and is, for that matter, exactly the same as:
var name;
name = "foo";
name = "bar";

Related

dynamic object definition

This is a serious question, It has been nagging me for a while. In JavaScript you can declare a variable which has no type. It's type is often dynamic, depends on further value assigned to it.
e.g
var text;
typeof(text); //undefined
text = 'someText';
typeof(text); //string
So as we know that Javascript can dynamically change variable's type why these assignments are invalid then?
e.g
var someObj;
someObj.a = 'hello world';
console.log(someObj) //TypeError
var someTable;
someTable[0] = 'hello world';
console.log(someTable[0]) //TypeError
where this problem can be fixed just by adding definition to variable declaration:
var someObj = {};
var someTable = [];
I'd expect a good explanation of this problem. Thanks for answers.
There's a big difference between declaration and initialisation of variables.
When you declare a variable without initializing it with a value, its type will be undefined, so when you will try to call it or access it, it will give undefined, because simply there were no value defined for the variable.
That's why it should be initialized:
var someObj = {};
var someTable = [];
So you can treat it as a string, an object or an array according its initialized value.
Documentation:
Please take a look at variables MDN Reference for further reading, where it says:
A var statement declares variables that are scoped to the running execution context’s VariableEnvironment. Var variables are created when their containing Lexical Environment is instantiated and are initialized to undefined when created. [...] A variable defined by a VariableDeclaration with an Initializer is assigned the value of its Initializer’s AssignmentExpression when the VariableDeclaration is executed, not when the variable is created.
You're getting confused about where the error is thrown. In your first example:
var someObj;
someObj.a = 'hello world'; // the error is thrown here
That error is thrown because someObj is undefined (not undeclared). So, you can't access the property a on undefined.
The same explanation applies for your second example:
var someTable;
someTable[0] = 'hello world'; // the error is thrown here
You're trying to access index 0 of undefined.
The reason that defining them as {} and [], respectively, fixes your issue, is that you are then accessing property a of {} and index 0 of [].
1) Data types in Javascript are not dynamic, they are mutable. This means that depending on kind of operation you are applying to them they can change from being something into another thing (e.g. a number can become a string doing something like this: 4 + 'a').
2) The "error" is a consequence of having a variable not initialized. In Javascript when you are doing this:var something = 'a'
you are doing two operations, a declaration, and an assignment. If you don't do the assignment and you try to access to a property of the object you have declared it will throw an error. In your case, you are declaring a variable but not initializing it to the "compiler" can't access the "a" property or the position 1 because it is of type undefined.

How JavaScript assigns `name` attribute of function?

In JavaScript, when I define function like this
function aaa(){}
I can later access the name by name attribute:
aaa.name
which will return
"aaa"
However, when I define function via var, it technically should be anonymous function without name attribute:
var aaa=function(){}
But instead it assumes that aaa is function name and assigns it to name attribute:
aaa.name
will also return
"aaa"
How JavaScript decides what should be the name, especially considering the fact that assignments could use more complicated scenarios:
var aaa=bbb=function(){}
or
var aaa=arr[0]=function(){}
?
Javascript declares the name variable of the function by taking the left-hand side argument that is equal to the function, which is 'aaa' in all basic cases. In the first complex definition, you declared state above Javascript will take the variable ab and assign it to a function making the name 'ab'. In the final example, you provided it sets the function equal to a pointer in memory, which is not a defined variable, this sets the name property to an empty string because arr[0] is not a variable name but a pointer to memory.
Here is a JSFiddle displaying this.
Something like this:
Inferred function names
Variables and methods can infer the name of an anonymous function from
its syntactic position (new in ECMAScript 2015).
var f = function() {};
var object = {
someMethod: function() {}
};
console.log(f.name); // "f"
console.log(object.someMethod.name); // "someMethod"
Read the entire blog. It will clear all your queries.

Why is my constant not pointing to new value

If i am not wrong, the pointer that the variable name is using cannot change in memory, but the thing the variable points to might change.
let name = "google";
const foo = name;
console.log(foo); //prints google
name = "yahoo";
console.log(foo); //prints google again instead of yahoo
Should it not print yahoo, as the variable name's value has been changed.. Can anyone explain me this.
Another example, where its changes...
const foo = [];
foo.push("test");
console.log(foo); // outputs ["test"]
I am getting confused here, can anyone explain me this.
Your first example uses an immutable string and the second uses a mutable object.
JS strings are immutable after being declared or created, so foo is not a reference to name's value, it points to the string. You're not changing the strings, you're pointing to a different one.
The array variable points to the object and continues pointing to the same object after it's been mutated. You're still pointing to the same object, however, since const is not deep.
This also highlights a common misunderstanding with JS' const, which functions more like Java's final than C++'s const. You are declaring a variable as const, not an instance of the object, so it only prevents you from reassigning to the variable, it does not prevent you from mutating the underlying object.
From MDN:
The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, just that the variable identifier cannot be reassigned.
This means that you can change the value assigned to a const, say by changing array or object, but cannot assign a new value to the const variable. E.g.:
Valid:
const a = [];
a.push(5);
console.log(a);
const b = {};
b['foo'] = 'bar';
console.log(b);
Invalid: This will throw error
const a = [];
a = [5];
console.log(a);
const b = {};
b = {'foo': 'bar'};
console.log(b);

Variable vs Parameter Scope and Assignment Values

I have been watching a video series by Douglas Crockford. I am a little confused on the relationship of assigning variables as a parameter of assigning variables as a global variable, let me demonstrate.
var bob = 22; //global scope
function funky(parameter){
parameter = null; //sets the var passed in to null
bob = 44; //sets the bob
}
var hello = [];
funky(hello); // hello still has the value of an empty array even after the function is invoked.
bob; // value is 44
So 'var bob' is assigned 44 when funky() is invoked. This bob holds the new value outside the scope of the function.
var hello is passed as a parameter, while inside funky, it has the value null, outside when hello is invoked in global space, it holds the value of an empty array.
Is this just something I have to memorize? If a defined variable in global scope is passed as a parameter, it will only hold it's new assigned value within the scope of the function? Am I missing something at a broader scope with either how a parameter is passed and assigned in a function?
Here is a repl.it of the code with console.log outputs while inside and outside the function/global scope.
http://repl.it/NgN
Because this line
parameter = null;
Only sets the value of the function's parameter, not the value of the variable that was passed in. However, bob inside the function is interpretted as a reference to the global variable, so it does modify the external value.
Note, however, that objects are references, so if you wrote it like this:
function funky(parameter){
parameter.hello = null;
}
Then calling funky does directly modify the object that the parameter references.
var x = { hello: [] };
funky(x); // x => { hello: null }
Is this just something I have to memorize?
Yes, understanding how parameters are passed is pretty important.
If a defined variable in global scope is passed as a parameter, it will only hold it's new assigned value within the scope of the function?
Parameters only hold their values within the scope of the function. Global variables are, well, global, so if they are modified inside the function, they keep that value outside the function.
Also, be aware of hiding—if a parameter has the same name as a global variable, the parameter hides the variable within the scope of that function.
ok, so the following example will confuse you even more.
var a = {'a': 'A'};
function foo(param){param.a = 'B';}
foo(a);
// now print a
{'a': 'B'}
Here's an important concept:
Primitives are passed by value, Objects are passed by "copy of a reference".
As for more information, you can check this answer:
Does Javascript pass by reference?
Regarding this:
var hello is passed as a parameter, while inside funky, it has the value null, outside when hello is invoked in global space, it holds the value of an empty array.
Do not think of parameter as an alias for hello. They are distinct variables. They are free to point to different things. Assigning a value -- null in this case -- to parameter has no effect on hello. After that line, the global variable hello still points to an empty array. Only parameter points to null.
Furthermore, funky(hello) passes the value of hello to the funky function. Consider the following:
var arr = [];
function addElements(arr) {
arr.push(5);
arr.push(77);
}
The global arr is still empty after addElements executes. The arr inside the function is distinct from the arr in the global scope. (I should note that the contents of each arr may point to the same objects, but that's a separate issue.)
(Note also that some languages do allow the sort of aliasing you seem to expect, but that's not how parameters are passed in JavaScript.)
JavaScript assumes that if you assign a value to a variable it is in the global scope—unless that variable is declared with a var. Like for example, this:
var bob = 22; //global scope
function funky(parameter){
parameter = null; //sets the var passed in to null
var bob = 44; //sets the bob
}
var hello = [];
funky(hello); // hello still has the value of an empty array even after the function is invoked.
bob; // value is 22
Since the function's bob variable is declared with a var, it is owned by the local scope of the function and has no impact on the bob declared outside the function's scope.
Regarding how objects differ from primitives when passed into functions, check out Jonathan Snook's article http://snook.ca/archives/javascript/javascript_pass and the helpful comment from #p.s.w.g.

difference between these functions

What is the difference between these 3 functions? What use is the new operator in the second function? Why should one use the first function over the third function?
First
var person = function(name){
this.name = alert(name);
};
var k = new person('kkkk');
var j = new person('jjjj');
Second
var person2 = function(name){
person2.name = alert(name);
};
var k2 = new person2('kkkk2');
var j2 = new person2('jjjj2');
Third
var person3 = function(name){
person3.name = alert(name);
};
var k3 = person3('kkkk3');
var j3 = person3('jjjj3');
The alert actually makes it pretty hard to examine the effects, so in my explanations, I'll assume alert(name) is actually name. (alert returns undefined, not its input)
The first one makes a function that you could use like a class. You then used it with new and made two objects, k and j. The this made it so you could access the names such that k.name === 'kkkk' and j.name === 'jjjj'.
The second one is similar to the first one, but k2.name and j2.name are undefined. You can access person2.name, but that's only equal to the name of the last time you instantiated it; thus, person2.name === 'jjjj2'.
The third one is similar to the second one, but doesn't abuse new. k3 and j3 are undefined, and you will get an error if you try to access k3.name and j3.name. Again, you will be able to access the value last passed to person3 with person3.name.
Your second and third function will not assign anything to person2.name and person3.name. So technically only your first function is valid that's why it should be used.
There is a very important concept in javascript called context. A context can be thought of as an object. this keyword refers to the context in which a function is executing.
You can create a new property in current context with the help of this. For example:
var person = function(name) {
this.name = name; // this can be accessed externally, just like public properties
var _name = name; // this can be accessed only within the function, just like a private property
__name = name; // if a property is not properly initialized with a 'var' or 'this', it becomes part of 'window' object, hence you can access it from anywhere using 'window.__name'
}
You can create a new context using new keyword:
var k = new person2('kkkk2'); // this will create a new context, create a property name in it and assign it value passed to function.
var j = new person('jjjj'); // this will create another context
You can always access different contexts and their properties:
alert(k.name); // this will show 'kkkk2'
alert(j.name); // this will show 'jjjj'
The first one declares a function, person(), that is (presumably) intended to be used as an object constructor - kind of the closest JavaScript comes to having classes. That means if you call it with new person() JS will create a new instance of a person object, and within the constructor this refers to that new instance so this.name creates a property on the instance. Unfortunately the value you've assigned to that property is undefined since the alert() function returns undefined. If you said this.name = name it would store the value that was in the function argument - that would be a more normal usage. Your k and j objects both have a name property with this syntax.
The second version, again with the new person2() syntax, will be creating objects that are instances of person2, however saying person2.name creates a property on the function itself. So that property is not accessible directly from the instances k2 and j2, and every time you call person2() the person2.name property gets overwritten. There is no problem with having properties on functions like this in a general sense, but in this case it doesn't really make sense unless you really need to remember the name associated with the most recent invocation.
The third version, without using the new keyword, will simply assign the return value from person3() to the k3 and j3 variables, but since you don't explicitly return anything they'll end up as undefined. And the person3.name will work exactly the same way as for person2.
EDIT: Except, note that name has special meaning in the context of functions, so for the second and third options it won't behave quite the same as if you created a property with some other name that doesn't have special meaning, e.g., myName.

Categories