Javascript Notebook
  • Introduction
  • Intro to JavaScript
    • Section 1 - Getting Started
    • Section 2 - Execution Contexts and Lexical Environements
    • Section 3 - Types and Operators
    • Section 3 Part 2 - Closures and Callbacks
    • Section 4 - Objects and Functions
    • Section 5 - Object Oriented Javascript and Prototypal Inheritance
    • Section 6 - Building Objects
    • Section 7 - Odds and Ends
    • Section 8 - Examining Famous Frameworks and Libraries
    • Section 9 - Let's Build a Framework or Library!
  • Midterm Review
  • Final Review
  • jQuery
    • Section 1 - Selectors
    • Section 2 - Events
    • Section 3 - Effects
  • Node.js
    • The Node Core
    • Modules, Exports, and Require
    • Events and the Event Emitter
    • Databases and SQl
  • D3.js
    • Diving In
    • Bar Chart
    • Creating A Complex Bar Chart
Powered by GitBook
On this page
  • Objects and Functions
  • Objects and Object Literals
  • Faking Namespaces
  • JSON and Object Literals
  • Functions are Objects
  • Function statements and Function Expressions
  • Value vs Reference
  • Objects Functions and This
  • Arrays
  • Looping through arrays
  • Arguements and Spread

Was this helpful?

  1. Intro to JavaScript

Section 3 - Types and Operators

in# Section 3 - Types and Operators

Objects and Functions

  • Constructing a new object

        var person = new Object();

        //defining new properties
        person['firstname'] = 'dan';
        person['lastname'] = 'mak';

        var firstnameperson = 'firstname';
        var lastnameperson = 'lastname';


        console.log(person); //Object
        console.log(person[firstnameperson]); //dan
        console.log(person[lastnameperson]); //mak
        console.log(person[firstname]); // doesnt work
  • Whats happening here:

    • [] is an operator that accesses a property of an object

    • = is us assigning a property.

    • [] used to modify, add, or access an objects property.

    • notice that firstnameperson and lastnameperson are used to dynamically define the properties of our object. Interestingly, trying to access more directly by the property I defined didnt seem to work.

  • A more convenient way of accessing a member object property.

    //similiar to C++
    console.log(person.firstname);
  • Why is this can be powerful:

  • We can define objects within other objects.

    //continued

    person.address = new Object();
    person.address['street'] = 'smithway';
    person.address['city'] = 'antelope';
    person.address['state'] = 'CA';
  • What we have done is defined an object within another object

    • AKA subobjects or child objects

  • This is pretty cool because it allows us to structure and organize properties in a very efficient way.

  • We can use this to build larger scaled models.

  • The syntax is very nice.

    //printing to console
    console.log(person.address.street);
    console.log(person.address.city);
    console.log(person.address.state);


    //alternative printing method
    console.log(person["address"]["street"]);
    console.log(person["address"]["city"]);
    console.log(person["address"]["state"]);
  • An alternative, possibly easier way of assigning object properties

    person.address.street = 'smithway';
    person.address.city = 'antelope';
    person.address.state = 'CA';
  • Dot operators are ususally preferred.

