Math In the Address Bar

Did you know that you can do math problems in the address bar of your browser? Regardless of what browser your using, you can use its address bar to find the answer to an arithmetic problem. For instance, let’s say that you are using Internet Explorer and all of a sudden someone asks you what 54 × 32 is. To figure it out, you type the following into the address bar and then hit the ENTER key:

javascript:alert(54 * 32)

If you tried it out, you know the answer is 1728. What about the square root of 1728? To figure it out, you could use the following:

javascript:alert(Math.sqrt(1728))

Now that you know that Math.sqrt(…) exists, you may be wondering, what other math related functions and constants like this exist. Here is a list of them derived from DevGuru.com:

Constants

Math.E
Euler’s constant and the base of natural logarithms (~2.7183).

Math.LN10
The natural log of 10.

Math.LN2
The natural log of 2.

Math.LOG10E
The base 10 log of E.

Math.LOG2E
The base 2 log of E.

Math.PI
PI – The circumference of a circle divided by its the diameter.

Math.SQRT1_2
One divided by the square root of 2.

Math.SQRT2
The square root of 2.

Functions

Math.abs(X)
The absolute value of the number X.

Math.acos(X)
The arccosine of X (which must be greater than or equal to -1 and less than or equal to 1) as a value between 0 and PI.

Math.asin(X)
The arcsine of X (which must be greater than or equal to -1 and less than or equal to 1) as a value between -PI / 2 and PI / 2.

Math.atan(X)
The arctangent of X as a value between -PI / 2 and PI / 2.

Math.atan2(X, Y)
The arctangent of X / Y as a value between -PI / 2 and PI / 2.

Math.ceil(X)
If X is an integer this evaluates to X, otherwise it evaluates to the next integer up.

Math.cos(X)
The cosine of X as a value between -1 and 1.

Math.exp(X)
The value of EX where E is Euler’s constant.

Math.floor(X)
If X is an integer, this evaluates to X, otherwise it evaluates to the next integer down.

Math.log(X)
The natural log (base E) of X (which must be greater than 0).

Math.max(X, Y, …)
The maximum number of X, Y, and any other parameters that you specify.

Math.min(X, Y, …)
The minimum number of X, Y, and any other parameters that you specify.

Math.pow(X, Y)
The value of XY.

Math.random()
A random number that is greater than or equal to 0 and less than 1.

Math.round(X)
The rounded value of X. If the fractional portion of the number is less than 0.5, the number is rounded down, otherwise it is rounded up.

Math.sin(X)
The sine of X as a value between -1 and 1.

Math.sqrt(X)
The square root X (which must be greater than or equal to 0).

Math.tan(X)
The tangent of X.

If you haven’t already guessed it, alert(...) actually displays whatever you specify in a new dialog box. Believe it or not, you can also assign values to variables and then use those variables later on. Of course, though, you have to do all of this on one line. Here is an example of what I mean by assigning values to variables and then using them later:

javascript:age = 2011 - 1987; alert(age + Math.sqrt(age))

If you tried the above code out in your address bar, you now know what my age plus the square root of my age is.

All I have to say now is, “welcome to the world if JavaScript!!!”

Private Variables In JavaScript

Often times, many people have made claims that it is not possible to make variables private in JavaScript. I am here to tell you that those people are wrong. There are many implementations from JavaScript guru’s such as Douglas Crockford explaining how to do this. Although these implementations will get the job done, I have noticed that these implementations do not use prototypal functions. On the contrary, the following shows how to give prototypal functions access to private members:

// Immediately executed closure to define a person.
var Person = (function() {
  // The parameter required to retrieve the private data of a person object.
  var theKey = {};
  
  function Person(firstName, lastName, isMale, birthDate) {
    // If birth date is a string, convert it to a date.
    if(typeof birthDate == "string")
      birthDate = new Date(birthDate);
    if(isNaN(birthDate.getTime()) || !(birthDate instanceof Date))
       throw new Error("the passed birth date was invalid");
    // Object literal to keep track of the private data.
    var privateData = {
      firstName : firstName + "",
      lastName : lastName + "",
      isMale : !!isMale,
      birthDate : birthDate
    };
    // If theKey is passed as aKey, the private members of the object are
    // returned.  Since aKey must be theKey in order to retrieve privateData and
    // theKey is an empty object literal, you can be sure that private members
    // will not be returned from the function to any code outside of the
    // closure.  The only non-prototypal function.
    this._ = function(aKey) {
      if(aKey == theKey)
        return privateData;
    };
  }
  
  // Alias for the prototype of the Person object.
  var p = Person.prototype;
  
  // Get or set the first name for the person.
  p.firstName = function(newName) {
    // Get the private data members.
    var pData = this._(theKey);
    // If a parameter was passed, assign the new first name.
    if(!arguments.length)
      return pData.firstName;
    // Set the first name.
    pData.firstName = newName;
    // Allow chainable calls.
    return this;
  };
  
  // Get or set the last name for the person.
  p.lastName = function(newName) {
    // Get the private data members.
    var pData = this._(theKey);
    // If a parameter was passed, assign the new last name.
    if(!arguments.length)
      return pData.lastName;
    // Set the last name.
    pData.lastName = newName;
    // Allow chainable calls.
    return this;
  };
  
  // Gets how many years old the person is.
  p.yearsOld = function() {
    var now = new Date;  // current date
    var birth = this._(theKey).birthDate;  // birth date
    var years = now.getFullYear() - birth.getFullYear();  // difference in years
    now = now.getMonth() * 100 + now.getDate();  // now as MMDD as number
    birth = birth.getMonth() * 100 + birth.getDate();  // now as MMDD as number
    return years - (now < birth);  // Return real years old.
  };
  
  // Gets the birth date.  Makes valueOf an alias so that people can be compared
  // by age.
  p.birthDate = p.valueOf = function() {
    return this._(theKey).birthDate;
  };
  
  // Gets the full name.
  p.fullName = function() {
    var pData = this._(theKey);
    return pData.firstName + " " + pData.lastName;
  };
  
  // Get the string representation of this person.
  p.toString = function() {
    var pData = this._(theKey);
    return "I am a " + this.yearsOld() + " year old "
      + (pData.isMale ? "male" : "female") + " named " + pData.firstName + " "
      + pData.lastName + ".";
  };
  
  // Allow the person pseudo-class to exist outside of this closure.
  return Person;
})();

