// 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 well
function 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]
From http://abdulapopoola.com/2013/12/15/a-peek-into-javascripts-array-prototype-map-and-jquery-map/
# Passing by reference # Say I want to share a web page with you. ## Reference ## - If I refer you to the URL, I'm passing by reference. You can use that URL to see the same web page I can see. If that page is changed, we both see the changes. If you delete the URL, all you're doing is destroying your reference to that page - you're not deleting the actual page itself. - The called functions' parameter will be the same as the callers' passed argument (not the value, but the identity - the variable itself - Variables that hold reference types actually hold a reference to a location in memory (on the heap) ## Value ## - If I print out the page and give you the printout, I'm passing by value. Your page is a disconnected copy of the original. You won't see any subsequent changes, and any changes that you make (e.g. scribbling on your printout) will not show up on the original page. If you destroy the printout, you have actually destroyed your copy of the object - but the original web page remains intact. - The called functions' parameter will be a copy of the callers' passed argument.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,y
var 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];
} // ...
}
Source: http://stackoverflow.com/questions/6396046/unlimited-arguments-in-a-javascript-function