Objects and Object Literals

    //this is an object literal
    var person = {};
  • This is performs that same thing as object new.

  • There are different ways of doing things. So what does this mean?

  • I think this is the better way to do thing when beginning to initialize things. Watch.

    var person { firstname: 'dan' };
  • Here we've constructed new object, a name value pair all on a single line.

  • The other approaches studied earlier, are probably better as commands; that letting the program modify things on the spot.

    // a larger scale model

    var Tony = {
        firstname: 'dan',
        lastname: 'mak',

        address: {
            city: 'smith',
            state: 'CA',
            street: 'smithway'
        }

    };
  • easy peezy

  • We can write functions that utalize objects.

    var dan = {
        firstname: 'dan',
        lastname: 'mak',

        address: {
            city: 'smith',
            state: 'CA',
            street: 'smithway'
        }

    };

    function greet(person) {
        console.log("hello " + person.firstname);
    };


    greet(dan);
  • Whats happening here:

    • An object is created using literals

    • A function which, and I have to get used to this, takes ANY variable (dynamically defined), that greets a person.

    • greet(Tony) passes in the OBJECT directly as a variable, so "hello" + Tony.firstname is outputed.

  • We can also create objects on the fly:

    greet({
        firstname: 'mary',
         lastname: 'h3h3'
    });
  • May have to get used to this. But Mary is a new object created on the function call. We passed in a function an object that was what?

  • function greet(person) takes a person, which is dynamically defined, and firstname is defined in Tony. Why does this work?

    console.log(dan); //object
    console.log(dan.firstname); //dan
    console.log(mary.firstname); // error
  • My understanding of this so far:

    • When we pass in a variable to a function, because everything is handled dynamically, it is created on the fly. So greet('dan'), is no different than greet ([some object]). Both are objects -> is just that strings are more primitive and easier understood. But objects you've defined have properties, so it complicates things a bit.

  • I think I got it now. This helped clear things up for me. Lets take a look at this again, slightly modified. Variable names dont make sense, but whatever - the point will get across.

    var dan = {
        firstname: 'dan',
        lastname: 'mak',

        address: {
            city: 'smith',
            state: 'CA',
            street: 'smithway'
        }

    };

    function greet(person) {
        console.log("hello " + person.address.city);
    };


    greet(dan); // hello smith

    greet({
        firstname: 'mary',
         lastname: 'h3h3'

    }); // ERRRRRRRRRRRRRRRRRRRRRRRRRROR


    console.log(dan.address.city); // hello smith
  • So what this means:

    • dan is the name of our object. But does not always have to be dan. Something more abstract like person would have made more sense. Because dan was constructed as the object originally, greet(dan) is understood because the object properties have been defined.

    • greeting mary, on the other hand does not because even though we've defined a NEW object that HAS NOT overwritten the previous (dan), we have not defined a property for that new object that the function understands (person.address.city).

    • To fix this, we define the property.

    greet({
        firstname: 'mary',
         lastname: 'h3h3',
         address: {
             city: 'smithhhhhhy'
         }

    }); // hello smithhhhhhy
  • And to prove that it has not become overwritten, we can greet dan again.

    //continued
    greet(dan); // hello smith
  • The most important take away from this I think is that object can be created very quickly, and in quiet high level manner. For example, in greeting mary, we are not talking about the properties from object dan. Rather, we are really defining an entirely new object that may or may not have the same properties as dan.

Faking Namespaces

  • A namespace is a container for variables and functions. Consider

    var greet = 'hello';
    var greet = 'hola';

    //overwrite (bad)
    console.log(greet); // hola
  • To avoid these kinds of conflictions, lets write a container, or object that specifies our information down.

    //fix

    var english = {};
    var spanish = {};

    english.greet = 'hello';
    spanish.greet = 'hola';

    console.log(english.greet ); // hello
    console.log(spanish.greet); // hola
  • Or if we want to have things even more compact, we can do this:

    //fix

    var english = {
        greetings: {
            greet: 'hello'
        }
    };
    var spanish = {};

    english.greet = 'hello';

    console.log(english.greetings.greet ); // hello
  • This is want I was refering to earlier about global variables. This is good practice because it keeps them where they belong rather than in the global namespace.

JSON and Object Literals

  • AKA js object notation

  • In the earlier days, data was sent across the internet using XML. This was however, inefficient, and had a lot of unnessessary characters, and hence more bandwidth required for this characters. The solution was to take the way js objects where sent. So we now send data via the JSON format. Looks like:

    {
        "firstname": "dan",
        "isCool": true
    }
  • Because JSON is so similiar to js, js has some built in capabilities related to JSON. And we can do so like this:

    var myObject = {
        firstname: 'dan',
        isCool: true
    }

    console.log(JSON.stringify(myObject));
  • The JSON file will be to what you see above.

  • Furthermore, we can do the reverse. Note that the format cannot have \n characters.

    var backtoObject = 
    JSON.parse(
    '{ "firstname": "dan", "isCool": true }'
    )


    console.log(backtoObject);
  • But we will notice that backtoObject will be the same as myObject.

  • JSON is a popular method of just sending over data - it is used interchangably with the term AJAX.

    • It also cannot contain functions, because it is not nessessarly data per-say.

Functions are Objects

  • Fundamental concept

  • First class functions: everything you can do with other types, you can do with functions.

    • Special type of object

    • Stored in memory

    • Functions dont require a name, aka an anoyomous function

    function greet(name) {
        console.log('hello ' + name);
    }

    greet.language = 'english';

    console.log(greet.language) //english
  • Consider this. We've defined a property to a function, and the notation we've used was the same as when treating other objects. And we can prove that the property is in memory.

