Skip to content

Instantly share code, notes, and snippets.

@rmurphey
Created March 18, 2011 17:57

Revisions

  1. rmurphey created this gist Mar 18, 2011.
    391 changes: 391 additions & 0 deletions functions-objects-context.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,391 @@
    /**
    * FUNCTIONS
    **/

    /**
    * Functions create closures; variables defined
    * inside of them are accessible inside the
    * function, and to any functions that were
    * defined within the same scope.
    **/

    $(document).ready(function() {

    var sayItOutside = (function(){

    var myVar = 'hello world',

    sayIt = function() {
    console.log(myVar);
    };

    myVar = 'a new value';

    return sayIt;

    }());

    // sayItOutside(); // 'a new value'
    // console.log(myVar);

    });


    /**
    * Functions are first class objects; we can move
    * them around just like we do with other types
    * of objects.
    **/

    $(document).ready(function() {

    $('#myDiv').click(function(e) {
    // console.log(e.target);
    });

    var repeater = function(fn, repeat) {
    while (repeat--) { fn(); }
    };

    // repeater(function() { console.log('hello'); }, 5);

    });


    /**
    * Functions can create other functions.
    **/

    $(document).ready(function() {

    var makeRepeater = function(fn, repeat) {
    return function() {
    while (repeat--) {
    fn();
    }
    };
    };

    var newFunction = makeRepeater(function() { console.log('hello'); }, 5);
    newFunction();
    });

    /**
    * Inside a function, you have access to 'arguments',
    * an array-like object that contains a list of the
    * arguments passed to the function.
    **/

    $(document).ready(function() {

    $('#myDiv').one('click', function() {
    // console.log(arguments);
    });

    });



    /**
    * OBJECTS
    **/


    /**
    * Objects can have properties and methods.
    **/

    $(document).ready(function() {

    var myObj = {
    paul : 'Google',
    adam : 'Bocoup',
    alex : 'BazaarVoice',
    sayHi : function() {
    console.log('hello');
    }
    };

    });


    /**
    * Inside an object method, 'this' refers to
    * the object that owns the method by default.
    **/

    $(document).ready(function() {

    var myObj = {
    paul : 'Google',
    adam : 'Bocoup',
    alex : 'BazaarVoice',

    sayHi : function(person) {
    var company = this[person] || 'no one';
    console.log(
    'Hello,',
    person,
    ', you work for',
    company,
    '.'
    );
    }
    };

    // myObj.sayHi('paul');

    });

    /**
    * The module pattern is the goodness of closures
    * combined with the goodness of objects.
    **/

    $(document).ready(function() {

    var myModule = (function(){

    // set up all the variables you'll need for
    // the module's functionality
    var privateVar = 'secret',
    publicVar = 'not secret',
    tellSecret = function() {
    console.log(privateVar);
    },
    setSecret = function(str) {
    if (str.length < 6) {
    console.log('not secret enough!');
    return;
    }
    privateVar = str;
    };

    // decide what to expose as a public API
    // to the module.
    return {
    tellSecret : tellSecret,
    setSecret : setSecret,
    publicVar : publicVar
    };

    }());

    // myModule.setSecret('new');

    });

    /**
    * Objects can share functionality by sharing
    * a "prototype" -- in fact, jQuery.fn is just
    * shorthand for jQuery.prototype, which allows
    * all of the methods available on jQuery objects
    * to be shared across objects.
    */

    $(document).ready(function() {

    var Person = function(first, last) {
    /**
    * Setting instance properties
    **/
    this.firstName = first;
    this.lastName = last;
    return this;
    };

    Person.prototype = {
    sayFirstName : function() {
    console.log(this.firstName);
    }
    };

    /**
    * Creating "instances" of Person
    **/
    var adam = new Person('adam', 'sontag'),
    rebecca = new Person('rebecca', 'murphey');

    // adam.sayFirstName();
    // rebecca.sayFirstName();
    });


    /**
    * Methods can be changed on individual instances
    * without affecting other instances.
    **/
    $(document).ready(function() {

    var Person = function(first, last) {
    this.firstName = first;
    this.lastName = last;
    return this;
    };

    Person.prototype = {
    sayFirstName : function() {
    console.log(this.firstName);
    }
    };

    var adam = new Person('adam', 'sontag'),
    rebecca = new Person('rebecca', 'murphey');

    /**
    * Changing the definition of an instance method
    **/
    // rebecca.sayFirstName = function() {};

    // rebecca.sayFirstName();
    // adam.sayFirstName();

    });


    /**
    * ... Unless you want to affect other instances! In
    * which case, you should modify the prototype instead.
    **/
    $(document).ready(function() {

    var Person = function(first, last) {
    this.firstName = first;
    this.lastName = last;
    return this;
    };

    Person.prototype = {
    sayFirstName : function() {
    console.log(this.firstName);
    }
    };

    var adam = new Person('adam', 'sontag'),
    rebecca = new Person('rebecca', 'murphey');

    /**
    * Changing the definition of a protype method
    **/
    Person.prototype.sayFirstName = function() {
    console.log('i have no name');
    };

    // rebecca.sayFirstName();
    // adam.sayFirstName();
    });

    /**
    * We can also create new objects that share the same
    * prototype using Object.create, which can be created
    * where it is not available.
    **/

    $(document).ready(function() {

    if (typeof Object.create !== 'function') {
    Object.create = function (o) {
    function F() {}
    F.prototype = o;
    return new F();
    };
    }

    var Person = {
    sayName : function() {
    console.log(this.firstName, this.lastName);
    }
    };

    var adam = Object.create(Person);

    $.extend(adam, {
    firstName : 'adam',
    lastName : 'sontag'
    });

    // console.log('adam is', adam);
    });



    /**
    * CONTEXT
    **/

    /**
    * We can change the meaning of 'this' inside
    * of a function. In fact, jQuery does exactly
    * that in order to have 'this' refer to the
    * element that triggered an event handler.
    *
    * To change the context in which a function runs --
    * that is, to change the meaning of 'this',
    * we use .call() or .apply().
    **/

    $(document).ready(function() {

    var p = {
    firstName : 'paul',
    lastName : 'irish'
    },

    a = {
    firstName : 'alex',
    lastName : 'sexton'
    },

    sayHi = function(greeting, question) {
    console.log(greeting, this.firstName, this.lastName, question);
    };

    /**
    * .apply takes a scope object and an array of arguments
    * to pass to the function that is being called. The
    * arguments in the array will be passed to the function
    * as individual arguments.
    **/

    // sayHi.apply(p, [ 'Hello', 'How are you today?' ]);

    /**
    * .call takes a scope object and zero or more additonal
    * arguments. Additonal arguments will be passed to the
    * function as individual arguments.
    **/

    // sayHi.call(a, 'Greetings', 'Is it so just cloud?' );

    });

    /**
    * jQuery offers the utility method $.proxy, which
    * lets you pass a function and the scope in which
    * the function should run.
    *
    * Be careful, though: the order of the arguments
    * passed to $.proxy can be confusing.
    *
    * $.proxy(context, 'methodName');
    * $.proxy(function() { ... }, context);
    *
    * This means we can easily change the meaning of this
    * inside an event handler, where this normally refers
    * to the element to which the handler was bound.
    **/

    $(document).ready(function() {

    var myObj = {
    thingToSay : 'it worked!',
    sayIt : function() {
    console.log('The thing I want to say is', this.thingToSay);
    }
    };

    // myObj.sayIt();
    // $('#myDiv').click(myObj.sayIt);
    // $('#myDiv').click($.proxy(myObj, 'sayIt'));

    });