More advanced notes on Crockford

advertisement
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).
Download