Function statements and Function Expressions

  • The difference between expressions are statements

  • An expression returns a value. For example.

    var a = 1 + 2; // expression returns 3, assigns to a
    2 / 4; // console expression
  • Statements dont return anything. But they can evaluate expressions. For example

    if (a === '3') {...};
  • Functions can be statments as well. Basically, from from C, they return 'void'

    function greet(name) {
        console.log('hello ' + name);
    }
  • Is stored in memory, but does not return a value.

  • Function Expressions:

  • Because functions are objects, we can do something like this

    var functionObject = function() {
        console.log('hello ' + name);
    }
  • This is what is known as an anoyomous function, because it does not contain a name property. Instead, functionObjects stores the memory location of function(). The function part is an expression because it results in a value.

  • And now as object, that has unique function properties, we can do something like this.

    functionObject('dan'); // hello dan
  • Note here that it was invoked about its declaration. While normally, we can call functions before they're delclaration, here because we are using the assignement operator, execution is handled after the memory allocation phase.

  • functionObject is undefined initially. The variable holds memory, but is not assigned anything only after its execution phase.

  • We can also do something really interesting.

    //begin with the basics
    function log(a) {
        console.log(a);
    }

    //taking primative forms
    log(3);
    log('hello');

    //self defined
    log( {stuff: 'something' });    
  • And now even function objects, which behave the same as literals.

    log (function() {
        console.log('something');
    });
  • Whats happening: variables are dynamic, we can pass in any kind of object.

  • This is useful because it is immediately invoked. Why pass it into a variable when you are only going to use it once, for example.

    • It is also useful because an immediately unvoked function by nature also wraps around a new scope for the variables that are created within it.

    • We can use this trick in building safe modules, or wrapped classes that will not interfear with other variables.

  • Note the name is not nessessary for a function, but it can have it. It just does not have to.

  • Which means that we can do something like this...

    function log(a) {
        a();
    }

    log (function() {
        console.log('something');
    }); // something
  • Pretty crazy. Its like reversing the procedure. What we've done is constructed an object right on the fly,and passed it into a function call. That function took this object, and invoked it.

  • This is known as functional programming. We can treat anything as a variable. Everything essentially becomes an object.

Value vs Reference

  • It we are using a primative type, and we pass in that type to another function, then we are copying the variable, because we are using a new location.

    • Primative types (or single value types) are automatically copied, and objects are passed by reference.

    • That mean there is a single entity or pointer address for objects, and that any changes within these object will affect all other objects that are pointed or derived from it.

  • New location in memory is created by value.

  • In addition copies are independent. There references do not affect one another, because they don't have any. Instead, they are treated are individual locations in memory.

  • References, on the other hand, are like desktop shortcuts. You have one real application, and as many shortcuts as you want to that particular real application. This way, we avoid wasting memory.

    function hello(a) {
        console.log(a);
    }

    var a = 3;
    var b;

    //copy
    b = a;
    a = 2;

    hello(a) // 2
    hello(b) // 3
  • The most important thing to note about copies, is that their addresses are unique. And this is what defines a value as unique.

  • One more thing to point out about references. If we delete the real deal, the other references will have broken links, so it would not have any access.

  • Assignment to an object uses reference. All object interact by reference.

    var a = {
        stuff: 'stuff'
    };

    // by reference automatically
    b = a;
    b.stuff = 'newstuff lol'

    console.log(b); // newstuff lol
    console.log(a); // newstuff lol


    a.stuff = 'newerrrr stuff';


    console.log(b); // newerrrr stuff
    console.log(a); // newerrrr stuff
  • Here, because objects are passed by reference, it does not matter what reference we use - the important thing to note is that they are the same object. Modify one, and you modify the other as well.

  • So objects are essentially single units in space and from what I known right now, there is no way to create a copy of that object like you can do with C. To get another object that is different you have to construct a new one.

  • Keyword: immutate. To change something. Here, we mutate our object.

  • We can demonstrate pass by reference through a function call, we do something like this:

    // function that modifies an object <-- reference
    function mutate(object) {
        object.stuff = 'mutated son';
    }

    mutate(a);

    console.log(b); // mutated sonf
    console.log(a); // mutated son
  • If we do this:

    //continued
    c = {stuff:'object'};

    console.log(b); // mutated son
    console.log(c); // object
  • Then c is a new object because their link was not established (c was not set = b).

  • Other programming language give us the option of deciding whether or not something should be passed by reference or by value. Js does not give us this option. Objects are references and primatives are by value.

