wk6.0

Javascript

(Borrowed and heavily copied from JavaScript: The Good Parts by Douglas Crockford)

Check out these links:

A note about strict mode

Note: place "use strict"; at the top of your javascript scripts in order to have better type checking.

Objects

Object literals

var empty_object = {};

var stoog = {
  "first-name": "Jerome", 
  "last-name": "Howard"
};

Quotes around the property are optional if the property is a valid javascript variable name (like first_name) but required if not a valid name (like first-name).

Retrieval

stooge["first-name"] //"Jerome"

If the property is a valid javascript variable name, we can access it using a '.'

stooge.first-name // not valid, will throw an error

flight.time // valid

If we try to retrieve the value of a non-existent property, we get an undefined value.

stooge["middle-name"] //undefined

We can use the || operator to fill in defaults:

var middle = stooge["middle-name"] || "(none)";

var status = flight.status || "unknown";

Attempting to retrieve values from undefined will throw a TypeError exception. This can be guarded against with the && operator:

flight.equipment // undefined

flight.equipment.model // throw "TypeError"

flight.equipment && flight.equipment.model // undefined

Update

stooge["first-name"] = "Lester" // replaces "Jerome"

stooge.nickname = "Curly" // creates a property .nickname and sets the value to "Curly"

Reference

Objects are passed around by reference. They are never copied:

var x = stooge;
x.nickname = 'Curly';
var nick = stooge.nickname; // What is the value of nick?
var a = {}, b = {}, c = {}; // a, b, c all refer to different objects

a = b = c = {}; // a, b, c, all refer to the same empty object

Prototype

No classes in javascript. Instead we use prototypes to inherit object properties.

Every object is linked to a prototype object from which it can inherit properties. All objects created from object literals are linked to Object.prototype, an object that comes standard with javascript.

This is similar to how declaring a base class in python:

class Deck:
  ...

is equivalent to declaring a class that inherits from the generic object class

class Deck(object): # Equivalent to the above class.
...

When you make an object in js, you can specify which object should be the prototype. The create method creates a new object that uses an old object as its prototype.

var another_stooge = Object.create(stooge); // linking another_stooge to stooge prototype via the create function.

Just like in python, when we make changes to our object the original object prototype is not changed:

another_stooge["first-name"] = "Moe";

stooge["first-name"] // "Lester"
another_stooge["first-name"] //"Moe"

If we call a property that doesn't exist in our object, javascript will look to the object prototype for the property and then the object prototype's prototype all the way back to Object.prototype. This is called delegation.

The prototype relationship is a dynamic relationship; if we add a new property to a prototype, that property will immediately be visible in all objects that inherit from that prototype.

stooge.profession = 'actor';
another_stooge.profession // 'actor'

Reflection

To figure out what type of value our property is use the typeof operator:

typeof flight.number // number
typeof flight.status // string
typeof flight.arrival // object
typeof flight.manifest // undefined

be careful though, it sometimes gives strange answers:

typeof NaN // 'number' lol
typeof Null // 'object' wat

The other option is to use hasOwnProperty which will return either true or false depending on whether the object has the given property. The hasOwnProperty does not look at the prototype chain.

stooge.hasOwnProperty("profession"); // true

another_stooge.hasOwnProperty("profession"); //false

Enumeration

for (name in another_stooge) { // will return all properties including prototype properties 
   console.log(name);
   }
for (name in another_stooge) {                    // will only return 'first'
    if (another_stooge.hasOwnProperty(name)) {
        console.log(name);
    }
}

There is no guarantee on the order that the property names will appear. If we want to get names in a specific order, we should use an array instead of a dict-like object.

var i;
var properties = [
    'first',
    'middle',
    'last',
    'age',
    'profession'
];

for (i = 0; i < properties.length; i += 1) {
    document.writeln(properties[i] + ': ' +
        another_stooge[properties[i]]);
};

Delete

Removing an object property will not touch the prototype property. As a result, if the prototype and the object have the same property name, removing the object property will expose the prototype property.

another_stooge.nickname // "Moe"

delete another_stooge.nickname;

another_stooge.nickname // "Curly"

Global Variables

Javascript has a global variable problem.

[Rant here]

There are three ways to define global variables.

  1. Place a var statement outside any function:
var foo = value;
  1. Add a property directly to the global object. The global object is the container of all global variables. In the web browsers, the global object goes by the name window:
window.foo = value;
  1. The third way (arguably the worst) is to use a variable without declaring it. This is called implied global:
foo = value;

Also note here, that when I say global, I don't mean global to a single script, I mean global to all the scripts referenced in the DOM. That's bad.

Local Variables

Javascript has function-level local scope (but not block scope for some reason...): Addendum: ES6 introduces block scoping with let: "let is the new var"

// code here can not use carName

function myFunction() {
    var carName = "Volvo";

    // code here can use carName

}

And global scope:

var carName = " Volvo";

// code here can use carName

function myFunction() {

    // code here can use carName 

}

and ...global scope!?

// code here can use carName

function myFunction() {
    carName = "Volvo";

    // code here can use carName

}

Global Abatement

One way to minimize the use of global variables is to create a single global variable for your application:

var MYAPP = {};

That variable then becomes the container for your applicatioon:

MYAPP.stooge = {
  first: "Joe",
  last: "Howard"
};

MYAPP.flight = {
  airline: "Oceanic",
  number: 815,
  departure: {
    IATA: "SYD",
    time: "2015-11-22 14:55",
    city: "Sydney"
  },
  arrival: {
    IATA: "LAX",
    time: "2015-11-23- 10:42",
    city: "Los Angeles"
  }
};

Later we will see that using closures for information hiding provides another effective global abatement technique.


In [ ]: