OOP in JS¶
1. concepts of oop¶
- Abstraction
- Polymorphism
- Inheretance
- Encapsulation
2. procedural vs oop¶
-
in procedural programming 1. you write functions. 2. change one function then you need to change everywhere 3. spaggitti code 4. functions have more parameters
-
in oop:
- you write classes.
- functions have less params.
- change only the code in the class and it will changes every where simply.
3. Abstraction¶
- reduce the impact of change.
- hide un-necceary data.
function Square(a, b){
this.x = a;
this.y = b;
this.area = function (){ console.log(this.x * this.y) };
let defaultLocation = {x:1, y:1} // private
let defaultArea = function(){
// code, this method is private
// we can call defaultLocation directly without this
}
}
defaultLocationanddefaultAreaare private. you can’t access them from the outer program.defaultLocationanddefaultAreaare local variables in the constructor function, so we can think of them as private but they arenot.- the square class interface does not contain defaultArea and defaultLocation and contain onlu x,y,area (the words with this).
- the square class is now abstracted, because we hide the default data so no body can miss around with them.
4. Inheretance¶
- eleminate redandant code.
5. polymorphism¶
- the object behaves differently depending on the class we are referincing.
- refactor ugly switch/case statments.
6. Encapsulation¶
- reduce complexity.
- increase reusability.
7. objects lterals¶
const square = {
x: 1,
y: 2,
area : function (){ console.log(this.x * this.y) }
}
- object is collection of key value pairs.
8. Factory functions¶
function createSquare(a,b){
return {
x: a,
y: b,
area : function (){ console.log( a * b) }
}
}
// so
let q1 = createSquare(2,2);
q1.area() //4
9. Constructors¶
- the first letter should be uppercase.
- it’s like creating an instance of class, but in js there is no classes.
function Square(a, b){
this.x = a;
this.y = b;
this.area = function (){ console.log(this.x * this.y) };
}
// so
q2 = new Square(2,2);
// if we remove new,
// 1) this will refer to the global object.
// 2) q2 will be undefined.
q2.area() //4
10. This¶
- by default
thisrefers to the global object, eg.window. - by using the
newkeyword before a constructor,thiswill refer to the new object.
11. every object has a constructor refers to the function that used to create this object.¶
12. Default constructors¶
let q3 = new Object()
q3.x = 2;
q3.y = 2;
q3.area = function(){ console.log(this.x * this.y) };
// OR
let q4 = new Object({
x:2,
y:2,
area: function(){ console.log(this.x * this.y) }
})
// so
q3.area() //4
q4.area() //4
- other default constructors:
new String(),new Boolean(),new Number()…
13. Functions are objects¶
const square = new Function('a , b', `
this.x = a;
this.y = b;
this.area = function (){ console.log(this.x * this.y) };
`)
// So
q5 = new square(2,2);
q5.area() //4
14. Value Types (pirmiatives) vs Reference Types¶
-
value types (pirimatives):
- Number
- String
- Boolean
- Symbol
- undefined
- null
-
Reference types:
- Object
- Array
- Map
- Set
- Function
-
copying a pirimative type will copy its value to the new variable.
- copying a refernce type will
not copyits value to the new var, instead thememory addressfor the first var is stored in the new var. - so copying a reference type is actually pointing to tits memory address.
// value
let x = 10;
let y = x;
x = 20; // x is 20, y still 10.
// reference
let x = { value: 10 };
let y = x;
x.value = 20; // y.value = x.value = 20.
- passing a var by its value to a function will not change its original value.
- passing a var by its reference will change its original value directly.
// primiatves (by value)
let x = 10;
function increase(num) { num++; }
increase(x);
console.log(x); // 10, copied by value, origin don't change.
// Objects (by reference)
let y = { value: 10 };
function increase(obj) { obj.value++; }
increase(y);
console.log(y); // { value: 11 }, copied by ref, origin changed directly.
15. add/remove properties¶
let o = {x:1}
// add
o.y = 2; // o is now {x:1, y:2}
o.x // 1, do notation
0["x"] // 1, bracket notation
// remove
delete o.y;
16. enamurating objects¶
// constructor
function Square(a, b){
this.x = a;
this.y = b;
this.area = function (){ console.log(this.x * this.y) };
}
// new object
let o = new Square(1,2)
// for .. in
for (key in o){
console.log(key) // x , y , area
console.log(o[key]) // 1, 2, funcion
}
// Object methods
const keys = Object.keys(o); // [x, y, area]
const values = Object.values(o); // [1, 2, function]
// check if a key existed in an oject
'x' in o; // true
'area' in o; // true
x in o; // false
17. setters and getters¶
function Square(a, b){
this.x = a;
this.y = b;
this.area = function (){ console.log(this.x * this.y) };
let defaultLocation = {x:1, y:1} // private
// 1) old way
this.getDefaultLocation = function(){
return defaultLocation // getter
}
this.setDefaultLocation = function(obj){
defaultLocation.x = obj.x;
defaultLocation.y = obj.y;
// this is setter function
}
// to access it;
// obj.getDefalutLocation() fo getter
// obj.setDefalutLocation(objet) fo setter
// 2) Another way
Object.definePropoerty(this, 'defaultLocation', {
get: function (){
return defaultLocation
}
set: function(obj){
defaultLocation.x = obj.x;
defaultLocation.y = obj.y;
// this is setter function
}
});
// to access it;
// obj.defalutLocation fo getter
// obj.defalutLocation = objet fo setter
}
- accessing private properties should be only using methods setters and getters.