IE8 bug in for-in JavaScript statement? - javascript

I think I've found a bug in IE's (IE8) handling for the for-in javascript statement. After several hours of boiling this down to a small example, it looks like IE specifically skips any property called "toString" in a for-in loop - regardless of whether it is in a prototype or is an "Own Property" of the object.
I've placed my test code here:
function countProps(obj) {
var c = 0;
for (var prop in obj) {
c++;
}
return c;
}
var obj = {
toString: function() {
return "hello";
}
};
function test() {
var o = "";
var d = document.getElementById('output');
o += "<br/>obj.hasOwnProperty('toString') == " + obj.hasOwnProperty('toString');
o += "<br/>countProps(obj) = " + countProps(obj);
o += "<br/>obj.toString() = " + obj.toString();
d.innerHTML = o;
}
This should produce:
obj.hasOwnProperty('toString') == true
countProps(obj) = 1
obj.toString() = hello
but in IE, I'm getting:
obj.hasOwnProperty('toString') == true
countProps(obj) = 0
obj.toString() = hello
This special casing of any property called 'toString' is wrecking havoc with my code that tries to copy methods into a Function.prototype - my custom toString function is always skipped.
Does anyone know a work-around? Is this some sort of quirks-mode only behavior - or just a BUG?

Yes, it is a bug. See this answer.
Quoting CMS:
Another well known JScript bug is the "DontEnum Bug", if an object in its scope chain contains a property that is not enumerable (has the { DontEnum } attribute), if the property is shadowed on other object, it will stay as non-enumerable, for example:
var dontEnumBug = {toString:'foo'}.propertyIsEnumerable('toString');
It will evaluate to false on IE, this causes problems when using the for-in statement, because the properties will not be visited.

This is a bug in IE, and also applies to properties named valueOf.
You can work around it like this:
if(obj.toString !== Object.prototype.toString || obj.hasOwnProperty("toString"))
//Handle it
if(obj.valueOf !== Object.prototype.valueOf || obj.hasOwnProperty("valueOf"))
//Handle it

Related

Javascript: Check if something can have properties _added_ to it

EDIT: Made clearer that the need is to determine if I can add properties to a value, not if a value can have its own properties.
Is there a way to check if is possible to add properties to a value?
For example, if I have this code:
function test( value ) {
// return true if it is possible to add properties to value
}
Other than actually adding a property value to test, is there a reliable way to deduce if value is something that properties can be added to?
For example, I know an object can have properties and undefined can't, but I'm not keen on creating a list of known things that might not suffice in the future. Is something like instanceof object sufficient?
The list of values that do not have properties is quite short: undefined and null. Testing for those should be straightforward (value == null).
Note that all other primitives can have properties (through boxing), but as the boxed object gets lost immeadiately there is no sense in adding properties to them:
1..test = 1;
"test".test = 1;
Infinity.test = 1;
NaN.test = 1;
true.test = 1;
Symbol().test = 1;
1n.test = 1;
To check for non-primitives, typeof value === "object" can be used, but as null is also an object (a very special one, actually it counts as a primitive but typeof lies about that), you have to explicitly check for value !== null.
While you can usually add properties to objects, they can be frozen, then adding properties is useless, the same applies to Proxies.
const obj = {};
Object.freeze(obj);
obj.test = 1;
console.log(obj.test);
And as Proxies can't be detected, there is no way to find out wether a property can be added or not.
A simple idea (although it does not solve completely the case as per Jonas Wilms answer) may be:
function test(value) {
try {
if (value.p === undefined) {
value.p = 10;
if (value.p === undefined) {
return false;
}
delete value.p;
}
} catch(e) {
return false;
}
return true;
}
console.log('null: ' + test(null));
console.log('undefined: ' + test(undefined));
console.log('number: ' + test(10));
console.log('object: ' + test({a:10}));
var obj = { get p() { return false; }, set p(v) {} };
console.log('object with property name confict: ' + test(obj));
As pointed out by Jonas Wilms:
Bad usecase. You are just writing your next headache :)
I need to refactor my code so it doesn't need to jump through hoops.

Is ES5 shim still needed for Internet Explorer 11?

