JavaScript Philosophy and Tutorial

Draft - still under construction

The purpose of this and the accompanying articles is not to teach the details of any specific part of the language. Such information is readily available from many sources.

You are reading this in order to learn how to think while using the language, how to write poetry and not doggerel, how to be a good programmer, coder, or author.

While writing this tutorial, I found myself having to explain why I was writing ugly and awkward code, when much cleaner code was obvious. Eventually, the explanations and examples of JavaScript's natural ugliness overwhelmed the intended purpose of this document. Those explanations have now been moved to a separate document, JavaScript Problems.

Familiarize yourself with JavaScript's failings before writing code, so you don't fall into the same traps and bad coding practices that so many others have. If you see what appears to be strange constructs or usages in the Tutorial, that document should explain why.

Web Design Philosophy

If you haven't read the introduction to web design philosophy, you should do that first. It covers the general philosophy to be applied to all languages, and you should understand it before reading this document.

On the other hand, its crucial point (you should think and write in the natural way for any given language) can become a bad idea when it is applied to a language as naturally bad as JavaScript.

JavaScript Philosophy

Enhance.

Web crawling software and people whose browsers aren't configured to run Javascript will not see anything from the use of this language. Use Javascript only to enhance the appearance of the page. Do not use it to provide essential information.

(Note that for our current purposes we are dealing mostly with static web pages, not with interactive forms that are running programs to produce further results. That is an entirely different topic.)

If you can avoid using JavaScript, that's great. But sometimes you really need to, and sometimes the temptation to add that little bit extra is too tempting. Use JavaScript to enhance the appearance and functionality of your web pages, not to compose and generate them. Anything generated by JavaScript will not be seen by web crawlers; it will not be indexed for searching; and it will not contribute to the ranking of your page.

Terminology

