I am new to JavaScript. From some tutorials I know in javascript there are two ways to declare the array.
One is like this:
var test = new Array("apple","pine");
or
test = new Array("apple","pine");
Two are like this,
var test=["apple","pine"];
but when i use this way to declare it:
test=Array("apple","pine");
It is still ok. why?
In Javascript, you may (and should) declare a variable using the var keyword, but it's not required. So any variable can be declared like this:
var a = 'abc';
or
a = 'abc';
But the first one (with var) should always be used when you're creating a new variable. Otherwise, you might be overwriting an already existing variable with the same name. An array is also a variable, so it too can be declared either with or without the var keyword. Then there are two ways to declare an array, and both do exactly the same thing:
var a = ['a', 'b', 'c'];
does the same as:
var a = new Array('a', 'b', 'c');
and the new keyword, in this case, is not required - as per the javascript specification. But it's usually used to indicate that you're creating a new instance of an object.
First, you really should stick to the simple "[ ... ]" notation to create and initialize your arrays. Thus:
var test = ["apple", "pine"];
You should also be careful to use var for all your local variables. (Actually I'll go out on a limb and say that it's just bad practice not to use var for all declarations.)
Now, using the Array constructor without the new prefix works because that's just how the Array constructor is defined. In other words, if it's not invoked with new, it returns you an array anyway. However, you really shouldn't worry about it because in most circumstances there's no reason to use the Array constructor at all.
var is used to declare a variable's scope.
x = 'hello';
function y() {
x = 'goodbye';
}
function z() {
var x = 'how are you';
}
y()
alert(x); // outputs 'goodbye';
z();
alert(x); // outpus 'hello';
Basically var declares a variable to be local scope. It has no real effect if you use it at the top level of a script, but within a function it'll make the variable "local".
Because new Array(...) and Array(...) do the same thing (= create a new array). That's just how it's defined in the spec.
See here: http://es5.github.com/#x15.4.1
When Array is called as a function
rather than as a constructor, it
creates and initialises a new Array
object. Thus the function call
Array(…) is equivalent to the object
creation expression new Array(…) with
the same arguments.
Therefore, these 3 lines are equivalent:
arr = ['apple', 'pine'];
arr = new Array('apple', 'pine');
arr = Array('apple', 'pine');
Related
I was reading a book called Effective JavaScript: 68 Specific Ways to Harness the Power of JavaScript, Point 4 Prefer Primitives to Object Wrappers and came across this sentence.
Getting and setting properties on primitives implicitly creates object
wrappers
Does this create an object wrapper?
"hello".someProperty = 17;
EDIT
If the above statement create an object then please explain this behaviour.
var test = "foo";
test.bar = "new prop";
test.bar //this prints undefined.
"hello".someProperty = 17;
The above statement does create an object wrapper, but it is disposed of as soon as its task is done.
var hello = 'Hello';
hello.someProperty = 17;
console.log(hello.someProperty);
This explains why trying to assign properties to a primitive doesn't work, but also doesn't throw an error. Assigning the property succeeds, but the property is set on a wrapper object which is immediately destroyed. So when you go to look up the property later, there is nothing there anymore.
Internally, this of primitive type is object.
String.prototype.thisType = function () {
return typeof this;
};
var hello = "hello";
console.log(typeof hello);
console.log(hello.thisType());
Read more Here
Yes, it creates an intermediate object, which is discarded after use. So the statement
"hello".someProperty = 17;
will internally be executed like this:
var temp = new String("hello"); // or any other variable name
temp.someProperty = 17;
So, now temp (or whatever named variable is created by JavaScript) will not be accessible because it is created and discarded immediately.
you have to create String Object by new Keyword.
var str = new String("My String");
//Here str is looks like
//String {"My String"}
str .xyz=5
str
//now String {"My String", xyz: 5}
I'm learning javascript right now, seems like beautiful functional language to me, it is wonderful move from PHP, I should have done this earlier. Although, I cannot figure this one out:
var v1 = (/[abc]/).test;
v1('a');
says test method called on incompatible undefined, I'm trying to store the test method of that regex into variable and invoke it later.
but it works with my own functions:
function foo(){
return 'I\'m foo';
}
var f = foo;
f(); // returns I'm foo
It should work on methods too, since functions are just methods of parent object anyway, right?
Ultimately, the reason I'm trying this is to be able to write something like this:
var a = ['a', 'b', 'c'];
a.every( (/[abc]/).test );
to check each array member against that regex.
Why doesn't this work? Is it limitation in passing built-in functions around? Or am I just doing something wrong?
PS: If you grind your teeth now and muffling something about bad practices, screw good practices, I'm just playing. But I'd like to hear about them too.
it works with my own functions
You are not using this inside the function. Consider this example:
var obj = {
foo: 42,
bar: function() {
alert(this.foo);
}
};
var f = obj.bar;
f(); // will alert `undefined`, not `42`
It should work on methods too, since functions are just methods of parent object anyway, right?
"Method" is just a colloquial term for a function assigned to a property on object. And functions are standalone values. There is no connection to the object a function is assigned to. How would this even be possible, since a function could be assigned to multiple objects?
Why doesn't this work?
What this refers to inside a function is determined at run time. So if you assign the function to a variable and call it later
var v1 = (/[abc]/).test;
v1('a');
this inside the function will refer to window, not to the regular expression object.
What you can do is use .bind [MDN] to explicitly bind this to a specific value:
var a = ['a', 'b', 'c'];
var pattern = /[abc]/;
a.every(pattern.test.bind(pattern));
Note though that since .bind returns a function, the only advantage over using a function expression is that it is a tad shorter to write.
Is it limitation in passing built-in functions around?
No, the problem exists for every method/function because that's how functions work. The nice thing about built-in functions though is that they often explicitly tell you when this is referring to the wrong type of object (by throwing an error).
Learn more about this.
If you store just a method, it does not carry with it a reference to your object - it just stores a reference to the .test method, but no particular object. Remember, a method is "just" a property on an object and storing a reference to a method doesn't bind it to that object, it just stores a reference to the method.
To invoke that method on a particular object, you have to call it with that object.
You can make your own function that calls the method on the desired object like this:
var v1 = function(x) {
return /[abc]/.test(x);
}
Then, when you do this:
v1('a');
It will execute the equivalent of this in your function:
/[abc]/.test('a');
But, it isn't entirely clear why you're doing that as you could also just define the regex and call .test() on it several times:
var myRegex = /[abc]/;
console.log(myRegex.test('a'));
console.log(myRegex.test('b'));
console.log(myRegex.test('z'));
The test function expects this to be a regular expression. The expression /[abc]/.test gives an unbound function (it does not remember that it belongs to /[abc]/). When you invoke it like you do, this will be undefined and the function will fail.
You can use bind to make the function remember the object it belongs to:
var v1 = /[abc]/.test.bind(/[abc]/);
or
var v1 = RegExp.prototype.test.bind(/[abc]/);
Your reference to the method has lost its knowledge of what it was a method of.
This isn't so much good practice as just the way JS works.
You can do:
var v1 = /[abc]/;
v1.test('a');
If you must encapsulate the test method, then you could do:
var v1 = function(str){
return /[abc]/.test(str);
};
v1('a');
I don't know if this is an acceptable solution, but you can do:
v1 = function(exp) { return (/[abc]/).test(exp); }
v1('a');
I see this syntax everywhere:
var mod = (function(){
var pvtvar;
var pvtfunc = function(){};
//return an object literal
return {
pubvar : 'whatever',
pubfunc : function(){}
};
}());
I recently came across this syntax:
//first create empty object
var mod = {};
(function(mod){
var pvtvar;
var pvtfunc = function(){};
//modify the mod object argument
mod.pubvar = 'whatever';
mod.pubfunc = function(){};
}(mod)); //pass object to IIFE
I know that they both work, and I think I understand completely why, I just want to make sure I'm not missing anything...Given identical members you end up with identical objects, it's just that in the second example mod references an empty object within the global scope for a fraction of a second, while in the first example mod only ever references the complete object once its value is returned by the IIFE.
So, am I correct in thinking that the only difference is the (very small) amount of time that the second object lives as an empty object?
And, my follow up question: do you use the second syntax, and why?
You're right. In your example, the first syntax is cleaner and more readable.
You use the second syntax when you want to pass along something more than an empty object into the module and get an augmented object in return.
I have a function with lots of variables and very big arrays being defined; this makes the function very large and hard to work with. How can I define the variables/arrays in another file and use them in this function?
Example:
DoStuff.js:
function genList(){
var listData = [
//lots of inner arrays and data
]
var dataItem = "value";//50 of these
//do stuff with the data
}
What I'm trying to do:
ExternalData.js:
var listData = [
//lots of inner arrays and data
]
var dataItem = "value";//50 of these
DoStuff.js:
function genList(){
//call variables/arrays from ExternalData.js
//do stuff
}
Note:
JQuery is applicable here, but I'd rather not call any other libraries for something so small.
I would define all the variables in an object for example:
var obj = {
array_one: ['x', 'y'],
some_value: 'z'
}
This method has the advantage of make a kind of namespace for all the variables, saving you from overriding values.
And then use that object into my code using some kind of include method.
One simple method could be to add the script before the one you are writing like this:
<script type="text/javascript" scr="file_with_object.js"></script>
Other more sophisticated but only advisable if you are going to repeat this kind of behavior
is to use a Library or a framework to make includes more concise, require.js is a good example
EDIT: In the previous example I used the object with var considering that the code was written on the global scope, I think it would be better to use window.obj = {} to ensure the variable is global. And, just for the record, any variable you define like this window.somevariable is going to be a global variable. Once you define a global variable you could use it anywhere in your code (after the definition takes place). The namespace is the right way to go though.
EDIT 2: I think this post is more about scope than includes. When you declare a variable this way: var some_variable; you are saying that you want to bind that variable to the current scope. So if you do that inside a function, that variable "lives" inside that function:
var some_var = 10;
function(){
var some_var = 5;
console.log(some_var) // 5
}
console.log(some_var) // 10
But if you declare the variable without the var on both cases you are making that varaible global the first time and overriding its value on the second:
some_var = 10;
function(){
some_var = 5;
console.log(some_var) // 5
}
console.log(some_var) // 5
And alway you declare a varaible without the var, that variable is accessible trough window.variablename, because you are not binding the variable to any particular scope, so the binding is made to the window objecy, which is the global scope "namespace".
Why should I declare
var foo = {}
instead of
var foo = new Object();
in JavaScript if they are similar?
Does the same applies to
foo[0].bar = new Function(){ "return hello"};
as in in
foo[0].bar = function(){return "hello"};
?
Is it an efficiency matter? Does it make difference?
I remember reading the following from w3fools.com:
personObj=new Object();
This is a bad and unnecessary use of the new keyword. They should be
using and advocating the object literal syntax ({}) for creating new
objects.
It doesn't say why, only that we should.
Actually
var foo = {}
and
var foo = new Object();
does the same thing (both expressions create an empty Object) but it's better to use shorter version (object literal), it takes less space time to write and another thing that using object literal you can create and assign values/properties to an Object as follows
person = {
property1 : "Hello"
};
but using new Object() you need to create it first and then assign values/properties as follows
person = new Object();
person.property1 = "Hello";
In your second example (function vs new function) there is a difference because new Function is slower and you can take a look at this test here.
No there isn't any efficiency increase or decrease, its just shorthand like using ? : for if/else..
I always use shorthand {} but if you are going to have a beginner reading your code you may want to use new Object().
The only times it might matter is if your writing a program that generates such javascript dynamically ... or your writing for a certain teacher in college who seems to have a certain standard that doesn't quite make sense at times.
The new Function() constructor doesn't really work that way.
It's called like:
var myFunc = new Function("param1", "param2", "message", "/*function-body-as-a-string*/ console.log(message); return param1 + \"=\" + param2;");
ie: really dumb, error-prone, stupid-slow (uses eval) and a security-hole.
Don't use it.