More advanced notes on Crockford – esp. his book 1. Function and adding more methods Function .prototype.method =function (name, func) { this.prototype[name]=func; return this; }; This is mentioned on p4 and elaborated in CH. 4(p28) == it uses the method method to create new methods. ME: I think that here name is what you will call the new method, func is a previously defined function, and method is ???? the name of the function/method which belongs to the Function object (the granddaddy of all functions) and which is used to add new functions to Function. So for any function f we could say f.method(qsort, quicksort) where quicksort has been previously defined. From then on we could call f.qsort( ) 2. Comments The /* */ syntax should be avoided as it can cause problems with regular expressions. 3. NaN NaN stands for not a number. It is not equal to itself. isNaN(x) tests for it. 4. Strings are immutable --- can you write str+=”ing”; ? Yes, but the result will be stored at a new location (with str pointing to it.) 5. for in and objects for (myvar in obj) { } myvar will iterate thru all the properties in obj. If you do NOT want the properties which are accessed thru the prototype use for (myvar in obj) {if (obj.hasOwnProperty(myvar)){ } } 6. truthy and falsy values falsy are: false, null, undefined, the empty string ‘ ‘, the number 0, the number NaN truthy: everything else 7. Object literals { name|string : expression [, name|string : expression]+ } when the would be name has a character which is not part of a JS name (e. g. a hyphen )then you need to put it in quotes and make it a string. You may use the dot notation when it is a legitimate name – other wise use the myObject[‘name’] form p.20-21 8. Logical operators, guarding and default values && is the logical AND. if (cond1 && cond2) will be false if cond1 is false – and JS will not go on to test cond2. Hence (http://javascript.crockford.com/survey.html) value = p && p.name //p.name will be retrieved only if p has a value – //avoiding an error (TypeError exception) //Good idea to use this technique! || is the logical OR. value = grade || 0 will assign a default grade of 0 if grade is still undefined. NOTE: The examples below work even tho’ stooge is created as an object literal (i.e. NOT with the new Object() constructor syntax.) var stooge = { “first-name”: ‘Jerome’, “last-name”: “Howard” } Note: first-name and last-name are in quotes (i.e. strings) b/c the hyphen prevents them from being a legal JS name. 9. All objects are passed by reference – including arrays, functions, hashes. (p.22) Example is var x = stooge; //previously defined hash x.nickname=’Curly’; var nick = stooge.nickname //”Curly” as x and stooge are // references to the same object. 10. Adding a new method to the Object constructor so that you can make a new object with the same prototype as the object passed in: if (typeOf Object.create !== ‘function’) { Object.create = function (o) { var F = function( ) { }; F.prototype = o; return new F(); }; }; var next_stooge = Object.create(stooge); 11. Passingand comparing by value/reference: Objects are all pass by reference. (Crockford p.22) Strings are probably pass by reference for efficiency (Flanagan –section 3.15.2)- but it doesn’t matter as strings are immutable and so you can’t do anything to change them. However, strings are compared by value! To summarize: (Flanagan section 3.15.4) numbers and Booleans – copied by value, compared by value & passed by value objects – copied by reference, compared by reference and passed by reference strings – compared by value; passing and copying ---- they are immutable! 12. Object properties and reflection As noted in my comment 5, you can get all the properties of an object with: for (myvar in obj) { } Here myvar will iterate thru all the properties in obj, including going up the prototype chain. To avoid going up the prototype chain, use: for (myvar in obj) { if (obj.hasOwnProperty(myvar)){ } }; You may choose to restrict the properties you look at with typeof: for (myvar in obj) { if (typeof myvar != ‘function’)){ } }; In all three of these examples, the order is not guaranteed. If you want the correct order and want to not go up the prototype chain use a for loop: for (i=0; i < obj.length; i++) {alert (obj[i]); } If you want to know what name goes with what value, create a new object for the names. For example: var stoogeProperties = {‘first-name’, ‘last-name’}; for (i=0; i < stooge.length; i++) {alert(stoogeProperties[i]+” has the value “+stooge[i]); } 13. Deleting properties There is a delete myobj.loseProperty statement. Of course, you may now see a loseProperty value from the proptotype. 14. The great Global Object in the sky All variables which are global are made properties of the Global Object. The Global Object has no name --- but you can get at it as either window or self. This can lead to naming conflicts. One way to avoid this is to create your own variable and assign all the other variables you are creating to be its properties: var myGlobalToday ={ }; myGlobalToday.stooge = { yourprevious definition here }; 15. Function objects Functions are objects. Objects are name/value pairs with a a hidden link to the prototype object. Function objects are linked to the Function.prototype (which itself links to Object.prototype). Every function object also has its own prototype property. So if myFunc( ) is a function object then myFunc.prototype links to an object. This object, in turn has a constructor property whose value is myFunc. That is myFunc.prototype.constructor( ) returns myFunc. myFunc.prototype.constructor( ) is different from myFunc.prototype. As functions are objects they can be passed, have methods, etc. 16. Function literals and nested functions A function literal is function myFunc ([parameter list]) {body}; Functions may be nested. A function nested inside another function has access to not only its own variables and parameters but also to those functions it is nested within. This is called closure. It happens because the a function created by a literal has a link to the outer context. 17. Function invocation These 4 patterns set this differently. a. Method invocation pattern this is bound to the object doing the invocation – at the time of invocation Example: myObj.myFunc() -- this refers to myObj This also happens if you call myObj[2], where myObj[2] is a method. Example with an optional parameter in the increment method: var myObj ={ value: 0, increment: function(inc) { this.value += typeof inc === ‘number’ ? inc :1; } } myObj.increment(); alert(myObj.value); myObj.increment(2); alert(myObj.value); //displays 1 //displays 3 b. Function invocation pattern this is bound to the Global Object Example var sum = add(3,4); Unfortunately, because this is bound to the Global Object you can’t use an inner function without the following workaround: Define a new variable – traditionally named that and assign this to it. Now when you define an inner function, you can use that. //augment myObj with a function which doubles its value property myObj.double = function ( ){ var that = this; //the work around var helper = function ( ){ that.value = add(that.value, that.value); } helper( ); //invoke it as a function }; //invoke double as a method myObj.double( ); alert (myObj.value); //gives twice the original value – here 6 c. Constructor invocation pattern In JavaScript objects inherit properties and method via their prototype. JavaScript is class-free. Example: Create a constructor and then add a public method: var Quo = function (str) {this.status = str; } Quo.get_status = function( ) { return this.status; } var confused = new Quo(‘very confused’); alert( confused.get_status(); ) //displays ‘very confused’ Quo has a capitalized name b/c it is a constructor --- bad things happen if you invoke it w.o. using new. This type of coding is NOT recommended. d. Apply invocation pattern Every function has an apply method. The apply method actually allows you to set the value of this. apply takes 2 parameters – the first is the value of this and the second is an array of arguments for the function. Example: var arr=[3,4]; var sum=add.apply(null,arr); //sum is 7 //Now we make an object statusObject with a status property – //but no get_status method. //Even tho’ statusObject doesn’t have a get_status method, we can //use apply to invoke get_status on statusObject. var statusObject = { status: “A-OK” }; var stt= Quo.prototype.get_status.apply(statusObject); //stt is “A-OK” My comment – WOW! I can take a method in any function or object (here Quo) and grab one of its methods via the prototype --- and then apply it. 18. The arguments array-like parameter If you have a function myfunc and call it with a list of parameters myFunc(x1, x2, .., xk) then inside myFunc there is arguments[ ] which has a length and which you can index thru. (arguments[ ] looks like an array,but it isn’t really one.) Somewhere I have read that it is dangerous to use, but here is an Example var listThem = function( ){ for (i=0; i < arguments.length; i++) alert(aguments[i]); } You could also use this to add up an arbitrary list of numbers, etc. 19. Return As noted in the function notes, every function returns either the specified value or undefined or (for a constructor with the new invocation) the new object created (i.e. this).