Variables
are data identifiers. JavaScript variables are typeless. A variable can represent any type of data, and may represent different types of data at different times.
Arrays
allow one to access multiple instances of data associated with a variable.
Array elements are accessed by var[index], where index is an integer.
Associative Arrays
associate multiple instances of data with a variable and key string combination (e.g. var["key"]), rather than with an integer index.
JavaScript Types
refer to the data itself. JavaScript variables themselves are typeless.
The typeof operator returns the name of the type of data that a variable refers to.
Types undefined, number, string, and boolean
are simple data.
You can change which value that the variable refers to, but not the value itself. (E.g. given x=y="abc"; y="def", x and y will have different values.)
Types object and function
are potentially complex structures.
More than one variable can refer to the same object or function.
Changing the data that one variable refers to will also change the data accessed by all other variables referring to that same object. (E.g. x=y=["a","b","c"]; x[1]="B", means that y[1] will also become "B")
Numbers
in JavaScript are floating point, not integer.
Bit operators (e.g. <<, &, and ~) are extremely efficient in other languages, but require complex processing in JavaScript. (Values are truncated to 32-bit integers, the operation is performed, and the result is converted to a 64-bit floating point number.)
Objects
in JavaScript are simply associative arrays, with their keys being known as properties.
var["property"] identifies one property of an object, which itself might be an object.
var["property"] can also be represented more simply as var.property, though the quotation marks are required if the property name matches a JavaScript reserved word.
Functions
JavaScript implements functions as objects, with a few extra intrinsic properties.
Arrays
JavaScript does not provide real arrays, but it does provide an object that behaves much like one.
Like functions, arrays are implemented as objects, with a few extra intrinsic properties, although the typeof operator does not recognize them as a distinct type as it does functions.
JavaScript arrays are simply associative arrays, with the key being the value of the integer converted to a string. (e.g. arr["007"]="Bond" will add a 007 property to the array, without affecting arr["7"], and will not change the current length of the array. Negative subscripts will of course work too, but they won't affect the length of the array.
one = 1
two = "2"
x = []
x["blue"] = 42 // key is "blue"
x[one-1] = " " // key and index is "0"
x["1"] = "a"   // key and index is "1"
x[1+1] = "b"   // key and index is "2"
               // x.length is 3
x[two+1] = "3" // key and index is "21"
x[-5] = "E"    // key is "-5"
x[-26]= "Z"    // key is "-26"
               // x.length is 22
					
x.length is one more than the largest key that has a non-negative numeric value when converted to a number.

JavaScript Example: Icon Insertion

Suppose you want to have an icon (when available) appear as part of each linked URL, as in the example previously given in the HTML document. This could of course be done manually, but it's a lot easier to maintain and you are less likely to forget one or to make a mistake if it can be done automatically by JavaScript.

The effect is purely cosmetic, it helps but isn't necessary, and if the JavaScript doesn't run or it fails, your page still looks fine. I.e. it fits within our philosophy.

<script> "use strict"
;(function() {
  var anchors = document.getElementsByTagName("a")
  var a
  var i
  for (a in anchors) {
    if ("undefined" !== typeof anchors[a].href) {
      i = document.createElement("img")
      i.setAttribute("alt", "")
      i.setAttribute("class", "icon")
      i.setAttribute("src", anchors[a].href.replace(/^(.*:\/\/[^\/]*).*/, "$1"+"/favicon.ico"))
      anchors[a].insertBefore(i, anchors[a].childNodes[0])
    }
  }
})()
</script>
			
Inserting inline icons before links.

If you place this script after the body of your page, all your anchors will be automatically modified.

img.icon {
  height: 1.5em;
  width: auto;
  margin-bottom: -.3em;
  vertical-align: baseline;
}
		
CSS to set icon size.

If the URL generated for any of the images is invalid or can't load for some other reason, the alt="" attribute will ensure that the browser doesn't display anything indicating that something went wrong. Your readers will simply not see an image at that location.

That is an ideal use of JavaScript. If it fails, your page will still look good and no one will know what they're missing.

JavaScript Example: Class Changes

Suppose you want parts of your web page to appear different under different circumstances, typically chosen by the user. One easy way of doing this is to define styles associated with two different CSS classes.

You can define a button or add an onclick= attribute to a block of HTML to use JavaScript to simply change the class attribute of a block of code.

CSS:
.normal xxx { ... }
.normal yyy { ... }
...
.fancy xxx { ... }
.fancy yyy { ... }
...
		
HTML:
<div class="normal" onclick="toggle_class(this,'normal','fancy')">
...
</div>
		
Script:
var toggle_class=function(e,a,b) {
  e.setAttribute(class, (e.getAttribute(class) === a) ? b : a)
}
		
Or putting the script inline:
<div class="normal" onclick="this.setAttribute(class, (this.getAttribute(class) === 'fancy') ? 'normal' : 'fancy')">
...
</div>
}
		
Toggling between two classes.

Stealth

In the above example, the div started out in the normal class. As with the inserted icons, if the JavaScript fails, nothing changes, your page still looks okay, and your audience isn't aware that anything is wrong.

But what if you have a message on the page telling the reader that they can change the style? That would make it obvious to them that your page is broken.

To avoid that, have the potentially betraying message displayed only if JavaScript is working.

CSS:
.scripted { display: none; }
			
HTML:
<div ...
  <p class="scripted">
    Click this section to toggle its presentation.
  </p>
  ...
</div>
			
Script:
...
</body>
<script> "use strict"
  ;(function() {
    var list = document.getElementsByClassName("scripted")
    var i
    for (i in list) {
  	  list[i].style.display = "initial"
    }
  })()
</script>
</html>
			
Hide scripted elements.

Similarly, you might have sections of code whose display is disabled by the script, thus elminating the need for any <noscript> tags. But generally, following the enhancement-only philosophy, there really isn't any need for this.

JavaScript Example: Style Changes and Additions

...

Assigning Methods

... ???

???

...

Summary

Philosophy:

  • Use JavaScript to enhance your pages, not to generate content.
  • Insert images and other cosmetics in a way that will not disrupt the page if the JavaScript fails or doesn't execute.
  • Use JavaScript to change appearance by changing CSS classes.
  • If necessary, use JavaScript to add new CSS rules.
  • Write your pages in a state that doesn't rely on JavaScript.
  • Initialize script-dependent features to not display until enabled by JavaScript.

A few rules to help avoid bugs:

... ???
...