Last active
October 20, 2017 09:30
-
-
Save 0bie/57732ebbe0ece444a8b6cbc5998d8ec5 to your computer and use it in GitHub Desktop.
Creating objects in JavaScript
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// `bind` and `this` | |
let dog = { | |
sound: 'woof', | |
talk: function() { | |
console.log(this.sound); | |
} | |
} | |
dog.talk(); // => 'woof' | |
let talkFunc = dog.talk; | |
talkFunc(); // => `undefined` | |
let boundFunc = talkFunc.bind(dog); | |
boundFunc(); // => 'woof' | |
let button = document.getElementById('button'); | |
button.addEventListener('click', dog.talk.bind(dog)); | |
function talk() { | |
console.log(this.sound); | |
} | |
let boromir = { | |
sound: 'One does not simply walk into mordor' | |
}; | |
let talkBoundToBoro = talk.bind(boromir); | |
talkBoundToBoro(); // => One does not simply walk into mordor | |
let boro = { | |
speak: talk, | |
sound: 'boro sound' | |
} | |
boro.speak(); // => 'boro sound' | |
let bor = { | |
sound: 'bor sound' | |
}; | |
bor.speak = talk.bind(bor); // => bound function | |
let blab = bor.speak; | |
blab(); // => 'bor sound' | |
let bo = { | |
speak: talk, | |
sound: 'bo sound' | |
} | |
let co = { | |
foo: bo.speak, | |
sound: 'co sound' | |
} | |
co.foo(); // => co sound | |
// prototype | |
function talk() { | |
console.log(this.sound); | |
} | |
talk(); // => `undefined` | |
let animal = { | |
talk | |
} | |
animal.talk(); // => `undefined` | |
let cat = { | |
sound: 'meow' | |
}; | |
cat.talk(); // => TypeError: cat.talk is not a function | |
Object.setPrototypeOf(cat, animal); | |
cat.talk() // => 'meow' | |
let dog = { | |
sound: 'woof' | |
}; | |
Object.setPrototypeOf(dog, animal); | |
let prarieDog = { | |
howl: function() { | |
console.log(this.sound.toUpperCase()); | |
} | |
}; | |
prarieDog.howl(); // => Uncaught TypeError: Cannot read property 'toUpperCase' of undefined | |
Object.setPrototypeOf(prarieDog, dog); | |
prarieDog.howl(); // => 'WOOF' | |
prarieDog.sound; // => 'woof' | |
prarieDog.talk(); // => 'woof' | |
// prototypes are delegates; they do not create a copy of the object | |
// `setPrototypeOf` is never really used; it is helpful in explaining the concept | |
// `new` | |
function Person(saying) { | |
this.saying = saying; | |
} | |
Person.prototype.talk = function() { | |
console.log('I say:', this.saying); | |
} | |
var person1 = new Person('foo1'); | |
person1.talk(); // => 'I say: foo1' | |
// What does `new` do? | |
// create a new object | |
// look up the constructors (Person) prototype then set that as the prototype of the newly created object | |
// assign `this` to the newly created object | |
// return the newly created object (unless the constructor has a `return` statement) | |
// Rebuild `new` to understand it | |
function newNew(constructor) { | |
var obj = {}; | |
var argsArray = Array.prototype.slice.apply(arguments); | |
Object.setPrototypeOf(obj, constructor.prototype); | |
constructor.apply(obj, argsArray.slice(1)); | |
return obj; | |
} | |
var person2 = newNew(Person, 'foo2'); | |
person2.talk(); // => I say: foo2 | |
// NOTE: If the constructor returns something that will be the value of the newly created object instead | |
// __proto__ vs prototype | |
let obj = {prop: 'value'}; | |
let obj1 = {prop1: 'value1'}; | |
Object.setPrototypeOf(obj1, obj); | |
obj1.prop1; // => 'value1' | |
obj1.prop; // => 'value' | |
obj1.__proto__; // => {prop: "value"} | |
function Func() {} | |
Func.prototype.evt = 'click'; | |
let myFunc = new Func(); | |
myFunc.evt; // => 'click' | |
myFunc.__proto__; // => {evt: "click", constructor: ƒ} | |
myFunc.prototype; // => `undefined` | |
Func.prototype; // => {evt: "click", constructor: ƒ} | |
let obj3 = {}; | |
obj3.prototype; // => `undefined` | |
obj3.__proto__; // => `Object` global object | |
obj3.__proto__ === Object.prototype; // => `true` | |
Object.prototype.test = 'footest'; | |
obj3.test; // => 'footest' | |
// https://coderwall.com/p/j1khtg/javascript-difference-between-__proto__-and-prototype | |
// `Object.create()` | |
// A static method on the `Object` prototype | |
// Creates a new object with the prototype set to a certain object | |
let ca = { | |
sound: '', | |
makeSound: function() { | |
console.log(this.sound); | |
} | |
}; | |
var u = Object.create(ca); | |
u.sound = 'uuu'; | |
u.makeSound(); // => 'uuu' | |
u.__proto__; // => {sound: "", makeSound: ƒ} | |
ca.isPrototypeOf(u); // => true | |
// Rebuild `Object.create` | |
function objectCreate(proto) { | |
const obj = {}; | |
Object.setPrototypeOf(obj, proto); | |
return obj; | |
}; | |
// Classes | |
class Mammal { | |
constructor(sound) { | |
this.sound = sound; | |
} | |
talk() { | |
return this.sound; | |
} | |
} | |
var animal = new Mammal('foo'); | |
animal.talk(); // => 'foo' | |
class Dog extends Mammal { | |
constructor() { | |
super('woof'); // `super` calls the constructor of the inherited class (`Mammal`) | |
} | |
} | |
var animal1 = new Dog(); | |
animal1.talk(); // => 'woof' | |
// `class` is a thin layer on top of prototypal inheritance | |
var animalSound = Dog.prototype.talk.bind({sound: 'bar'})(); | |
animalSound; // => 'bar' | |
Dog.prototype.isPrototypeOf(animal); // => true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment