Small JavaScript Goodies: Patterns

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • Dormilich
    Recognized Expert Expert
    • Aug 2008
    • 8694

    Small JavaScript Goodies: Patterns

    sometimes you need to check, whether in a set of tests at least one condition fails. one good way of programming this includes Exceptions.
    Code:
    // the test function
    function test(v)
    {
        if ("x" == v) // or whatever condition you like
        {
            throw new Error("Condition X failed.");
        }
    }
    a very simple example. test, if in an array all elements are numbers.
    Code:
    function test(n)
    {
        if (isNaN(n)) throw new TypeError("element is not a number.");
    }
    var a = [1, 5, 2, "a", 7];
    try
    {
        for (var l, i=0, l=a.length; i<l; i++)
        {
            test(a[i]);
        }
    }
    catch (e)
    {
        alert(e.message); // show the error message
    }
    suppose you want to check if at least one of the tests does not fail*. here is one possibility to do that using the same test function.
    Code:
    // I call it the “inverted failure test” or “escape test”
    for (var i=0; i<l; i++)
    {
        try
        {
            test(value[i]);
        }
        // every failed test continues the loop, bypassing the final Exception
        catch (e)
        {
            continue;
        }
        // if a test does not fail, the catch block is not executed
        // and the final Exception is thrown
        throw new Error("Condition X met.");
    }
    again a very simple example. this time we want to test, whether there is a number in the array.
    (this pattern pays off for complex test functions.)
    Code:
    // same test function as before
    function test(n)
    {
        if (isNaN(n)) throw new TypeError("element is not a number.");
    }
    var sentence = "I’m an animal lover, so I owe 5 dogs and 7 cats.";
    var a = sentence.split(" ");
    try
    {
        for (var l, i=0, l=a.length; i<l; i++)
        {
            try
            {
                test(a[i]);
            }
            catch (e)
            {
                continue;
            }
            throw new Error("there was a number in.");
        }
    }
    catch (e)
    {
        alert(e.message);
    }
    a real world example (a Chess board) (there are 600 more lines of code… omitted)
    this method is the test function for any Check test (e.g. is the King still in Check(mate)?)
    Code:
    Board.prototype.tryCheck = function(field, capture)
    {
    	try
    	{
    		var offset    = this.offset(false); // get the right set of pieces
    		this.test     = true; // do not execute move
    		this.schlagen = Boolean(capture);	// if I need the test in non-capturing mode	
    		for (var i=1+offset; i<16+offset; i++)
    		{
    			try
    			{
    				if ("xx" == this.piece[i].pos) // an already captured piece
    				{
    					continue;
    				}
    				this.piece[i].move(field);
    			}
    			catch (e)
    			{	// eventually leave without error
    				continue;
    			}
    			// if one piece does a correct move
    			throw new Error("King is still in Check.");
    		}
    	}
    	catch (e) // forward the exception
    	{
    		throw e;
    	}
    	finally
    	{	// reset to default
    		this.test     = false;
    		this.schlagen = false;
    	}
    }
    * which in certain circumstances is not wanted

    using logical XOR
    Code:
    if (expr1 ^ expr2)
    it simply works because the boolean result of expr1 and expr2 represent bitwise 0 (false) and 1 (true). Nevertheless, it is still a bitwise operation. I f you get an error, typecast to Boolean.
    Code:
    if (Boolean(expr1) ^ Boolean(expr2))
    real example, quit a search loop if one of the break conditions appear
    Code:
    // find the root of a polynomial function
    Fn.prototype.findRoot = function()
    {
    	var cnt = 0, dph = 0, end = this.limit[1]; // end of the search interval
    	var erg, x = this.anf; // this.anf = this.limit[0] (start of search interval)
    	var dir = ((end - x) > 0) ? true : false; // searching up or down
    	
    	do
    	{
    // if search direction is down (false) the return is triggered only if the x value drops below the interval end
    		if ([B]dir ^ (x < end)[/B])
    			return false;
    		
    		erg = this.y(x);
    		
    		// another break test …
    		
    		if ((erg > 0 && this.lastY < 0) || (erg < 0 && this.lastY > 0))
    		{
    			this.step /= -10;
    			dph++;
    		}
    		else if (0 != erg)
    			x += this.step;
    
    		this.lastY = erg;
    	}
    	while (erg != 0);
    	this.x0.push(x);
    	return true;
    }
Working...