view core-javascript/core-javascript-work/tutorial.js @ 154:ee0bf994ab95 core-javascript.closure-exercises

Add remove_answers.py script (and clean up closure-exercises.py).
author jf3243
date Wed, 02 Nov 2011 17:27:39 +0000
parents e8bfe6c50a01
children
line wrap: on
line source

// [Rhino] $ js -f testtools.js -f tutorial.js
// [JSDB] $ jsdb -load testtools.js -load tutorial.js

// start warm-up
TEST('warm-up', function()
{
    assert( '0' == 0 );
    assert ( 0 == '' );
    assert( '0' != '' );

    var a = NaN;
    assert( a != a );

});
// end warm-up


// start closures
TEST('closures', function()
{
    // A factory for creating get-set pairs.
    var get_set_factory = function(){

        var value;
        var get = function(){
            return value;
        };
        var set = function(new_value){
            value = new_value;
        };

        return {
            get: get,
            set: set
        };
    };

    // Create and unpack two get-set pairs.
    var tmp;
    tmp= get_set_factory();
    var get_a = tmp.get;
    var set_a = tmp.set;

    tmp= get_set_factory();
    var get_b = tmp.get;
    var set_b = tmp.set;

    // Test that both pairs work.
    set_a(12);
    assert( get_a() === 12 );

    set_b(13);
    assert( get_b() === 13 );

    // Test that each pair has its own value.
    assert( get_a() === 12 );

});
// end closures


// start return_this
TEST('return_this', function()
{
    var return_this = function(){
        return this;
    };

    var default_this = return_this();
    assert( default_this.telltail === 'global' );

    var obj = {};
    obj.return_this = return_this;
    assert( obj.return_this === return_this );

    assert( obj.return_this() === obj );
    assert( obj['return_this']() === obj );

    assert( return_this.call(obj) === obj );
    assert( return_this.apply(obj) === obj );

    assert( return_this.call(undefined).telltail === 'global' );
    assert( return_this.apply(undefined).telltail === 'global' );

});
// end return_this


// start transient-bind
TEST('transient-bind', function()
{
    // Set up the test object.
    var return_this = function(){
        return this;
    };
    var obj = {
        return_this : return_this
    };
    assert( obj.return_this === return_this );

    // Deferring method call changes the outcome.
    var method_deferred = obj.return_this;
    assert( method_deferred ===  obj.return_this );
    assert( method_deferred() !==  obj.return_this() );  // AAA

    // The two outcomes, precisely stated.
    assert( obj.return_this() === obj );
    assert( method_deferred().telltail === 'global' );

    // Another view on the matter.
    assert( method_deferred === return_this );
    assert( method_deferred() === return_this() );  // BBB

});
// end transient-bind


// start millers-device
TEST('millers-device', function()
{
    var array = [];
    var obj = {};
    var fn = function(){};

    assert( typeof array === 'object' );
    assert( '' + obj === '[object Object]' );

    assert( obj.toString() === '[object Object]' );

    var object_toString = obj.toString;

    assert( object_toString.call(array) === '[object Array]' );
    assert( object_toString.call(fn) === '[object Function]' );

});
// end millers-device


// start return_arguments
TEST('return_arguments', function()
{
    var return_arguments = function(){
        return arguments;
    };

    var my_arguments = return_arguments(0, 1);

    assert( my_arguments.length === 2 );

    assert( my_arguments[0]  === 0 );
    assert( my_arguments[1]  === 1 );

    assert( '' + my_arguments === '[object Object]' );
    assert( '' + [0, 1] === '0,1' );

    var array_slice = [].slice;
    var my_arguments_fixed = array_slice.call( my_arguments );

    assert( '' + my_arguments_fixed === '0,1');

    var obj = {};
    assert( obj.toString.call( my_arguments_fixed ) === '[object Array]' );

});
// end return_arguments


// start new-operator
TEST('new-operator', function()
{
    // A 'traditional class'.  It records 'this' as a side effect.
    var this_in_Fn;
    var Fn = function(){
        this_in_Fn = this;
    };

    // Call the 'class' without the 'new'.
    this_in_Fn = null;          // Clear any previous value.
    var non_instance = Fn();
    assert( non_instance === undefined );
    assert( this_in_Fn.telltail === 'global');

    // Call the 'class' with the 'new'.
    this_in_Fn = null;          // Clear any previous value.
    var instance = new Fn();
    assert( instance === this_in_Fn );
    assert( instance.telltail === undefined );

    // Demonstrate that instance is a descendant of Fn.prototype.
    Fn.prototype.telltail = 'instance-of-Fn';
    assert( instance.telltail === 'instance-of-Fn' );

    // We can give Fn a new prototype.
    instance.new_telltail = 'child-of-instance';
    Fn.prototype = instance;

    // And now an instance of Fn has two telltails.
    var second_instance = new Fn();
    assert( second_instance.telltail === 'instance-of-Fn' );
    assert( second_instance.new_telltail === 'child-of-instance' );

});
// end new-operator