// Returns undefined. No warning
return
{
status: true
};
// can be avoided by moving the bracket to the top line
return {
status: true
};- Reserved Words
- Most of the words are not used in the language
- Unicode
- Array == 'Object' && Null == 'Object'
- Eval()
- Don't use this - access to JS compiler and interpreter evaluates a string as though it were an expression and returns a result
- Improper use of eval opens up your code for injection attacks
- Debugging can be more challenging (no line numbers, etc.)
- The Constructor
- Fail to use "new" prefix and you clobber the global scope
- No way of checking for this issue
-
Object-like (they have methods), but are immutable
- Numbers, strings, booleans
-
Collections of name / value pairs, having a hidden link to Object.protoype
- Names: strings, Values: strings, numbers, booleans, & objects
-
Mutable keyed collections
-
Arrays, functions, regular expressions
-
Passed about by reference, never copied
-
Usually implemented as hashtables, so values can be retrieved quickly
-
Properties:
- Named values on objects ? FirstName: john - FirstName is a property
var I;
var properties = [
'first-name',
'middle-name',
'last-name',
'profession'
];
for (I = 0, properties.length; I +=1) {
document.writeln(propoerties[i] + ': ' +
another_stooge[properties[i]]);
}- Get the properties we want, without digging up the prototype chain
Delete another_stooge.nickname
# Functions # - Encloses a set of statements, and each function creates a new execution context (this) - Are objects - By default, return undefined - Linked to Function.prototype - Which is linked to Object.Prototype - Two additional properties: - Function's context (this) - Code that implements the function's behavior (arguments) - Also created w/ a prototype property - Independent of an object - If a value is a function, we consider it a method - Can access instance variables with this - Is on an object # Literal # - The name (is optional), can be used to call itself recursivelyvar add = function (a, b) {
Return a + b;
};function outer() {
return function () {
console.log("returning a function within a function");
}
}function outer() {
var name = "Bob";
function inner() {
Alert(name); // 'Bob'
}
return inner;
}
var something = outer();
something(); // 'Bob'var myObject = {
value: 0,
increment: function ( inc ) {
this.value += typeof inc === 'number' ? inc : 1;
}
};- Functions that get their object context from this are Public Methods
- Binding of this happens at time of invocation
myObject.double = function() {
var that = this ; // Workaround
var helper = function () {
That.value = add(that.value, that.value);
};
Helper();
};
myObject.double();Statement
// What we see
function funcName() {}
// Under the hood
var funcName = function funcName() {}Expression
// stores ref to anon function
var funcRef = function () {};
// stores ref to named fun
var fundRef = func funcName() {};var red = new Color(255, 0, 0);
var blue = {r:255, g:0, b:0}
// Outputs true
console.log(red instanceof Color);
// Outputs false
console.log(blue instanceof Color);
var Quo = (string) {
this.status = string;
};- Not recommended. A better style lies ahead.
var array = [3, 4];
var sum = add.apply(null, array); // sum is 7
var status {
Status: 'A-OK'
};
var status = Quo.prototype.get_status.apply(statusObject);
// status is "A-OK'var sum = function () {
var I, sum = 0;
For (I = 0; I < arguments.length; I +=1) {
Sum += arguments[i];
}
Return sum;
}Not really an array -- it's an array-like object Arguments has length property, but lacks all of the array methods
# Hoisting # - Using a function before you declare itHoisted(); // logs "foo"
function hoisted() {
Console.log("foo");
}- Function expressions are not hoisted though
notHoisted(); // Will not work
var notHoisted = function() {
Console.log("bar");
}(function(){ /* code */ }()); // Crockford recommends this one
(function(){ /* code */ })(); // But this one works just as wellfunction Container(param) {
function dec() {
if (secret > 0) {
secret -= 1;
return true;
} else {
return false;
}
}
this.member = param;
var secret = 3;
var that = this;
// privileged method
this.service = function () {
return dec() ? that.member : null;
};
}- Service is available to other objects & methods, but does not allow access to private members
- This is because of closures
- Public:
- Can be added at any time
- Function that uses this to access its object
function Constructor (…) {
this.membername = value;
}
Constructor.prototype.membername = value;Private:
function Constructor(…){
var self = this;
var membername = value;
function membername(…) {…}
}Privileged
function Constructor(…) {
this.membername = function(…) {…};
}(function(global) {
"use strict";
var MySingletonClass = function() {
if ( MySingletonClass.prototype._singletonInstance ) {
return MySingletonClass.prototype._singletonInstance;
}
MySingletonClass.prototype._singletonInstance = this;
this.Foo = function() {
// ...
};
};
var a = new MySingletonClass();
var b = MySingletonClass();
global.result = a === b;
}(window));
console.log(result);- Simply accessing variables outside of your immediate lexical scope creates a closure
- The local variables for a function — kept alive after the function has returned
- Inner function always has access to the vars & parameters of its outer function
- Have access to the outer function’s variable even after the outer function returns
- Store references to the outer function’s variables
if (typeof Object.create !== 'function') {
Object.create = function (o) {
function F() {}
F.prototype = o;
return new F();
};
}
newObject = Object.create(oldObject);From http://javascript.crockford.com/prototypal.html
## Method method ##function.prototype.method = function (name, func) {
this.prototype[name] = func;
return this;
};Use this method to add methods in Number, String, Function, Object, Array, RegExp. For example:
Number.method('integer', function () {...});
String.method('trim', function () {...});for(var name in obj) {
if (obj.hasOwnProperty(name)) {
}
}jQuery callback example
var numbers = [1,2,3,4],
squareNumbers = function (number) {
return number * number;
},
squares = $.map(numbers, squareNumbers);
console.log(squares);
//logs [1,4,9,16]Array.prototype.map callback example
var numbers = [1,2,3,4],
squares = numbers.map(squareNumbers);
console.log(squares);//logs [1,4,9,16]Passing by pointer is passing by reference - in the example above, the URL is a pointer to the resource Great tutorial on the two: http://www.leerichardson.com/2007/01/parameter-passing-in-c.html
# Setting default parameter values #function foo( a, b ) {
a = a || '123';
b = b || 55;
Print( a + ',' + b );
}
foo(); // prints: 123,55
foo('bar'); // prints: bar,55
foo('x', 'y'); // prints x,yvar html = ['aaa', 'bbb', 'ccc', ...].join('');// Create an anonymous function expression that gets invoked immediately,
// and assign its *return value* to a variable. This approach "cuts out the
// middleman" of the named `makeWhatever` function reference.
//
// As explained in the above "important note," even though parens are not
// required around this function expression, they should still be used as a
// matter of convention to help clarify that the variable is being set to
// the function's *result* and not the function itself.
var counter = (function(){
var i = 0;
return {
get: function(){
return i;
},
set: function( val ){
i = val;
},
increment: function() {
return ++i;
}
};
}());
// `counter` is an object with properties, which in this case happen to be
// methods.
counter.get(); // 0
counter.set( 3 );
counter.increment(); // 4
counter.increment(); // 5
counter.i; // undefined (`i` is not a property of the returned object)
i; // ReferenceError: i is not defined (it only exists inside the closure)It's like an array, but it's not an array. In fact it's so weird that you really shouldn't use it much at all. A common practice is to get the values of it into a real array:
The simple, straightforward way to turn arguments into an array is therefore
function foo() {
var args = [];
for (var i = 0; i < arguments.length; ++i) {
args[i] = arguments[i];
} // ...
}