Skip to content

Instantly share code, notes, and snippets.

@gerard-morera
Last active January 21, 2016 23:55
Show Gist options
  • Save gerard-morera/9e694f6951074c3ef06e to your computer and use it in GitHub Desktop.
Save gerard-morera/9e694f6951074c3ef06e to your computer and use it in GitHub Desktop.
Javascript notes
--------------Scope----------------
---localScope---
A local scope refers to any scope defined past the global scope.
If I define a function and create variables inside it, those
variables becomes locally scoped.
// Scope A: Global scope out here
var myFunction = function () {
// Scope B: Local scope in here
};
---functionScope---
All scopes in JavaScript are created with Function Scope only,
they are not created by for or while loops or expression
statements like if or switch. So, New functions = new scope
// Scope A
var myFunction = function () {
// Scope B
var myOtherFunction = function () {
// Scope C
};
};
---lexicalScope---
Inner functions have access to the scope of the outer ones.
var foo = function () {
var a = 3, b = 5;
var bar = function () {
var b = 7, c = 11;
// At this point, a is 3, b is 7, and c is 11
a += b + c;
// At this point, a is 21, b is 7, and c is 11
};
// At this point, a is 3, b is 5, and c is not defined
bar();
// At this point, a is 21, b is 5
};
-------------Hoisting---------------
function declarations and variable declarations
are always moved invisibly to the top of their containgin
scope by js interpleter. Function para,emters and
language defined names are already there.
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
--------------closure----------------
Inner functions get access to the parameters and
variables of the functions they are defined within.
var sayHello = function (name) {
var text = 'Hello, ' + name;
return function () {
console.log(text);
};
};
sayHello('Todd');
// nothing happens, no errors, just silence...
// so:
var helloTodd = sayHello('Todd');
helloTodd();
// will call the closure and log 'Hello, Todd
That function defines a value variable. That
variable is always available to the increment and
getValue methods, but the function’s scope keeps
it hidden from the rest of the program
var myObject = function () {
var value = 0;
return {
increment: function (inc) {
value += typeof inc === 'number' ? inc : 1;
},
getValue: function () {
return value;
}
};
}();
Here we are not assigning a function to myObject but
assigning the result of invoking that function.
The function returns an object containing two
methods, and those methods continue to enjoy the
privilege of access to the value variable.
--------------closure----------------
var quo = function (status) {
return {
get_status: function () {
return status;
}
};
};
// Make an instance of quo.
var myQuo = quo("amazed");
document.writeln(myQuo.get_status( ));
This quo function is designed to be used without the
new prefix, so the name is not capitalized. When we
call quo, it returns a new object containing a
get_status method. A reference to that object is
stored in myQuo. The get_status method still has
privileged access to quo’s status property even though
quo has already returned. get_status does not have
access to a copy of the parameter; it has access to
the parameter itself. This is possible because the
function has access to the context in which it was
created. This is called closure.
--------------closure----------------
var fade = function (node) {
var level = 1;
var step = function () {
var hex = level.toString(16);
node.style.backgroundColor = '#FFFF' + hex + hex;
if (level < 15) {
level += 1;
setTimeout(step, 100);
}
};
setTimeout(step, 100);
};
fade(document.body);
---------------This-----------------
The this reference ALWAYS refers to (and holds the value
of) an object.
Each scope binds a different value of this depending on
how the function is invoked.
var myFunction = function () {
console.log(this);
// this = global, [object Window]
};
myFunction();
-----
var myObject = {};
myObject.myMethod = function () {
console.log(this);
// this = Object { myObject }
};
----
$("button").click (function (event) {
// $(this) will have the value of the button ($("button"))
​ // object​ because the button object invokes the click () method​
console.log ($ (this).prop ("name"));
});
----
There are a few scenarios where this does not have the
value of the invoking object.
1. this when used in a method passed as a callback
var user = {
data:[
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],
clickHandler:function (event) {
var randomNum = ((Math.random () * 2 | 0) + 1) - 1;
// random number between 0 and 1​
// This line is printing a random person's name and age from
//the data array​
console.log (this.data[randomNum].name + " " + this.data[randomNum].age);
}
}
// The button is wrapped inside a jQuery $ wrapper, so it
//is now a jQuery object​
// And the output will be undefined because there is no
//data property on the button object​
$ ("button").click (user.clickHandler);
// Cannot read property '0' of undefined
In the code above, since the button ($(“button”)) is an
object on its own, and we are passing the user.clickHandler
method to its click() method as a callback, we know that
this inside our user.clickHandler method will no longer
refer to the user object
SOLUTION:
$("button").click (user.clickHandler.bind (user));
---
2. this inside closure
Closures cannot access the outer function’s this variable by
using the this keyword because the this variable is
accessible only by the function itself, not by inner functions.
var user = {
tournament:"The Masters",
data :[
{name:"T. Woods", age:37},
{name:"P. Mickelson", age:43}
],
clickHandler:function () {
// the use of this.data here is fine, because
// "this" refers to the user object, and data is a
// property on the user object.​
SOLUTION: var theUserObj = this;
this.data.forEach (function (person) {
// But here inside the anonymous function (that we pass
// to the forEach method), "this" no longer refers to
// the user object.​
// This inner function cannot access the outer function's
// "this"​
console.log ("What is This referring to? " + this);
//[object Window]​
console.log (person.name + " is playing at " + this.tournament);
// T. Woods is playing at undefined​
// P. Mickelson is playing at undefined​
SOLUTION: console.log (person.name + " is playing at " + theUserObj.tournament);
})
}
}
--------ChangeScopeWith------------
----.call();.apply();.bind()-------
var links = document.querySelectorAll('nav li');
for (var i = 0; i < links.length; i++) {
(function () {
console.log(this);
}).call(links[i]);
}
IN CONTRUCTION
-------------Hoisting---------------
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);
-------------Hoisting---------------
var x = 1;
console.log(x); // 1
if (true) {
var x = 2;
console.log(x); // 2
}
console.log(x); // 2
-------------Hoisting---------------
function foo() {
var x = 1;
if (x) {
(function () {
var x = 2;
// some other code
}());
}
// x is still 1.
}
-------------Hoisting---------------
the assignment portion of the declaration are not
hoisted.
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
--------------callbacks----------------
sYncronous way:
request = prepare_the_request();
response = send_request_synchronously(request);
display(response);
asyncronous way:
request = prepare_the_request();
send_request_asynchronously(request, function (response) {
display(response);
});
We pass a function parameter to the send_request_asynchronously
function that will be called when the response is available.
-----------------Object-----------------
The simple types of JavaScript are numbers, strings, booleans
(true and false), null, and undefined. All other values are
objects. Numbers, strings, and booleans are object-like in
that they have methods, but they are immutable. Objects in
JavaScript are mutable keyed collections. In JavaScript, arrays
are objects, functions are objects, regular expressions are
objects, and, of course, objects are objects.
Every object is linked to a prototype object from which it can
inherit properties. All objects created from object literals
are linked to Object.prototype, an object that comes standard
with JavaScript.
-------------ObjectCreation---------------
Three ways to create objects:
var newObject = {};
var newObject = object.create( Object.prototype );
var newObject = new Object ();
-------------
Four ways in which keys and values can then be assigned to
an object:
1. Dot syntax
// Set properties
newObject.someKey = "Hello World";
// Get properties
var value = newObject.someKey;
2.Square bracket syntax
// Set properties
newObject["someKey"] = "Hello World";
// Get properties
var value = newObject["someKey"];
3.Object.defineProperty
// Set properties
Object.defineProperty( newObject, "someKey", {
value: "for more control of property's behavior",
writable: true,
enumerable: true,
configurable: true
});
( to be a bit more readable: )
var defineProp = function ( obj, key, value ){
var config = {
value: value,
writable: true,
enumerable: true,
configurable: true
};
Object.defineProperty( obj, key, config );
};
4. Object.defineProperties
// Set properties
Object.defineProperties( newObject, {
"someKey": {
value: "Hello World",
writable: true
},
"anotherKey": {
value: "Foo bar",
writable: false
}
});
-----------BasicConstructors------------
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
this.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
}
//Instantation
var civic = new Car( "Honda Civic", 2009, 20000 );
* Problems of this aprox:
- Makes inheritance difficult
- toString() is reefined for each of the new objects created
usig the Car contructor.
----Prototypes----
function Car( model, year, miles ) {
this.model = model;
this.year = year;
this.miles = miles;
}
Car.prototype.toString = function () {
return this.model + " has done " + this.miles + " miles";
};
// Usage:
var civic = new Car( "Honda Civic", 2009, 20000 );
---ObjectLiterals---
There should be no comma used after the final name/value
pair in the object as this may result in errors.
var myObjectLiteral = {
variableKey: variableValue,
functionKey: function () {}
};
Outside of an object, new members may be added to it using
assignment:
myObjectLiteral.property = "someValue";
-----------------Module------------------
We can use functions or closures to make modules. A module
is a function or object that pressents an interface but hides
its state and implementations.
var MODULE = (function () {
var my = {},
privateVariable = 1;
function privateMethod() {
// ...
}
my.moduleProperty = 1;
my.moduleMethod = function () {
// ...
};
return my;
}());
we’ve declared a global module named MODULE, with two public
properties: a method named MODULE.moduleMethod and a
variable named MODULE.moduleProperty. In addition, it
maintains private internal state using the closure of the
anonymous function.
----------TheModulePattern-----------
The Module pattern was originally defined as a way to provide
both private and public encapsulation for classes in conventional
software engineering.
In JavaScript, the Module pattern is used to further emulate
the concept of classes in such a way that we are able to
include both public/private methods and variables inside a
single object, thus shielding particular parts from the
global scope. With this pattern, only a public API is returned,
keeping everything else within the closure private.
var testModule = (function () {
var counter = 0;
return {
incrementCounter: function () {
return counter++;
},
resetCounter: function () {
console.log( "counter value prior to reset: " + counter );
counter = 0;
}
};
})();
// Increment our counter
testModule.incrementCounter();
// Check the counter value and reset
testModule.resetCounter();
Here, other parts of the code are unable to directly read the
value of our incrementCounter() or resetCounter(). The counter
variable is actually fully shielded from our global scope so
it acts just like a private variable.
---------
var myNamespace = (function () {
var myPrivateVar, myPrivateMethod;
// A private counter variable
myPrivateVar = 0;
// A private function which logs any arguments
myPrivateMethod = function( foo ) {
console.log( foo );
};
return {
// A public variable
myPublicVar: "foo",
// A public function utilizing privates
myPublicFunction: function( bar ) {
// Increment our private counter
myPrivateVar++;
// Call our private method using bar
myPrivateMethod( bar );
}
};
})();
---------
var basketModule = (function () {
// privates
var basket = [];
function doSomethingPrivate() {
//...
}
function doSomethingElsePrivate() {
//...
}
// Return an object exposed to the public
return {
// Add items to our basket
addItem: function( values ) {
basket.push(values);
},
// Get the count of items in the basket
getItemCount: function () {
return basket.length;
},
// Public alias to a private function
doSomething: doSomethingPrivate,
// Get the total value of items in the basket
getTotal: function () {
var q = this.getItemCount(),
p = 0;
while (q--) {
p += basket[q].price;
}
return p;
}
};
})();
basketModule returns an object with a public API we can use.
basketModule.addItem({
item: "bread",
price: 0.5
});
basketModule.getItemCount();
basketModule.getTotal()
TO CHECK:
augmentation, cloning and inheritance
http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html
http://rmurphey.com/blog/2009/10/15/using-objects-to-organize-your-code/
-------------Functions-------------
Functions in JavaScript are objects. Function objects are
linked to Function.prototype (which is itself linked to
Object.prototype). Every function is also created with two
additional hidden properties: the function’s context and the
code that implements the function’s behavior.
Since functions are objects, they can be used like any other
value. The thing that is special about functions is that they
can be invoked.
There is no run- time error when the number of arguments and
the number of parameters do not match. If there are too many
argument values, the extra argument values will be ignored.
If there are too few argument values, the undefined value will
be substituted for the missing values.
When a function is not the property of an object, then it is
invoked as a function. When a function is invoked with this pattern,
this is bound to the global object.
--------------------
inheritance
In classical languages, objects are instances of classes, and a class
can inherit from another class. JavaScript is a prototypal language,
which means that objects inherit directly from other objects.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment