Skip to content

Instantly share code, notes, and snippets.

@0bie
Last active October 20, 2017 09:30
Show Gist options
  • Save 0bie/57732ebbe0ece444a8b6cbc5998d8ec5 to your computer and use it in GitHub Desktop.
Save 0bie/57732ebbe0ece444a8b6cbc5998d8ec5 to your computer and use it in GitHub Desktop.
Creating objects in JavaScript
// `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