Creating variable with constructor - javascript

I was looking around and saw this page where they were using String and Array constructors while creating their variables.
How does this differ from not using them?
Example:
var str = "string"; // How I'd normally do it.
var str = new String("string"); // How they did it.
var arr = ["Array", "Item"]; // How I'd normally do it.
var arr = new Array("Array", "Item"); // How they did it.
How exactly do these two differ?

var str = "string"; // typeof string
This is represented as block of memory, use it if you don't want to call a member on it
var str = new String("string"); // typeof object
This is a boxed object, which is slightly more resource consuming, but if you call i.e.
"Hello".length;
The JS parser must first create the boxed object from the string memory and then call the method, which is even slower.
The arrays syntax are always boxed objects in JS: [] is just syntax shorthand for new Array() AFAIK. Um, almost: see the zzzzBov's comment below.

Related

Javascript array index

Sorry for asking a noob question but if I have an array:
MyArray["2cd"]="blah1";
MyArray["3cx"]="blah3";
MyArray["8cz"]="blah2";
And a string myStr="2cd";
And then I use MyArray[myStr] to get the value of blah, how can I get the number I am accessing in the object/array or 0 in this case?
If I may read between the lines, it sounds like you're thinking that the code you posted:
MyArray["2cd"] = "blah1";
MyArray["3cx"] = "blah3";
MyArray["8cz"] = "blah2";
will automatically become the equivalent of:
MyArray[0] = MyArray["2cd"] = "blah1";
MyArray[1] = MyArray["3cx"] = "blah3";
MyArray[2] = MyArray["8cz"] = "blah2";
and therefore you can get the string "blah1" either of these two ways:
var foo = MyArray[0]; // sets foo to "blah1"
var bar = MyArray["2cd"] // also sets bar to "blah1"
But that's not how JavaScript works.
You certainly can set things up so you can use my MyArray[0] and MyArray["2cd"] to fetch the same value, but you have to do it explicitly as in my example.
One thing you didn't mention is how you declared MyArray itself. Is it an Array or an Object? That is, before the code you posted, did you create MyArray with:
var MyArray = {}; // or equivalently, var Array = new Object;
or:
var MyArray = []; // or equivalently, var Array = new Array;
The first example creates an Object, the second an Array.
What is a bit confusing is that JavaScript has both of these two types, which in many cases you can use somewhat interchangeably. But it's customary to use an Object when you are using arbitrary (generally but not necessarily non-numeric) keys into the object, as in your example. Conversely, it's customary to use an Array when you are primarily using strictly numeric indexes.
In fact, JavaScript's Array type inherits from the Object type. An Array is simply an Object with some additional behavior:
An Array has additional methods such as .push() which appends an item to the array.
An Array has a .length property which is automatically updated when you add elements with .push() or a direct array[123] assignment, or when you remove elements with .pop() or other methods.
What JavaScript doesn't have, as Fabrício pointed out, is an "associative array" that behaves like what you might find in some other languages. It has Objects and it has Arrays (which inherit from Objects), and you have to deal with each of those on their own terms.

Pointer behavior between objects