I am looking at the compat tables, and it seems like IE 11 supports all of ES5 except (under Miscellaneous) this feature: "Enumerable properties can be shadowed by non-enumerables". I don't understand what that means, despite the provided example.
Can I get away from using ES5 shim since IE11 supports most of it?
Yes it is safe to drop ES5 shim in that scenario. I make websites available IE11 and common issues are custom variables, ES6 obviously and CSS calc() related bugs. Managed to make my own custom variable emulator using a map and used a similar approach CSS calc().
The length property they use here, actually comes from the prototype of the Function constructor, Function.prototype.length and returns the amount of arguments expected by the function. As you can see on the page I linked, the property is not enumerable, so for ... in should not enumerate the given property. The following snippet demonstrates that the property is not enumerable and therefore result will remain true.
var result = true;
for(var propertyName in Function) {
if(propertyName == 'length') {
result = false;
}
}
var isLengthEnumerable = Function.prototype.propertyIsEnumerable('length');
console.log('Function.prototype.length is enumerable: ' + isLengthEnumerable);
console.log('Result: ' + result);
The snippet above gives us the following output:
Function.prototype.length is enumerable: false
Result: true
But in javascript, everything is an object and inherits properties from Object.prototype through its prototype chain, including Function. So what happens when we assign the same property length to Object.prototype?
var result1 = true;
var result2 = true;
Object.prototype.length = 42;
Object.prototype.otherProperty = 42;
for (var propertyName in Function) {
if (propertyName == 'length') {
result1 = false;
}
if (propertyName == 'otherProperty') {
result2 = false;
}
}
var isLengthEnumerable = Object.prototype.propertyIsEnumerable('length');
var isOtherPropertyEnumerable = Object.prototype.propertyIsEnumerable('otherProperty');
console.log('Object.prototype.length is enumerable: ' + isLengthEnumerable);
console.log('Object.prototype.otherProperty is enumerable: ' + isOtherPropertyEnumerable);
console.log('Result1: ' + result1);
console.log('Result2: ' + result2);
The above snippet gives us the following results:
Object.prototype.length is enumerable: true
Object.prototype.otherProperty is enumerable: true
Result1: true
Result2: false
As the Object.prototype.length property we just assigned is enumerable, you would expect that result1 would now be false. But because Function already has a length property (although not enumerable), the length property inherited from Object.prototype is not enumerated. The property has been shadowed.
This is what doesn't happen in IE11, there Object.prototype.length will be enumerated anyways and result1 will become false as well.

Check if an array item is set in JS

