Javascript Primitives, Objects and Classes

Vagelis Papadogiannakis
Source Development

papas_source

The 6 types of Javascript primitives

Vagelis Papadogiannakis
Source Development

papas_source
- String
- Number
- Bigint
- Boolean
- null
- undefined
- Symbol
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});
THE END

ANY QUESTIONS?
Javascript Primitives, Objects and Classes
By papas_source
Javascript Primitives, Objects and Classes
A Talk for the May 2019 meeting of our local DevStaff community https://www.meetup.com/devstaff/
- 214