I would like to understand well something i observe more and more.
In some circonstances, different instances from a same model change their attributes the same way (if i have 2 UserModel A and B, if i change A, B will be affected the same way).
I observed some practical cases:
When i send an instance of a model to a view constructor, they are linked, if i change the model in my view, the outside one will be affected the same way. I guess sometime we just send a pointer and not a copy of the instance to the view.
More specific with some code;
A = new UserModel();
B = new UserModel();
var Data = A.get('info'); //where info = {some: "thing"};
Data.some = 'other';
B.set('info', Data); //A.get('info') == B.get('info')
Because i got the object info and not only the attributes separately (i tested it and there is no repercution between the values this way).
So my question is, are we always using pointers with objects in javascript ? Is it specific to backbone ? I would like to understand what is behind this behavior.
Thanks.
Objects and Arrays are passed or assigned as references in javascript, not copies. If you want a copy of an object or an array, you have to explicity make a copy.
Simpler types such as numbers, boolean are copied when assigned or passed.
Strings are a bit of special case. They are passed as references, but since strings are immutable (can't be changed), you can't really use a string reference for anything because any attempt to modify the string creates a new string.
A couple examples:
// arrays assigned by reference
var a = [1,2,3];
var b = a;
a[0] = 0;
alert(b[0]); // alerts 0 because b and a are the same array
// objects assigned by reference
var c = {greeting: "hello"};
var d = c;
c.greeting = "bye";
alert(d.greeting); // alerts "bye" because c and d are the same object
// numbers assigned as copies
var e = 3.414;
var f = e;
e = 999;
alert(f); // alerts 3.414 because f is its own copy of the original number
// make a copy of an array
var g = [1,2,3];
var h = g.slice(0); // h is now a copy
h[0] = 9;
alert(g); // shows [1,2,3]
alert(h); // shows [9,2,3]
The same is true for passing arguments to a function or returning values from a function. Unless an explicit copy is created, arrays and objects are passed or returned by reference.
A shallow copy of an array can be made with the .slice() method.
var arr1 = [1,2,3];
var arr2 = arr1.slice(0); // make independent copy of first array
A shallow copy of an object can be made by copying each property from the original object to a new object.
Deep copies involve testing the type of each item being copied and recursing on the object if it is an object or array so nested objects and arrays are copied too.

array.splice not working

i want to remove array element, but giving error while using splice,
i m using following function
with myAra as global var,
but in console ,it is giving me an error, TypeError: myAra.splice is not a function
var myAra = Array();
function charCounts(e,textAreaId)
{
myAra = $("#"+textAreaId).val();
var countNewLines = stringOccurrences(myAra, "\n");
if(myAra.length>75)
{
for (var i = 75; i >myAra.length; i++)
{
myAra.splice(i, 1);
}
$("#"+textAreaId).val(myAra);
}
}
myAra is a String, not an Array, at the point when you call splice. It has the value of the element.
This is a nice example of why globals are EVIL, sure you declared the variable an array (badly): var myAra = Array() (I'll explain at the end what's bad about this), but later on:
myAra = $("#"+textAreaId).val();//returns a string, variable is now a string, not an array
You've reassigned a string to the array, so the variable now references a string constant, and cannot be used as an Array (not safely, in a X-browser way at least).
Array() is bad, why? Well, for starters, you're calling a constructor, but you're not using the new keyword. With arrays that's not a big problem (it'll return a new instance all the same), but when you start defining your own objects, and constructors, you'll find yourself up to your neck in globals. Also, suppose you wanted an array and initialize the first element to an int: var anArray = new Array(2);, you won't get an array that looks like this: anArray[0] === 2, you'll get anArray === [undefined,undefined]. Compare that to var anArray('2') --> ['2']. Given the fact that JS is loosely typed, and you'll often use variables when initializing an array, it's hard to tell weather or not you're passing a numeric string or a number to the constructor. The best way to initialize arrays is by using the literal notation: [2,3,4], as an added bonus, it requires less typing, too
Replace the following:
if(myAra.length>75)
{
for (var i = 75; i >myAra.length; i++)
{
myAra.splice(i, 1);
}
$("#"+textAreaId).val(myAra);
}
with the below code:
if(myAra.length>75)
{
var moreNum = myAra.length - 75;
myAra.splice(75, moreNum ); // remove all items after the 75th item
$("#"+textAreaId).val(myAra);
}
Note - splice change the actual array, that's why the loop was failing. Hope it helps.
You are assigning a string value directly to the myAra so it will convert it to string ..typeOf myAra. Use myAra[0]=$("#"+textAreaId).val();...since javascript is a loosely coupled language
In the first line you used var myAra = Array(), but the jQuery val() function returns a string.
EDIT: Also I think the prefered way of creating arrays in JS is the var myArray = [], and not using the var myArray = new Array() expression.

Is this Javascript object literal key restriction strictly due to parsing?

