Archive for May 8th, 2011|Daily archive page
Arrays, delete v. splice
Delete doesn’t really delete an array item like you think it does. It replaces whatever was there with undefined.
Consider:
(function () {
"use strict";
var myArray = ["one", "two", "three", "four"];
delete myArray[2];
window.onload = function () {
var message, htmlMarkup, i;
message = document.getElementById('LabelMessage');
htmlMarkup = "<p>myArray Length: " + myArray.length + "</p>";
for (i = 0; i < myArray.length; i = i + 1) {
htmlMarkup += "<p>myArray[" + i + "]: " + myArray[i] + "</p>";
}
message.innerHTML = htmlMarkup;
};
}());
With the following HTML:
<!DOCTYPE HTML> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>My Document</title> <script src="Test.js" type="text/javascript"></script> </head> <body> <h1>My JavaScript Tests</h1> <div id="LabelMessage">Test</div> </body> </html>
What we see is an array length of 4 (not 3), and undefined instead of “three”.
To truly remove the third item in the array, and shift the fourth one up or left to fill-in for the third one, use:
myArray.splice(2, 1);
“use strict” in a function?
JsLint started to complain about using the “use strict” in a function form. What???
I found this Douglas Crockford posting from December 2010: “Strict Mode Is Coming To Town”
I was code testing delete Array[i]. Here’s a code sample that implements the recommendation, and passes JsLint:
(function () {
"use strict";
var myArray = ["one", "two", "three", "four"];
}());
So… if developing modules, from here on out, in the module file wrap it all up in a closure, and “use strict” will respect the scope of the closure, and not clobber up all the old stuff that is not ES5 ready… (I think it was referred to as “sloppy” co-mingled with “strict”)
Objects passed by reference
Consider:
var MyObject;
MyObject = MyObject || {};
MyObject.Message = "";
function UpdateMessage(obj) {
obj.Message = "Hello World!";
}
UpdateMessage(MyObject);
window.onload = function () {
var message = document.getElementById("LabelMessage");
message.innerHTML = MyObject.Message;
};
We’ve passed “MyObject” to a function, and changed the value of the property “MyObject.Message” inside the function. When we write this value to the DOM element “LabelMessage”, what we see is:
“Hello World!”
Lexical Scope
Scope defined statically, based on where definition of, say a variable, is within the source code. For example:
var x = 0; function f() { return x; } function g() { var x = 1; return f(); } window.onload = function () { var message = document.getElementById('LabelMessage'); message.innerHTML = g(); }What we see displayed on the web page for “message” is: 0 (zero).
Why:
At the moment f() is defined, the value of “x” in the lexical scope (where it appears in the source code) is the value of “x” defined in line 1.
The scope of “var x = 1;” in function g() is g(). It is not in the same lexical scope of “var x = 0;” from line 1. Therefore, at the time f() is defined the only “var x” in scope is the one defined earlier on line 1.
To test this, we remove the “var” from in front of “x” in g(). Now what “x” in g() is referring to is the “x” on line 1. When we refresh the page, we see “1” displayed.
Another Observation:
In JsLint (www.jslint.com) the option to have one “var” block per function makes perfect sense.
Imagine if there were “var” declarations all over the code and in multiple places in a single function. Try figuring the which of the declared scopes is the right one!
Note on simulating classes
Thinking of C#…
Instance properties would look something like this:
Class(param) {
this.property = param;
}
Instance methods:
Class.prototype.method = function () { /* function body... */ };
Class properties (similar to “static” in C#):
Class.PROPERTY = value;
Class methods – invoked through the class itself, not any particular instance of the class. The “this” keyword does not refer to any particular instance of the class but tot the constructor function itself. Typically “this” is not used at all. Operations are not on instances but on any passed in parameters or variables in scope.
Class.method = function () { /* function body... */ };
The Douglas Crockford videos
Excellent videos to add to the collection.
- Volume One: The Early Years
- Chapter 2: And Then There Was JavaScript
- Act III: Function the Ultimate
- Episode IV: The Metamorphosis of Ajax
- Part V: The End of All Things
Thanks Brandon, for pointing these out.
Leave a comment