I've got an array
var assoc_pagine = new Array();
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
I tried
if (assoc_pagine[var] != "undefined") {
but it doesn't seem to work
I'm using jquery, I don't know if it can help
Thanks
Use the in keyword to test if a attribute is defined in a object
if (assoc_var in assoc_pagine)
OR
if ("home" in assoc_pagine)
There are quite a few issues here.
Firstly, is var supposed to a variable has the value "home", "work" or "about"? Or did you mean to inspect actual property called "var"?
If var is supposed to be a variable that has a string value, please note that var is a reserved word in JavaScript and you will need to use another name, such as assoc_var.
var assoc_var = "home";
assoc_pagine[assoc_var] // equals 0 in your example
If you meant to inspect the property called "var", then you simple need to put it inside of quotes.
assoc_pagine["var"]
Then, undefined is not the same as "undefined". You will need typeof to get the string representation of the objects type.
This is a breakdown of all the steps.
var assoc_var = "home";
var value = assoc_pagine[assoc_var]; // 0
var typeofValue = typeof value; // "number"
So to fix your problem
if (typeof assoc_pagine[assoc_var] != "undefined")
update: As other answers have indicated, using a array is not the best sollution for this problem. Consider using a Object instead.
var assoc_pagine = new Object();
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
var assoc_pagine = new Array();
assoc_pagine["home"]=0;
Don't use an Array for this. Arrays are for numerically-indexed lists. Just use a plain Object ({}).
What you are thinking of with the 'undefined' string is probably this:
if (typeof assoc_pagine[key]!=='undefined')
This is (more or less) the same as saying
if (assoc_pagine[key]!==undefined)
However, either way this is a bit ugly. You're dereferencing a key that may not exist (which would be an error in any more sensible language), and relying on JavaScript's weird hack of giving you the special undefined value for non-existent properties.
This also doesn't quite tell you if the property really wasn't there, or if it was there but explicitly set to the undefined value.
This is a more explicit, readable and IMO all-round better approach:
if (key in assoc_pagine)
var is a statement... so it's a reserved word... So just call it another way.
And that's a better way of doing it (=== is better than ==)
if(typeof array[name] !== 'undefined') {
alert("Has var");
} else {
alert("Doesn't have var");
}
This is not an Array.
Better declare it like this:
var assoc_pagine = {};
assoc_pagine["home"]=0;
assoc_pagine["about"]=1;
assoc_pagine["work"]=2;
or
var assoc_pagine = {
home:0,
about:1,
work:2
};
To check if an object contains some label you simply do something like this:
if('work' in assoc_pagine){
// do your thing
};
This worked for me
if (assoc_pagine[var] != undefined) {
instead this
if (assoc_pagine[var] != "undefined") {
TLDR; The best I can come up with is this: (Depending on your use case, there are a number of ways to optimize this function.)
function arrayIndexExists(array, index){
if ( typeof index !== 'number' && index === parseInt(index).toString()) {
index = parseInt(index);
} else {
return false;//to avoid checking typeof again
}
return typeof index === 'number' && index % 1===0 && index >= 0 && array.hasOwnKey(index);
}
The other answer's examples get close and will work for some (probably most) purposes, but are technically quite incorrect for reasons I explain below.
Javascript arrays only use 'numerical' keys. When you set an "associative key" on an array, you are actually setting a property on that array object, not an element of that array. For example, this means that the "associative key" will not be iterated over when using Array.forEach() and will not be included when calculating Array.length. (The exception for this is strings like '0' will resolve to an element of the array, but strings like ' 0' won't.)
Additionally, checking array element or object property that doesn't exist does evaluate as undefined, but that doesn't actually tell you that the array element or object property hasn't been set yet. For example, undefined is also the result you get by calling a function that doesn't terminate with a return statement. This could lead to some strange errors and difficulty debugging code.
This can be confusing, but can be explored very easily using your browser's javascript console. (I used chrome, each comment indicates the evaluated value of the line before it.);
var foo = new Array();
foo;
//[]
foo.length;
//0
foo['bar'] = 'bar';
//"bar"
foo;
//[]
foo.length;
//0
foo.bar;
//"bar"
This shows that associative keys are not used to access elements in the array, but for properties of the object.
foo[0] = 0;
//0
foo;
//[0]
foo.length;
//1
foo[2] = undefined
//undefined
typeof foo[2]
//"undefined"
foo.length
//3
This shows that checking typeof doesn't allow you to see if an element has been set.
var foo = new Array();
//undefined
foo;
//[]
foo[0] = 0;
//0
foo['0']
//0
foo[' 0']
//undefined
This shows the exception I mentioned above and why you can't just use parseInt();
If you want to use associative arrays, you are better off using simple objects as other answers have recommended.
if (assoc_pagine.indexOf('home') > -1) {
// we have home element in the assoc_pagine array
}
Mozilla indexOf
function isset(key){
ret = false;
array_example.forEach(function(entry) {
if( entry == key ){
ret = true;
}
});
return ret;
}
alert( isset("key_search") );
The most effective way:
if (array.indexOf(element) > -1) {
alert('Bingooo')
}
W3Schools

How do I enumerate the properties of a JavaScript object? [duplicate]

This question already has answers here:
How do I loop through or enumerate a JavaScript object?
(48 answers)
Closed 6 years ago.
How do I enumerate the properties of a JavaScript object?
I actually want to list all the defined variables and their values, but I've learned that defining a variable actually creates a property of the window object.
Simple enough:
for(var propertyName in myObject) {
// propertyName is what you want
// you can get the value like this: myObject[propertyName]
}
Now, you will not get private variables this way because they are not available.
EDIT: #bitwiseplatypus is correct that unless you use the hasOwnProperty() method, you will get properties that are inherited - however, I don't know why anyone familiar with object-oriented programming would expect anything less! Typically, someone that brings this up has been subjected to Douglas Crockford's warnings about this, which still confuse me a bit. Again, inheritance is a normal part of OO languages and is therefore part of JavaScript, notwithstanding it being prototypical.
Now, that said, hasOwnProperty() is useful for filtering, but we don't need to sound a warning as if there is something dangerous in getting inherited properties.
EDIT 2: #bitwiseplatypus brings up the situation that would occur should someone add properties/methods to your objects at a point in time later than when you originally wrote your objects (via its prototype) - while it is true that this might cause unexpected behavior, I personally don't see that as my problem entirely. Just a matter of opinion. Besides, what if I design things in such a way that I use prototypes during the construction of my objects and yet have code that iterates over the properties of the object and I want all inherited properties? I wouldn't use hasOwnProperty(). Then, let's say, someone adds new properties later. Is that my fault if things behave badly at that point? I don't think so. I think this is why jQuery, as an example, has specified ways of extending how it works (via jQuery.extend and jQuery.fn.extend).
Use a for..in loop to enumerate an object's properties, but be careful. The enumeration will return properties not just of the object being enumerated, but also from the prototypes of any parent objects.
var myObject = {foo: 'bar'};
for (var name in myObject) {
alert(name);
}
// results in a single alert of 'foo'
Object.prototype.baz = 'quux';
for (var name in myObject) {
alert(name);
}
// results in two alerts, one for 'foo' and one for 'baz'
To avoid including inherited properties in your enumeration, check hasOwnProperty():
for (var name in myObject) {
if (myObject.hasOwnProperty(name)) {
alert(name);
}
}
Edit: I disagree with JasonBunting's statement that we don't need to worry about enumerating inherited properties. There is danger in enumerating over inherited properties that you aren't expecting, because it can change the behavior of your code.
It doesn't matter whether this problem exists in other languages; the fact is it exists, and JavaScript is particularly vulnerable since modifications to an object's prototype affects child objects even if the modification takes place after instantiation.
This is why JavaScript provides hasOwnProperty(), and this is why you should use it in order to ensure that third party code (or any other code that might modify a prototype) doesn't break yours. Apart from adding a few extra bytes of code, there is no downside to using hasOwnProperty().
The standard way, which has already been proposed several times is:
for (var name in myObject) {
alert(name);
}
However Internet Explorer 6, 7 and 8 have a bug in the JavaScript interpreter, which has the effect that some keys are not enumerated. If you run this code:
var obj = { toString: 12};
for (var name in obj) {
alert(name);
}
If will alert "12" in all browsers except IE. IE will simply ignore this key. The affected key values are:
isPrototypeOf
hasOwnProperty
toLocaleString
toString
valueOf
To be really safe in IE you have to use something like:
for (var key in myObject) {
alert(key);
}
var shadowedKeys = [
"isPrototypeOf",
"hasOwnProperty",
"toLocaleString",
"toString",
"valueOf"
];
for (var i=0, a=shadowedKeys, l=a.length; i<l; i++) {
if map.hasOwnProperty(a[i])) {
alert(a[i]);
}
}
The good news is that EcmaScript 5 defines the Object.keys(myObject) function, which returns the keys of an object as array and some browsers (e.g. Safari 4) already implement it.
In modern browsers (ECMAScript 5) to get all enumerable properties you can do:
Object.keys(obj)
(Check the link to get a snippet for backward compatibility on older browsers)
Or to get also non-enumerable properties:
Object.getOwnPropertyNames(obj)
Check ECMAScript 5 compatibility table
Additional info:
What is a enumerable attribute?
I think an example of the case that has caught me by surprise is relevant:
var myObject = { name: "Cody", status: "Surprised" };
for (var propertyName in myObject) {
document.writeln( propertyName + " : " + myObject[propertyName] );
}
But to my surprise, the output is
name : Cody
status : Surprised
forEach : function (obj, callback) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") {
callback(prop);
}
}
}
Why? Another script on the page has extended the Object prototype:
Object.prototype.forEach = function (obj, callback) {
for ( prop in obj ) {
if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !== "function" ) {
callback( prop );
}
}
};
for (prop in obj) {
alert(prop + ' = ' + obj[prop]);
}
Simple JavaScript code:
for(var propertyName in myObject) {
// propertyName is what you want.
// You can get the value like this: myObject[propertyName]
}
jQuery:
jQuery.each(obj, function(key, value) {
// key is what you want.
// The value is in: value
});
Here's how to enumerate an object's properties:
var params = { name: 'myname', age: 'myage' }
for (var key in params) {
alert(key + "=" + params[key]);
}
I found it... for (property in object) { // do stuff } will list all the properties, and therefore all the globally declared variables on the window object..
You can use the for of loop.
If you want an array use:
Object.keys(object1)
Ref. Object.keys()
If you are using the Underscore.js library, you can use function keys:
_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
Python's dict has 'keys' method, and that is really useful. I think in JavaScript we can have something this:
function keys(){
var k = [];
for(var p in this) {
if(this.hasOwnProperty(p))
k.push(p);
}
return k;
}
Object.defineProperty(Object.prototype, "keys", { value : keys, enumerable:false });
EDIT: But the answer of #carlos-ruana works very well. I tested Object.keys(window), and the result is what I expected.
EDIT after 5 years: it is not good idea to extend Object, because it can conflict with other libraries that may want to use keys on their objects and it will lead unpredictable behavior on your project. #carlos-ruana answer is the correct way to get keys of an object.
If you're trying to enumerate the properties in order to write new code against the object, I would recommend using a debugger like Firebug to see them visually.
Another handy technique is to use Prototype's Object.toJSON() to serialize the object to JSON, which will show you both property names and values.
var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']};
Object.toJSON(data);
//-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}'
http://www.prototypejs.org/api/object/tojson
I'm still a beginner in JavaScript, but I wrote a small function to recursively print all the properties of an object and its children:
getDescription(object, tabs) {
var str = "{\n";
for (var x in object) {
str += Array(tabs + 2).join("\t") + x + ": ";
if (typeof object[x] === 'object' && object[x]) {
str += this.getDescription(object[x], tabs + 1);
} else {
str += object[x];
}
str += "\n";
}
str += Array(tabs + 1).join("\t") + "}";
return str;
}

Hidden Features of JavaScript? [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 11 years ago.
Locked. This question and its answers are locked because the question is off-topic but has historical significance. It is not currently accepting new answers or interactions.
What "Hidden Features" of JavaScript do you think every programmer should know?
After having seen the excellent quality of the answers to the following questions I thought it was time to ask it for JavaScript.
Hidden Features of HTML
Hidden Features of CSS
Hidden Features of PHP
Hidden Features of ASP.NET
Hidden Features of C#
Hidden Features of Java
Hidden Features of Python
Even though JavaScript is arguably the most important Client Side language right now (just ask Google) it's surprising how little most web developers appreciate how powerful it really is.
You don't need to define any parameters for a function. You can just use the function's arguments array-like object.
function sum() {
var retval = 0;
for (var i = 0, len = arguments.length; i < len; ++i) {
retval += arguments[i];
}
return retval;
}
sum(1, 2, 3) // returns 6
I could quote most of Douglas Crockford's excellent book
JavaScript: The Good Parts.
But I'll take just one for you, always use === and !== instead of == and !=
alert('' == '0'); //false
alert(0 == ''); // true
alert(0 =='0'); // true
== is not transitive. If you use === it would give false for
all of these statements as expected.
Functions are first class citizens in JavaScript:
var passFunAndApply = function (fn,x,y,z) { return fn(x,y,z); };
var sum = function(x,y,z) {
return x+y+z;
};
alert( passFunAndApply(sum,3,4,5) ); // 12
Functional programming techniques can be used to write elegant javascript.
Particularly, functions can be passed as parameters, e.g. Array.filter() accepts a callback:
[1, 2, -1].filter(function(element, index, array) { return element > 0 });
// -> [1,2]
You can also declare a "private" function that only exists within the scope of a specific function:
function PrintName() {
var privateFunction = function() { return "Steve"; };
return privateFunction();
}
You can use the in operator to check if a key exists in an object:
var x = 1;
var y = 3;
var list = {0:0, 1:0, 2:0};
x in list; //true
y in list; //false
1 in list; //true
y in {3:0, 4:0, 5:0}; //true
If you find the object literals too ugly you can combine it with the parameterless function tip:
function list()
{ var x = {};
for(var i=0; i < arguments.length; ++i) x[arguments[i]] = 0;
return x
}
5 in list(1,2,3,4,5) //true
Assigning default values to variables
You can use the logical or operator || in an assignment expression to provide a default value:
var a = b || c;
The a variable will get the value of c only if b is falsy (if is null, false, undefined, 0, empty string, or NaN), otherwise a will get the value of b.
This is often useful in functions, when you want to give a default value to an argument in case isn't supplied:
function example(arg1) {
arg1 || (arg1 = 'default value');
}
Example IE fallback in event handlers:
function onClick(e) {
e || (e = window.event);
}
The following language features have been with us for a long time, all JavaScript implementations support them, but they weren't part of the specification until ECMAScript 5th Edition:
The debugger statement
Described in: § 12.15 The debugger statement
This statement allows you to put breakpoints programmatically in your code just by:
// ...
debugger;
// ...
If a debugger is present or active, it will cause it to break immediately, right on that line.
Otherwise, if the debugger is not present or active this statement has no observable effect.
Multiline String literals
Described in: § 7.8.4 String Literals
var str = "This is a \
really, really \
long line!";
You have to be careful because the character next to the \ must be a line terminator, if you have a space after the \ for example, the code will look exactly the same, but it will raise a SyntaxError.
JavaScript does not have block scope (but it has closure so let's call it even?).
var x = 1;
{
var x = 2;
}
alert(x); // outputs 2
You can access object properties with [] instead of .
This allows you look up a property matching a variable.
obj = {a:"test"};
var propname = "a";
var b = obj[propname]; // "test"
You can also use this to get/set object properties whose name is not a legal identifier.
obj["class"] = "test"; // class is a reserved word; obj.class would be illegal.
obj["two words"] = "test2"; // using dot operator not possible with the space.
Some people don't know this and end up using eval() like this, which is a really bad idea:
var propname = "a";
var a = eval("obj." + propname);
This is harder to read, harder to find errors in (can't use jslint), slower to execute, and can lead to XSS exploits.
If you're Googling for a decent JavaScript reference on a given topic, include the "mdc" keyword in your query and your first results will be from the Mozilla Developer Center. I don't carry any offline references or books with me. I always use the "mdc" keyword trick to directly get to what I'm looking for. For example:
Google: javascript array sort mdc
(in most cases you may omit "javascript")
Update: Mozilla Developer Center has been renamed to Mozilla Developer Network. The "mdc" keyword trick still works, but soon enough we may have to start using "mdn" instead.
Maybe a little obvious to some...
Install Firebug and use console.log("hello"). So much better than using random alert();'s which I remember doing a lot a few years ago.
Private Methods
An object can have private methods.
function Person(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
// A private method only visible from within this constructor
function calcFullName() {
return firstName + " " + lastName;
}
// A public method available to everyone
this.sayHello = function () {
alert(calcFullName());
}
}
//Usage:
var person1 = new Person("Bob", "Loblaw");
person1.sayHello();
// This fails since the method is not visible from this scope
alert(person1.calcFullName());
Also mentioned in Crockford's "Javascript: The Good Parts":
parseInt() is dangerous. If you pass it a string without informing it of the proper base it may return unexpected numbers. For example parseInt('010') returns 8, not 10. Passing a base to parseInt makes it work correctly:
parseInt('010') // returns 8! (in FF3)
parseInt('010', 10); // returns 10 because we've informed it which base to work with.
Functions are objects and therefore can have properties.
fn = function(x) {
// ...
}
fn.foo = 1;
fn.next = function(y) {
//
}
I'd have to say self-executing functions.
(function() { alert("hi there");})();
Because Javascript doesn't have block scope, you can use a self-executing function if you want to define local variables:
(function() {
var myvar = 2;
alert(myvar);
})();
Here, myvar is does not interfere with or pollute the global scope, and disappears when the function terminates.
Know how many parameters are expected by a function
function add_nums(num1, num2, num3 ){
return num1 + num2 + num3;
}
add_nums.length // 3 is the number of parameters expected.
Know how many parameters are received by the function
function add_many_nums(){
return arguments.length;
}
add_many_nums(2,1,122,12,21,89); //returns 6
Here are some interesting things:
Comparing NaN with anything (even NaN) is always false, that includes ==, < and >.
NaN Stands for Not a Number but if you ask for the type it actually returns a number.
Array.sort can take a comparator function and is called by a quicksort-like driver (depends on implementation).
Regular expression "constants" can maintain state, like the last thing they matched.
Some versions of JavaScript allow you to access $0, $1, $2 members on a regex.
null is unlike anything else. It is neither an object, a boolean, a number, a string, nor undefined. It's a bit like an "alternate" undefined. (Note: typeof null == "object")
In the outermost context, this yields the otherwise unnameable [Global] object.
Declaring a variable with var, instead of just relying on automatic declaration of the variable gives the runtime a real chance of optimizing access to that variable
The with construct will destroy such optimzations
Variable names can contain Unicode characters.
JavaScript regular expressions are not actually regular. They are based on Perl's regexs, and it is possible to construct expressions with lookaheads that take a very, very long time to evaluate.
Blocks can be labeled and used as the targets of break. Loops can be labeled and used as the target of continue.
Arrays are not sparse. Setting the 1000th element of an otherwise empty array should fill it with undefined. (depends on implementation)
if (new Boolean(false)) {...} will execute the {...} block
Javascript's regular expression engine's are implementation specific: e.g. it is possible to write "non-portable" regular expressions.
[updated a little in response to good comments; please see comments]
I know I'm late to the party, but I just can't believe the + operator's usefulness hasn't been mentioned beyond "convert anything to a number". Maybe that's how well hidden a feature it is?
// Quick hex to dec conversion:
+"0xFF"; // -> 255
// Get a timestamp for now, the equivalent of `new Date().getTime()`:
+new Date();
// Safer parsing than parseFloat()/parseInt()
parseInt("1,000"); // -> 1, not 1000
+"1,000"; // -> NaN, much better for testing user input
parseInt("010"); // -> 8, because of the octal literal prefix
+"010"; // -> 10, `Number()` doesn't parse octal literals
// A use case for this would be rare, but still useful in cases
// for shortening something like if (someVar === null) someVar = 0;
+null; // -> 0;
// Boolean to integer
+true; // -> 1;
+false; // -> 0;
// Other useful tidbits:
+"1e10"; // -> 10000000000
+"1e-4"; // -> 0.0001
+"-12"; // -> -12
Of course, you can do all this using Number() instead, but the + operator is so much prettier!
You can also define a numeric return value for an object by overriding the prototype's valueOf() method. Any number conversion performed on that object will not result in NaN, but the return value of the valueOf() method:
var rnd = {
"valueOf": function () { return Math.floor(Math.random()*1000); }
};
+rnd; // -> 442;
+rnd; // -> 727;
+rnd; // -> 718;
"Extension methods in JavaScript" via the prototype property.
Array.prototype.contains = function(value) {
for (var i = 0; i < this.length; i++) {
if (this[i] == value) return true;
}
return false;
}
This will add a contains method to all Array objects. You can call this method using this syntax
var stringArray = ["foo", "bar", "foobar"];
stringArray.contains("foobar");
To properly remove a property from an object, you should delete the property instead of just setting it to undefined:
var obj = { prop1: 42, prop2: 43 };
obj.prop2 = undefined;
for (var key in obj) {
...
The property prop2 will still be part of the iteration. If you want to completely get rid of prop2, you should instead do:
delete obj.prop2;
The property prop2 will no longer will make an appearance when you're iterating through the properties.
with.
It's rarely used, and frankly, rarely useful... But, in limited circumstances, it does have its uses.
For instance: object literals are quite handy for quickly setting up properties on a new object. But what if you need to change half of the properties on an existing object?
var user =
{
fname: 'Rocket',
mname: 'Aloysus',
lname: 'Squirrel',
city: 'Fresno',
state: 'California'
};
// ...
with (user)
{
mname = 'J';
city = 'Frostbite Falls';
state = 'Minnesota';
}
Alan Storm points out that this can be somewhat dangerous: if the object used as context doesn't have one of the properties being assigned to, it will be resolved in the outer scope, possibly creating or overwriting a global variable. This is especially dangerous if you're used to writing code to work with objects where properties with default or empty values are left undefined:
var user =
{
fname: "John",
// mname definition skipped - no middle name
lname: "Doe"
};
with (user)
{
mname = "Q"; // creates / modifies global variable "mname"
}
Therefore, it is probably a good idea to avoid the use of the with statement for such assignment.
See also: Are there legitimate uses for JavaScript’s “with” statement?
Methods (or functions) can be called on object that are not of the type they were designed to work with. This is great to call native (fast) methods on custom objects.
var listNodes = document.getElementsByTagName('a');
listNodes.sort(function(a, b){ ... });
This code crashes because listNodes is not an Array
Array.prototype.sort.apply(listNodes, [function(a, b){ ... }]);
This code works because listNodes defines enough array-like properties (length, [] operator) to be used by sort().
Prototypal inheritance (popularized by Douglas Crockford) completely revolutionizes the way you think about loads of things in Javascript.
Object.beget = (function(Function){
return function(Object){
Function.prototype = Object;
return new Function;
}
})(function(){});
It's a killer! Pity how almost no one uses it.
It allows you to "beget" new instances of any object, extend them, while maintaining a (live) prototypical inheritance link to their other properties. Example:
var A = {
foo : 'greetings'
};
var B = Object.beget(A);
alert(B.foo); // 'greetings'
// changes and additionns to A are reflected in B
A.foo = 'hello';
alert(B.foo); // 'hello'
A.bar = 'world';
alert(B.bar); // 'world'
// ...but not the other way around
B.foo = 'wazzap';
alert(A.foo); // 'hello'
B.bar = 'universe';
alert(A.bar); // 'world'
Some would call this a matter of taste, but:
aWizz = wizz || "default";
// same as: if (wizz) { aWizz = wizz; } else { aWizz = "default"; }
The trinary operator can be chained to act like Scheme's (cond ...):
(cond (predicate (action ...))
(predicate2 (action2 ...))
(#t default ))
can be written as...
predicate ? action( ... ) :
predicate2 ? action2( ... ) :
default;
This is very "functional", as it branches your code without side effects. So instead of:
if (predicate) {
foo = "one";
} else if (predicate2) {
foo = "two";
} else {
foo = "default";
}
You can write:
foo = predicate ? "one" :
predicate2 ? "two" :
"default";
Works nice with recursion, too :)
Numbers are also objects. So you can do cool stuff like:
// convert to base 2
(5).toString(2) // returns "101"
// provide built in iteration
Number.prototype.times = function(funct){
if(typeof funct === 'function') {
for(var i = 0;i < Math.floor(this);i++) {
funct(i);
}
}
return this;
}
(5).times(function(i){
string += i+" ";
});
// string now equals "0 1 2 3 4 "
var x = 1000;
x.times(function(i){
document.body.innerHTML += '<p>paragraph #'+i+'</p>';
});
// adds 1000 parapraphs to the document
How about closures in JavaScript (similar to anonymous methods in C# v2.0+). You can create a function that creates a function or "expression".
Example of closures:
//Takes a function that filters numbers and calls the function on
//it to build up a list of numbers that satisfy the function.
function filter(filterFunction, numbers)
{
var filteredNumbers = [];
for (var index = 0; index < numbers.length; index++)
{
if (filterFunction(numbers[index]) == true)
{
filteredNumbers.push(numbers[index]);
}
}
return filteredNumbers;
}
//Creates a function (closure) that will remember the value "lowerBound"
//that gets passed in and keep a copy of it.
function buildGreaterThanFunction(lowerBound)
{
return function (numberToCheck) {
return (numberToCheck > lowerBound) ? true : false;
};
}
var numbers = [1, 15, 20, 4, 11, 9, 77, 102, 6];
var greaterThan7 = buildGreaterThanFunction(7);
var greaterThan15 = buildGreaterThanFunction(15);
numbers = filter(greaterThan7, numbers);
alert('Greater Than 7: ' + numbers);
numbers = filter(greaterThan15, numbers);
alert('Greater Than 15: ' + numbers);
You can also extend (inherit) classes and override properties/methods using the prototype chain spoon16 alluded to.
In the following example we create a class Pet and define some properties. We also override the .toString() method inherited from Object.
After this we create a Dog class which extends Pet and overrides the .toString() method again changing it's behavior (polymorphism). In addition we add some other properties to the child class.
After this we check the inheritance chain to show off that Dog is still of type Dog, of type Pet, and of type Object.
// Defines a Pet class constructor
function Pet(name)
{
this.getName = function() { return name; };
this.setName = function(newName) { name = newName; };
}
// Adds the Pet.toString() function for all Pet objects
Pet.prototype.toString = function()
{
return 'This pets name is: ' + this.getName();
};
// end of class Pet
// Define Dog class constructor (Dog : Pet)
function Dog(name, breed)
{
// think Dog : base(name)
Pet.call(this, name);
this.getBreed = function() { return breed; };
}
// this makes Dog.prototype inherit from Pet.prototype
Dog.prototype = new Pet();
// Currently Pet.prototype.constructor
// points to Pet. We want our Dog instances'
// constructor to point to Dog.
Dog.prototype.constructor = Dog;
// Now we override Pet.prototype.toString
Dog.prototype.toString = function()
{
return 'This dogs name is: ' + this.getName() +
', and its breed is: ' + this.getBreed();
};
// end of class Dog
var parrotty = new Pet('Parrotty the Parrot');
var dog = new Dog('Buddy', 'Great Dane');
// test the new toString()
alert(parrotty);
alert(dog);
// Testing instanceof (similar to the `is` operator)
alert('Is dog instance of Dog? ' + (dog instanceof Dog)); //true
alert('Is dog instance of Pet? ' + (dog instanceof Pet)); //true
alert('Is dog instance of Object? ' + (dog instanceof Object)); //true
Both answers to this question were codes modified from a great MSDN article by Ray Djajadinata.
You may catch exceptions depending on their type. Quoted from MDC:
try {
myroutine(); // may throw three exceptions
} catch (e if e instanceof TypeError) {
// statements to handle TypeError exceptions
} catch (e if e instanceof RangeError) {
// statements to handle RangeError exceptions
} catch (e if e instanceof EvalError) {
// statements to handle EvalError exceptions
} catch (e) {
// statements to handle any unspecified exceptions
logMyErrors(e); // pass exception object to error handler
}
NOTE: Conditional catch clauses are a Netscape (and hence Mozilla/Firefox) extension that is not part of the ECMAScript specification and hence cannot be relied upon except on particular browsers.
Off the top of my head...
Functions
arguments.callee refers to the function that hosts the "arguments" variable, so it can be used to recurse anonymous functions:
var recurse = function() {
if (condition) arguments.callee(); //calls recurse() again
}
That's useful if you want to do something like this:
//do something to all array items within an array recursively
myArray.forEach(function(item) {
if (item instanceof Array) item.forEach(arguments.callee)
else {/*...*/}
})
Objects
An interesting thing about object members: they can have any string as their names:
//these are normal object members
var obj = {
a : function() {},
b : function() {}
}
//but we can do this too
var rules = {
".layout .widget" : function(element) {},
"a[href]" : function(element) {}
}
/*
this snippet searches the page for elements that
match the CSS selectors and applies the respective function to them:
*/
for (var item in rules) {
var elements = document.querySelectorAll(rules[item]);
for (var e, i = 0; e = elements[i++];) rules[item](e);
}
Strings
String.split can take regular expressions as parameters:
"hello world with spaces".split(/\s+/g);
//returns an array: ["hello", "world", "with", "spaces"]
String.replace can take a regular expression as a search parameter and a function as a replacement parameter:
var i = 1;
"foo bar baz ".replace(/\s+/g, function() {return i++});
//returns "foo1bar2baz3"
You can use objects instead of switches most of the time.
function getInnerText(o){
return o === null? null : {
string: o,
array: o.map(getInnerText).join(""),
object:getInnerText(o["childNodes"])
}[typeis(o)];
}
Update: if you're concerned about the cases evaluating in advance being inefficient (why are you worried about efficiency this early on in the design of the program??) then you can do something like this:
function getInnerText(o){
return o === null? null : {
string: function() { return o;},
array: function() { return o.map(getInnerText).join(""); },
object: function () { return getInnerText(o["childNodes"]; ) }
}[typeis(o)]();
}
This is more onerous to type (or read) than either a switch or an object, but it preserves the benefits of using an object instead of a switch, detailed in the comments section below. This style also makes it more straightforward to spin this out into a proper "class" once it grows up enough.
update2: with proposed syntax extensions for ES.next, this becomes
let getInnerText = o -> ({
string: o -> o,
array: o -> o.map(getInnerText).join(""),
object: o -> getInnerText(o["childNodes"])
}[ typeis o ] || (->null) )(o);
Be sure to use the hasOwnProperty method when iterating through an object's properties:
for (p in anObject) {
if (anObject.hasOwnProperty(p)) {
//Do stuff with p here
}
}
This is done so that you will only access the direct properties of anObject, and not use the properties that are down the prototype chain.
Private variables with a Public Interface
It uses a neat little trick with a self-calling function definition.
Everything inside the object which is returned is available in the public interface, while everything else is private.
var test = function () {
//private members
var x = 1;
var y = function () {
return x * 2;
};
//public interface
return {
setx : function (newx) {
x = newx;
},
gety : function () {
return y();
}
}
}();
assert(undefined == test.x);
assert(undefined == test.y);
assert(2 == test.gety());
test.setx(5);
assert(10 == test.gety());

Categories

Resources