Please refer to the code below, when I "comment in" either of the commented out lines, it causes the error (in IE) of "':' expected". So then is my conclusion correct, that this inability to provide a reference to an object value, as an object key in a string literal; is this strictly an interpreter/parsing issue? Is this a candidate for an awful (or at least "bad") "part" of Javascript, in contrast to Crockford's "good parts"?
<script>
var keys = {'ONE': 'one'};
//causes error:
//var obj1 = {keys.ONE: 'value1'};
//var obj1 = {keys['ONE']: 'value1'};
//works
var obj1 = {};
obj1[keys.ONE] = 'value1';
//also works
var key_one = keys.ONE;
var obj2 = {key_one: 'value1'};
</script>
The limitation of the literal object syntax is that the names has to be literal. As the names can be specified as an identifer as well as a string, it's not possible to use a variable instead.
This will create an object with a property n, not a property answer:
var n = 'answer';
var o = { n: 42 };
You cannot use variables as keys when defining object with {}
Therefore they are being interpreted as string names and can consist only of characters avaliable for variable names
the
objectname[anythingThatReturnsValue]='value1'; is the way to go.
ALSO
You can generate a string and parse it
var s='{"'+keys.ONE+'": "value1"}';
var obj=JSON.parse(s);
//or
s='var obj2='+s;
eval(s);
Both above methods are bad practices for creating objects in JavaScript and I don't recommend them.
Think about it: if it were to work the way you want it would totally introduce a language ambiguity.
var obj = {something:"red"}
var obj = {"something":"red"}
The two statements are equivalent in JavaScript, because bareword keys are "autoquoted." So if something means the literal string "something", how it could also refer to the variable "something". It can't. So if you want to use variables they have to go in square bracket notation instead of key : value notation.
You can try:
var obj = {};
var val = 'foo';
obj[val] = 'bar';
obj.foo >>> 'bar';

Arrays in JavaScript

While reading a book about JavaScript I stumbled across an example:
var names = new Array("Paul","Catherine","Steve");
var ages = new Array(31,29,34);
var concatArray;
concatArray = names.concat(ages);
My question is, why doesn't the variable concatArray need to be define as a new Array() in order to store the concatenated data for both arrays name and ages , but when I try to treat the concatArray as an array by adding another line of code "document.write(concatArray[0])", it works just like an array and shows me the data stored in the first element. I just wonder why I'm not declaring the concatArray as a new array, yet it still works as one.
You are declaring concatArray as a new array but the declaration is implicit. The concat function returns a new array which contains concatenated copies of the original two arrays. The type of concatArray is inferred from the return type of the concat function.
Variable don’t have a specific data type in Javascript like in other languages. You can assign a variable every value you want.
That means var concatArray; declares the variable but the value is undefined:
var concatArray;
alert(typeof concatArray === "undefined");
Only when assigning the return value of names.concat(ages) (an array) to concatArray it get’s that type:
var names = new Array("Paul","Catherine","Steve");
var ages = new Array(31,29,34);
var concatArray;
alert(typeof concatArray === "undefined");
concatArray = names.concat(ages);
alert(concatArray.constructor === Array);
Javascript doesn't care what the contents of the var are when it is declared; that is why you can declare var concatArray without needing to specify it as an array. Once you assign it a value and a type (as the result of the concat() function) javascript treats the var as an array.
Simply put, w3schools says it pretty concisely:
The concat() method is used to join two or more arrays.
This method does not change the existing arrays, it only returns a copy of the joined arrays.
w3schools
Looks like Andrew and Matthew beat me to it anyway.
Because Javascript is dynamically typed. A variable doesn't have a specifuc type, and an array is an object that you can assign to any variable.
When you declare a variable without assigning it a value, it just exists with an undefined value:
var answer;
// now the variable exists, but it doesn't have a value
answer = 42;
// now the variable has the numerical value 42
answer = "hello";
// now the numerical value has been replaced with the string value "hello"
answer = [];
// now the variable contains an empty array
answer[0] = 1337;
// now the variable contains an array that contains an item with the value 1337
answer = -1
// now the array is gone and the variable contains the value -1
I would make an answer slightly different of Andrew's one.
JavaScript variables are not strongly typed. You can put a string, then a number, then an object in the same variable. When you use the variable, the interpreter checks its current type is suitable for the usage you try to make. If you write:
var a = 45;
alert(a[0]);
a = [ 5 ];
alert(a[0]);
you will get successively undefined then 5.

Categories