The code above defines a person pseudo-class in JavaScript. There are four members that are private to each instantiated person object: firstName, lastName, isMale, and birthDate. The first name and last name can be retrieved and set by using the public getters/setters firstName() and lastName(). In addition, fullName() is another accessor method. The person’s birth date can only be retrieved by using either birthDate() or valueOf(). In addition, you can find out how many years old the person is by using yearsOld(). Finally, you can print the person object out as a string to find all of the person’s information.

Now it is time for the tests:

var me = new Person("Chris", "West", true, "October 11, 1492");
var jade = new Person("Jade", "Williams", false, "April 28, 1984");
var harry = new Person("Harry", "Finkelstien", true, "June 4, 1987");

// Show my full name.
alert(me.fullName());

// Change Jade's last name and then show it.
alert(jade.lastName("Flintstone").fullName());

// Show how old harry is.
alert(harry.yearsOld());

// Show everything about the three people.
alert(me);
alert(jade);
alert(harry);

// An attempt to retrieve the private members from the outside.
alert("Could " + (me._({}) == undefined ? "not " : "")
  + "access the private members from the outside.");

I think the comments explain most of the test code pretty well. One thing to note is that, just because you pass in an empty object literal doesn’t mean that it is the same one that is needed to retrieve the private members.

In conclusion, as is demonstrated in my definition of the Person pseudo-class, prototypal functions can retrieve private members.

Deep Copy of Arrays

With jPaq and many other JavaScript libraries, it is very easy to do a shallow copy of an array. On the other hand, it isn’t as easy to do a deep copy of arrays. For this reason, I plan on replacing the Array.prototype.clone() function with the following:

Array.prototype.clone = function(doDeepCopy) {
    if(doDeepCopy) {
        var encountered = [{
            a : this,
            b : []
        }];

        var item,
            levels = [{a:this, b:encountered[0].b, i:0}],
            level = 0,
            i = 0,
            len = this.length;

        while(i < len) {
            item = levels[level].a[i];
            if(Object.prototype.toString.call(item) === "[object Array]") {
                for(var j = encountered.length - 1; j >= 0; j--) {
                    if(encountered[j].a === item) {
                        levels[level].b.push(encountered[j].b);
                        break;
                    }
                }
                if(j < 0) {
                    encountered.push(j = {
                        a : item,
                        b : []
                    });
                    levels[level].b.push(j.b);
                    levels[level].i = i + 1;
                    levels[++level] = {a:item, b:j.b, i:0};
                    i = -1;
                    len = item.length;
                }
            }
            else {
                levels[level].b.push(item);
            }

            if(++i == len && level > 0) {
                levels.pop();
                i = levels[--level].i;
                len = levels[level].a.length;
            }
        }

        return encountered[0].b;
    }
    else {
        return this.slice(0);
    }
};

The above code can be used to make deep copies of arrays. It is important to note, though, that only sub-arrays are deeply copied, not objects. The reason so much code is used is to even make it possible to make a deep copy of a recursive array structure. The following code exemplifies how to use this function:

// Create a recursive array to prove that the cloning function can handle it.
var arrOriginal = [1,2,3];
arrOriginal.push(arrOriginal);

// Make a shallow copy of the recursive array.
var arrShallowCopy = arrOriginal.clone();

// Prove that the shallow copy isn't the same as a deep copy by showing that
// arrShallowCopy contains arrOriginal.
alert("It is " + (arrShallowCopy[3] === arrOriginal)
    + " that arrShallowCopy contains arrOriginal.");

// Make a deep copy of the recursive array.
var arrDeepCopy = arrOriginal.clone(true);

// Prove that the deep copy really works by showing that the original array is
// not the fourth item in arrDeepCopy but that this new array is.
alert("It is "
    + (arrDeepCopy[3] !== arrOriginal && arrDeepCopy === arrDeepCopy[3])
    + " that arrDeepCopy contains itself and not arrOriginal.");

If you want to use this code right now, there is nothing stopping you. The code doesn’t require any library references and is fully cross-browser compatible. A JSBin example can be found here. It even works in JScript. The only thing that I ask is that you give credit where it is due. šŸ˜€