Objects Functions and This

  • What is this? Its a pointer to an object that can change depending on the circumstance.

  • We've already identified that this under the global enviroment is the window object.

    console.log(this); // window object 
  • The first thing to notice is the even functions' 'this' will all access the global window object namespace.

        console.log(this) // window


        function hello(){
            console.log(this); // window
        }

        var a = function() {
            console.log(this); // window
        }

        hello();
        a();
  • And we can add an object property to this namespace.

    function hello(){
        console.log(this); // window
        this.supWindow = 'added to global namespace';
    }

    console.log(supWindow);
  • So the question now is how can we modify create a new context for 'this' other than the global one.

  • The answer is when we create a new object.

    var newObject = {
        name: 'dan',
        last: 'mak',
        log: function() {
            console.log(this);
        }
    }

    console.log(newObject); // newbject
    newObject.log(); // newObject
  • First thing to note is the we've invoked an annoymous function through an object. This, in this case was created under a new execution context, so now points to a new namespace because of the context it was created under. This is useful because we can use this very convieniently rather than having to create an new object simply to modify something.

  • Sigh... the mistakes I've been making.

    var newObject = {
        name: 'dan',
        last: 'mak',
        log: function() {
            console.log(this);
            this.name = 'not dan';
        }
    }

    console.log(newObject); // newbject
    newObject.log(); // newObject

    function printName(object) {
        console.log(object.name);
    }

    printName(newObject); // not dan
  • You see? Every new object has a this, within its own context, and we can use it to modify object properties.

  • This next bit identifies what others feel is wrong with js.

    var newObject = {
        name: 'dan',
        last: 'mak',
        log: function() {

            this.name = 'not dan';

            var a = function() {
                this.name = 'sam';
            }
            a();
        }
    }


    function printName(object) {
        console.log(object.name);
    }

    printName(newObject); // dan

    newObject.log();

    printName(newObject); // not dan
  • Whats is going on here? Is this not pointing to the same object? I would have expected sam.

  • As it turns out, every internal function of an object has this same kind of problem. Maybe its because of the concept of functional programming, and how functions are treated ecactly like objects.

  • 'a' object, i believe created a new context for this. So this.name was a new property defined for the new object.

    var newObject = {
        name: 'dan',
        last: 'mak',
        log: function() {
            var self = this;
            self.name = 'not dan';

            var a = function() {
                self.name = 'sam';
            }
            a();
        }
    }


    function printName(object) {
        console.log(object.name);
    }

    printName(newObject); // dan

    newObject.log();

    printName(newObject); // sam
  • To fix this, we have to understand how references work. var self has stored a reference to the object this, which was created under the context of newObject. Now, whenever we reference self, we will be referencing newObject's properties. Now, executing a() will indirectly modify newObjects' name.

  • Using this, modifies the context in which is was created under.

Arrays

    var array = new Array();

    var array2 = [
        false,
        'dan',
        {
            name:'dan',
            last:'mak'
        },
        function opMang(anything) {
            console.log(anything + 'cool');
        }
    ];


    console.log(array2); // container listing
    console.log(array2[1]); // dan
    array2[3](array2[2].name); // dancool
  • First thing to notice is that array can hold any kind of objects in their container. Even functions, objects. In addition, anything within an array can be invoked whenever.

  • They just have to be accessed, and called.

  • The syntax comes pretty simple too.

Looping through arrays

var arr = [];

arr.push(1);
arr.push(2);
arr.push(function() {
  console.log("hello");
})

arr[2](); // hello
arr.forEach(function(i) {
  console.log(i);
})

// 1
// 2
// [Function]

Arguements and Spread

  • arguements aka parameters.

  • One very interesting thing about functions in javascript is that their arguements or parameters still have their memory allocated in the first phase, even if they are not called.

    function greet(first,last,middle) {
        console.log(first);
        console.log(last);
        console.log(middle);
    }

    greet(); // undefined // undefined // undefined
  • And even if we go provide an arguement, js is flexible enough allow you to do these things. And the order

    greet('dan'); // dan // undefined // undefined
  • And when we want we can coerse to a default value - like before (albiet this doesnt introduce any new concepts)

    function greet(first,last,middle) {
    first = first || 'sam';

    console.log(first);
    console.log(last);
    console.log(middle);
    }

    greet(); // sam // undefined // undefined

    greet('dan'); // dan // undefined // undefined
  • Now for the arguements keyword.

  • What the arguements keyword does is it lists the arguements that where passed to it.

    function greet(first,last,middle) {
        first = first || 'sam';

        console.log(first);// dan
        console.log(last);// mak 
        console.log(middle);// andrey
        console.log(arguements) // ['dan','mak','andrey']
    }

    greet('dan', 'mak', 'andrey');  
  • Notice that it looks very similiar to an array. Although it is not exactly an array - it acts enough as an array to the point where we can use it as an array under most circumstances.

  • And one practical application to this would look like something to this:

    function greet(first,last,middle) {
        first = first || 'sam';

        if (arguments.length == 0) {
            console.log("no arguments");
            return;
        }

        console.log(first);// dan
        console.log(last);// mak 
        console.log(middle);// andrey
        console.log(arguments) // ['dan','mak','andrey']
    }

    greet(); // no arguments
    greet('dan'); // dan // undefined // undefined
    greet('dan', 'mak', 'andrey');  
  • Where arguments considers undefined to not be an arguement.

  • An like arrays, they can be accessed directly;

    console.log(arguments[0]); // dan
PreviousSection 2 - Execution Contexts and Lexical EnvironementsNextSection 3 Part 2 - Closures and Callbacks

Last updated 5 years ago

Was this helpful?