Javascript Primitives, Objects and Classes
Vagelis Papadogiannakis
Source Development
papas_source
The 6 types of Javascript primitives
Vagelis Papadogiannakis
Source Development
papas_source
How to create Primitives:
Easy. Assign it to a variable or a constant
Vagelis Papadogiannakis
Source Development
papas_source
var my_string = "I am a string";
const my_other_string = "0042"; // still a string
let my_number = 42;
const i_am_null = null;
All primitives are immutable. The variables that hold them, are not
my_string.toUpperCase();
// "A STRING"
console.log(my_string); // a string
function add_one(my_number){
my_number += 2; // a new var is created here!
}
console.log(my_number); // 2
add_one(my_number);
console.log(my_number); // still 2!
Variable Scope
Variable is available wherever it is declared
Vagelis Papadogiannakis
Source Development
papas_source
function fn(){
var num = 5; // function scope
let unused = 69; // block (=function) scoped
if (num === 5) {
let a = num + 2; // block scope
const b = num + a; // block scope
console.log(num, a, b); // 5, 7, 12
}
console.log(num); // 5
console.log(a); // ReferenceError: a is not defined
// because a is block scoped to the `if`
console.log(b); // We' ll never make it here :(
}
fn();
Hoisting
Declarations are moved to the top
Vagelis Papadogiannakis
Source Development
papas_source
console.log(x); // undefined
var x = 5;
// What the computer understands
var x;
console.log(x);
x = 5;
let is hoisted, too. With a little difference... TDZ
console.log(a);
let a = 2;
// ff: ReferenceError: can't
// access lexical declaration
// `a' before initialization
// ch: Uncaught ReferenceError:
// a is not defined
var x = 2;
function foo(){
console.log(x);
let x = 3;
}
foo();
// same error BUT...
// if let didn't hoist
// it would print "2"
enter
TEMPORAL
DEAD
ZONE
WAT?
Well, whenever control flow enters a new scope, all the let/const bindings belonging to the given scope are instantiated before any code inside of the given scope is executed aka "hoisted"
but may not be accessed in any way (this is why we get the referenceError) until the variable’s LexicalBinding is evaluated.
Javascript Objects
In JS almost everything is an Object
Vagelis Papadogiannakis
Source Development
papas_source
// literal
var o = {
name: 'papas'
};
// with constructor
var oo = new Object({
name:'papas'
});
console.log(o);
Arrays and Functions are also Objects
function inc(num) {
// do something
return num + 1;
}
console.log(inc.prototype);
Every Object has its `prototype`
Javascript Objects
How Prototypal Inheritance works
Vagelis Papadogiannakis
Source Development
papas_source
var Car = function(name){
this.name = name;
this.toString = function() {
return 'I am defined in the constructor! I am a ' + this.name;
};
};
console.log(Car.prototype); // shows an Object with only constructor
Car.prototype.toString = function() {
return 'hello from prototype. I am a ' + this.name;
};
var honda = new Car('Honda');
var tesla = new Car('Tesla');
console.log(tesla + ''); // I am defined in the constructor! I am a Tesla
tesla.toString = function(){
return 'hello from the ' + this.name + ' instance!';
};
console.log(tesla + ''); // hello from the Tesla instance!
console.log(honda + ''); // I am defined in the constructor! I am a Honda
delete tesla.toString;
console.log(tesla + ''); // hello from prototype. I am a Tesla!
delete Car.prototype.toString;
console.log(tesla + ''); // [object Object]
Javascript Objects
Objects are passed via Reference
Vagelis Papadogiannakis
Source Development
papas_source
const john = {
name: 'John'
};
function setname_george(o) {
o.name = 'George';
return o;
}
console.log(john); // {name: "John"}
const george = setname_george(john);
console.log(george); // {name: "George"} Seems legit
console.log(john); // {name: "George"} We fckd up john
Javascript Objects
Object References
Vagelis Papadogiannakis
Source Development
papas_source
const person = {
name: 'John'
};
const data = {
person: person
};
person.name = 'George';
console.log(data);
// {person: {name: 'George'}}
// data is an Object.
// It holds a reference to another object, `person`.
// when `person` changes, `data` changes too...
const data = {
person: {
name: 'John'
}
};
const person = data.person;
person.name = 'George';
console.log(data);
// {person: {name: 'George'}}
// data is an Object.
// It holds a reference to another object, `person`.
// when `person` changes, `data` changes too...
const data = {
person: {
name: 'John'
}
};
const person = data.person;
delete data.person;
console.log(data);
// {}
// reference of `person` was deleted from `data`
console.log(person);
// {name: 'John'}
// this reference still exists!
Javascript Objects
Lets create an object instance (one of many ways)
Vagelis Papadogiannakis
Source Development
papas_source
function Person (first, last) {
this.first_name = first;
this.last_name = last;
this.fullname = function(){
return this.first_name + ' ' + this.last_name;
}
}
const jd = new Person('John', 'Doe');
const ml = new Person('Mary', 'Lamb');
jd.first_name; // "John"
ml.last_name; // "Lamb"
jd.fullname(); // "John Doe"
ml.fullname(); // "Mary Lamb"
console.log(jd.fullname == ml.fullname); // false!
So, when we create a 1000 objects this way
1000 versions of the fullname are also created!
Not good, not at all good.
💛 Lets meet prototype 💛
Javascript Objects
Working with objects and the prototype
Vagelis Papadogiannakis
Source Development
papas_source
function Person () {}
Person.prototype = {
first: 'John', last: 'Doe',
hobbies: ['sitting', 'sleeping'],
fullname: function(){
return this.first_name + ' ' + this.last_name;
}
};
const jd = new Person(), ml = new Person();
ml.first = 'Mary'; ml.last = 'Lamb';
console.log(jd); // "Person {}"
console.log(ml); // "Person {first: 'Mary', last: 'Lamb'}
console.log(jd.fullname == ml.fullname); // true!
jd is created and no properties are assigned.
jd does not have a `first` or `last` property.
They are inherited by the prototype.
ml is created and both `first` and `last` properties
are assigned to it.
ml's prototype inherited properties, are overwritten
Dont you just 💛 prototype ?
Javascript Objects
Lets play more!
Vagelis Papadogiannakis
Source Development
papas_source
function Person () {}
Person.prototype = {
first: 'John', last: 'Doe',
hobbies: ['sitting', 'sleeping'],
fullname: function(){
return this.first_name + ' ' + this.last_name;
}
};
const jd = new Person(), ml = new Person();
ml.first = 'Mary'; ml.last = 'Lamb';
ml.hobbies[1] = 'running';
console.log(ml.hobbies); // ["sitting", "running"]
console.log(jd.hobbies); // ["sitting", "running"] <- WTaF?
Don't forget, arrays are Objects. When we messed with
marry's `hobbies` property, we messed with an Array
The Array was mutated. ALL OF IT. WHERE-EVER it was.
(bummer - It just "happened" to be on the prototype)
Since john's `hobbies` property was also pointing
to that same Array they were modified also.
This stinks... So, what do we do? 🥁🥁🥁🥁
Javascript Objects
Well it is simple... We use a combination of the prototype and the constructor function
Vagelis Papadogiannakis
Source Development
papas_source
function Person () {
this.hobbies = ['sitting', 'sleeping'];
}
Person.prototype = {
first: 'John', last: 'Doe',
fullname: function(){
return this.first_name + ' ' + this.last_name;
}
};
const jd = new Person(), ml = new Person();
ml.first = 'Mary'; ml.last = 'Lamb';
ml.hobbies[1] = 'running';
console.log(ml.hobbies); // ["sitting", "running"]
console.log(jd.hobbies); // ["sitting", "sleeping"] yup, that's me
Javascript Objects
All together and best practices
Vagelis Papadogiannakis
Source Development
papas_source
function Person (first, last) {
if (!(this instanceof Person)) {
// this is your safeguard in case you forget the `new` keyword
return new Person(first, last);
}
this.first = first;
this.last = last;
return this;
};
Person.prototype = {
fullname: function(){
return this.first + ' ' + this.last;
}
}
const john_doe = new Person('John', 'Doe');
const john_do = Person('John', 'Doe'); // yeay!
Javascript Classes
How to declare a Class
Vagelis Papadogiannakis
Source Development
papas_source
class Person {
constructor (first, last) {
this.first = first;
this.last = last;
}
fullname() {
return this.first + ' ' + this.last;
}
}
const jd = new Person('John', 'Doe');
Javascript Classes
Vagelis Papadogiannakis
Source Development
papas_source
class Car {
constructor (name, hp) {
this.name = name;
this.hp = hp;
}
static race(car1, car2) {
const winner = car1.hp > car2.hp ? car1 : car2;
return "the winner is " + winner.name;
}
}
const lada = new Car("Lada Niva", 80);
const ferrari = new Car("Ferrari", 661);
Car.race(lada, ferrari);
// "the winner is Ferrari"
Static functions
Javascript Classes
Vagelis Papadogiannakis
Source Development
papas_source
class Animal {
constructor (name) {
this.name = name;
}
}
class WalkingAnimal extends Animal{
constructor (name) {
super(name); // `super()` before `this`!
this.can_walk = true;
this.walk_distance = 0;
}
walk (meters) {
this.walk_distance += meters;
}
}
class SwimmingAnimal extends Animal{
constructor (name) {
super(name);
this.can_swim = true;
this.swim_distance = 0;
}
swim (meters) {
this.swim_distance += meters;
}
}
const peppa = new WalkingAnimal('Peppa Pig');
const nemo = new SwimmingAnimal('Nemo Clownfish');
So, How do we create a `tux` animal?
It can walk, and it can swim!
Javascript Prototypal Inheritance
Vagelis Papadogiannakis
Source Development
papas_source
function Animal() {}
function WalkingAnimal() {}
function SwimmingAnimal() {}
function WalkingSwimmingAnimal() {}
Animal.prototype = { name: '' };
WalkingAnimal.prototype = Object.assign({}, Animal.prototype, {
can_walk: true, walk_distance: 0, walk:function(distance){
this.walk_distance += distance;
}
});
SwimmingAnimal.prototype = Object.assign({}, Animal.prototype, {
can_swim: true, swim_distance: 0, swim:function(distance){
this.swim_distance += distance;
}
});
WalkingSwimmingAnimal.prototype = Object.assign({},
WalkingAnimal.prototype,
SwimmingAnimal.prototype
);
const dog = new WalkingAnimal(); dog.walk(4);
const fish = new SwimmingAnimal(); fish.swim(10);
const tux = new WalkingSwimmingAnimal(); tux.swim(7); tux.walk(4);
console.table({dog, fish, tux});
ANY QUESTIONS?