Js: Prototypal Inheritance
Ways to create Js objects, prototype chain, deeper look at objects Sources: partially paid Udemy course, it's perfect, Great article on ES6 classes VS usual methods for creating objects, types of object properties and their attributes
29 flashcards · Programming Languages · by lakesare
var jane = new Person(); syntax was a marketing strategy for Java developers, because they were used to creating objects using new keyword, and something called a class.
function Person() {} const jane = new Person(); What is jane.__proto__?
jane.__proto__ points to Person.prototype.
Why do function constructors usually set: object's properties within the function body, but object's methods on the prototype? function Person(name) { this.name = name; } Person.prototype.sayHi = function() { console.log('Hi, I am ' + this.name); }
For efficiency/ memory space. We could just as well set object's methods inside the function body. But then, with every new Person(), we'd be creating a new method.
Name 4 ways to create objects with inheritance in Js.
1. class Hi extends Hello {} 2. Object.create 3. Function constructors 4. Set prototype directly to object.__proto__
Create object using Object.create.
const person = { name: 'Default', surname: 'Default' }; const jane = Object.create(person); jane.name = 'Jane'; jane.surname //=> 'Default'
Create object using function constructor.
function Person(name) { this.name = name || 'Default'; } Person.prototype.surname = 'Default'; const jane = new Person('Jane'); jane.surname //=> 'Default' Makes jane.__proto__ === Person.prototype.
Create object using direct assignment to __proto__.
const person = { name: 'Default', surname: 'Default' }; const jane = { name: 'Jane' }; jane.__proto__ = person; jane.surname //=> 'Default'
Write a polyfill for Object.create. const person = { name: 'Default', surname: 'Default' }; const jane = Object.create(person); jane.name = 'Jane'; jane.surname //=> 'Default'
if (!Object.create) { Object.create = (parent) => { function Creator() {} Creator.prototype = parent; return new Creator(); } }
The use of myObject.__proto__ is discouraged. Why? What should we use instead?
Why not use __proto__: Because it's never been in spec, and is now deprecated. Changing object's __proto__ is very slow. What to use instead: Object.getPrototypeOf(jane); Object.setPrototypeOf(jane, parent); Links: mozilla
What happens internally when we access __proto__?
__proto__ exposes private [[Prototype]] property of an object.
myFunction.prototype VS myObject.__proto__?
myFunction.prototype does nothing, unless it was called with new myFunction(). In that case myFunction.prototype is nothing but a __proto__ for all the objects that get created using this function constructor.
What can __proto__ be?
It can be either an object or null.
What's a constructor function in Js?
A constructor is just a function that happens to be called with the new operator.
Rewrite this constructor function so that it can be used without the new keyword: function Person(name) { this.name = name || 'Default'; } const jane = new Person('hi');
function Person(name) { const newObject = {}; newObject.name = name || 'Default'; newObject.__proto__ = Person.prototype; return newObject; } so newObject is created newObject.__proto__ gets assigned to function.prototype and newObject gets returned
And, just to hammer it home: Objects do not "inherit from" their prototypes. They delegate to them.
Every function in Js has a property prototype: myFunction.prototype = {} What's inside of it?
myFunction.prototype = { constructor: myFunction }
Rewrite object instanceof Constructor.
object.__proto__ === Contrusctor.prototype OR, recursively: object.__proto__.__proto__, etc... === Costructor.prototype The instanceof operator tests presence of constructor.prototype in object's prototype chain.
What is Object.defineProperty() used for?
Normal property addition through assignment creates { value: "red", writable: true, configurable: true, enumerable: true } If we want something else - we use Object.defineProperty.
What's the signature of Object.defineProperty() method?
Object.defineProperty( objectToModify, // string propNameString, // string descriptor // object (attributes for either data property, or accessor property. ) For example: Object.defineProperty(jane, 'name', { value: 'NonJane' })
Name 2 types of object properties and 4 attributes of each. (each property has 4 attributes/descriptors)
data properties: { value, writable } accessor properties: { get, set } They share: { configurable, enumerable }.
data property attributes: { value, writable } accessor property attributes: { get, set } shared attributes: { configurable, enumerable }. What do these attributes do?
value: the current value of the property. writable: if property value can be modified. get: function that returns the property value. set: function that sets the property value. configurable: if property attributes can be changed. enumerable: if property can be enumerated.
object = { color: "red" }; What type of property is color? What attributes does it have?
By default it is a data property, with attributes: { value: "red", writable: true, configurable: true, enumerable: true }
What would Babel transpile this code to? class Person { constructor(name) { this.name = name; } static hi() {} hello() {} } const jane = new Person("Jane");
function Person(name) { this.name = name; } defineProperties(Person.prototype, prototypeProps); defineProperties(Person, staticProps); Where defineProperties uses Object.defineProperty and makes both prototypeProps and staticProps usual data properties.
Name 2 ways to create an object with nonstandard properties. And what is the difference between them?
Object.create({}, { age: { writable: true, configurable: true, value: 'hello' } } ) Object.defineProperties({}, { age: { writable: true, configurable: true, value: 'hello' } } ) The difference is that: Object.create creates a new object (therefore we can use this method for inheriting), while Object.defineProperties modifies the object we pass it.
Write how class Dog extends Animal {} may be implemented using function constructors. Here is the Animal class, write Dog class: function Animal(name){ this.name = name; } Animal.prototype.eat = function(){};
function Dog(name, goodness){ Animal.call(this, name); // super() this.goodness = "Good"; } Dog.prototype = Objec.create(Animal.prototype); // inherit methods Dog.prototype.fff = function(){};
What is the difference between Bird.prototype = Object.create(Animal.prototype); and Bird.prototype = new Animal(); ?
The only real difference is whether or not the Animal function is called during the creation of Bird.prototype. Depending on your circumstances and intent, you may or may not want that to happen, so let's consider them roughly interchangeable but with different purposes.
Name 2 properties any function has.
fn.name - name of the function fn.prototype.constructor
const Person = function(name) { this.name = name; } Person.prototype.sayHi = function(){ console.log(`Hi, I'm ${this.name}`); } const person = new Person('Ivania'); Name all properties of person.__proto__ object.
person.__proto__ is { sayHi: function..., constructor: function... } person.__proto__ always points to the constructor_function.prototype. And any function has a .prototype.constructor property.
Object.defineProperty(person, 'surname', descriptor) Descriptor can be either data descriptor, or an accessor descriptor. How does Js know which's which?
Neither of value/writable/get/set keys, it is treated as a data descriptor. Both value/writable and get/set keys: an exception is thrown. Bear in mind that these attributes are not necessarily the descriptor's own properties. Inherited properties will be considered as well. In order to ensure these defaults are preserved, you might specify all options explicitly, or point to null with Object.create(null).