Class & Prototypal Inheritance
Presenter: Yauheni Pozdnyakov
t.me/youhy
We'll talk about...
-
Object and types
-
Prototypes
-
OOP in JS
Something important before...
TYPES!
Primitives
and...
Boxing
Unboxing
Boxing & Unboxing
Primitives
Object constructors
var a = 5;
let b = 'I love JS'
const iReallyDo = true; //nothing but primitives
a.toString(); //"5"
b.toUpperCase(); //"I LOVE JS"METHOD CALL OVER A PRIMITIVE???? WHAT???
Boxing & Unboxing
let a = 'I love js ';
a.toUpperCase();
IT'S OKAY!
a - primitive
let's pack it...
var tempA = new String(a)
typeof tempA // object
let's call toUpperCase() method from String object over tempA
tempA// I LOVE JS
unbox tempA to a
a// I LOVE JS
STILL PRIMITIVE!!!
Conclusion
- Primitives are not Objects and do not have propeties
- JS creates object over the primitive(Boxes it)
- Perfoms an action over it
- Returns modefied value back to the primitive (Unboxes it)
- Destroys object
Some code
let length = 'this is string'.length; //what you see
let length = (new String('this is string')).length; // what is done
Prototypes
- Is Object
- Could be used as a constructor
function A() {}Inner properties [[Construct]] and Prototype
- [[Construct]] allocates memory for new instance
- is called by "new"
function A(){}
A(); // call A as a function
var a = new A(); // call for [[Constructor]] to create an instance of AConstructor property
JavaScript’s object system is based on prototypes, not classes.
const Coder= function(name, lang) {
this.name = name;
this.lang = lang;
this.code = () => `${this.name} codes ${this.lang}`;
};
const john = new Coder('John', 'JavaScript');
const mary = new Coder('Mary', 'GoLang');
john.code() // John codes JavaScript
mary.code() // Mary codes GoLangconsole.log(john.constructor); // function Coder(name, lang) { ... };
console.log(john.constructor.name); // Coder
console.log(john instanceof Coder); // true
Constructor property is assigned to each function created with "new" and points to the Constructor function, which has created this instance
Each time creates function and with code function inside of it.
let a=25;
a.constructor === Number//????A little bit more about "New"
- Create a new instance
- Bind `this` to the new instance
- Reference the new object’s delegate [[Prototype]] to the object referenced by the constructor function’s `prototype` property.
- Names the object type after the constructor, which you’ll notice mostly in the debugging console. You’ll see `[Object Foo]`, for example, instead of `[Object object]`.
- Allows `instanceof` to check whether or not an object’s prototype reference is the same object referenced by the .prototype property of the constructor.
Prototype and _proto_
const Coder= function(name, lang) {
this.name = name;
this.lang = lang;
};
Coder.prototype.code = function(){
return `${this.name} codes ${this.lang}`
};
const john = new Coder('John', 'JavaScript');
john.code() // John codes Javascript
Creates prototype object
Places code function inside of it
No need to copy code function to each instance of Coder
code method is accessed by _proto_ link from Coder instance to Coder.prototype object
Array.prototype.shift()
[].shift()
Any difference?
Prototype chaining
console.dir([].__proto__); // same as
console.dir(Array.prototype);
WHY???
// For Numbers
console.dir((10).__proto__); // Number
console.dir((10).__proto__.__proto__); // Object
// For Strings
console.dir('str'.__proto__); // String
console.dir('str'.__proto__.__proto__); // Object
// For objects
console.dir([].__proto__); // Array
console.dir([].__proto__.__proto__); // Object
// For Coder
console.dir(john.__proto__); // Coder
console.dir(john.__proto__.__proto__); // ObjectIf a property is not found on the object, the lookup is delegated to the delegate prototype, which may have a link to its own delegate prototype, and so on up the chain until you arrive at`Object.prototype`, which is the root delegate.
Prototype delegation
Prototype and _proto_
-
_proto_ chaining (looking for methods in chain of prototypes)
- Prevents from useless copies
- All instanses share same linked methods stored once (Bad or Good geather afterwards)
- Prototype stores methods that should be applied to each instance
- All instances reffer to the same prototype, if method in prototype has been changed - all instances will use modified method.
Conclusion
Class & Prototypal Inheritance
Class Inheritance: A class is a description of the object to be created. Classes inherit from classes and create subclass relationships:class hierarchy
May or may not use "class" keyword from ES6
Prototypal Inheritance: A prototype is a working object instance. Objects inherit directly from other objects.
Single-ancestor parent/child hierarchies and create the tightest coupling available in OO design.
Instances are typically instantiated via factory functions, object literals, or `Object.create()`.
Base Class Problem
- `A` is the base class
- `B` inherits from `A`
- `C` inherits from `B`
- `D` inherits from `B`
`C` calls `super`, which runs code in `B`. `B` calls `super` which runs code in `A`.
A` and `B` contain unrelated features needed by both `C` & `D`. `D` is a new use case, and needs slightly different behavior in `A`’s init code than `C` needs. So the newbie dev goes and tweaks `A`’s init code. `C` breaks because it depends on the existing behavior, and `D` starts working.
Concatenative inheritance
`Object.assign()` ES6
Underscore/Lodash’s `.extend()`
We have features:
| Features list |
|---|
| feat1 |
| feat2 |
| feat3 |
| feat4 |
`C` needs `feat1` and `feat3`
`D` needs `feat1`, `feat2`, `feat4`
const C = compose(feat1, feat3);
const D = compose(feat1, feat2, feat4);D needs something different from feat1??
No problem! Let's customise feat1 for D not affecting for others
const D = compose(custom1, feat2, feat4);And `C` remains unaffected!
ES6 classes
ES6 classes desugar to constructor functions, so everything that follows about constructor functions also applies to ES6
Benefits of Constructors & `class`:
- `this` refers to the new object.
- Some people like the way `myFoo = new Foo()` reads.
- There may be a micro-optimization performance benefit
- A single, canonical way to emulate classes in JavaScript. Prior to ES6, there were several competing implementations in popular libraries
Drawbacks of Constructors & `class`:
-
Required `new`
- Temptation for users to create problematic class hierarchies using the extends keyword.
Conclusion
- JavaScript Prototypal model is very dynamic
- Object.create creates the same prototype chain
- Think weather classic inheritance is the best for you, or maybe today is time for extending and concatinating objects?
- ES6 classes doesn't change anything in the JavaScript world! They are still translated into prototypes and constructor function.
- constructor(){...} from ES6 Classes turns into constructor function like in ES5
- Methods from ES6 classes are assigned to prototype like in ES5
Any questions?
THANK YOU FOR ATTENTION!!!
Class and Prototypal Inheritance
By Yauheni Pozdnyakov
Class and Prototypal Inheritance
- 158