eventloop / platicas

Propón una plática para Eventloop
77 stars 3 forks source link

OLOO como 'el' paradigma de JavaScript #29

Closed mishelashala closed 8 years ago

mishelashala commented 9 years ago

OLOO as the JavaScript Paradigm

1. What is and what isn't JavaScript

JavaScript = [ 'imperative', 'almost-functional', 'prototype-based' ]; JavaScript !== OOP;

2. Understanding proto and prototype.

Prototype-based means: every object inherits properties and methods from other objects, not from classes.

// The global object, everyone inherits from it.
Object;

// The prorotype property contains all the methods and properties
// to inherit.
Object.prototype;

// The parent from where inherits, like it's on the top of
// the chain it returns {}
Ojbect.prototype.constructor;

// The methods and properties that inherits from constructor.
// Like it doesn't have a parent it returns {}.
Object.prototype.__proto__;

_note_: proto: is not part of ES5, but moderns browsers implement it anyway. That's why ES6 now implements it.

example:

var foo = {
    name: 'foo'
};

var f = Object.create(foo);

console.log(f); // {}
console.log(f.prototype); // undefined
console.log(f.__proto__); // { name: 'foo' }

3. Understanding functional JavaScript

1. Pure functions

// A pure function is any function that returns always the
// same value with the same input

// is a pure function!
var s = Math.sin(1);

// Is not a pure function!
// assuming it returns a different value everytime.
var d = random.getRandomNumber();

2. High-order functions

// A function that adds a higher level of abstraction.

var data = [1,2,3];

// Low level of abstraction
for (let index = 0, len = data.length; index < len; index++) {
    console.log(data[index]);
}
// Higher level of abstraction
function forEach(arr, cb) {
    for (let index = 0, len = arr.length; index < len; index++) {
        cb(arr[index]);
    }
}

let data = [1,2,3,4];
// high-order function
forEach(data, console.log);
// examples!
Array.prototype.forEach;
Array.prototype.map;
Array.prototype.reduce;

3. Stateless

let data = [1,2,3,4];

// State? Which one?
// I don't see anyone.
data.forEach(e => console.log(e));

4. Inmutability

// It works everytime, even if the
// state of the variable changes!
let data = [1,2,3,4];

// it works!
data.forEach(e => console.log(e));

// still working!
data = [1,2,3,4,5,6];
data.forEach(e => console.log(e));

// It works, dosen't print anything, but it works!
data = [];
data.forEach(e => console.log(e));

4. What's wrong with OOP JavaScript?

1. Constructor pattern!

// 1. It creates a variable called 'this';
// 2. It assigns this.constructor = Person;
// 3. it assigns this.name = name;
// 4. it assigns this.age = age;
// 5. it returns automatically this;
function Person (name, age) {
    this.name = name;
    this.age = age;
}

// OO Abstraction, JS is not an OO language!
let p = new Person('John Doe', 20);

Constructor pattern is broken

function Person (name, age) {
    this.name = name;
    this.age = age;

    // You can return anything manually, and compilers dont care!
    return { name: 'Chuck Testa', age: 55 };
}

// John Doe, is that you?
let p = new Person('John Doe', 20);

// Nope, its Chuck Testa!
console.log(p);

Don't touch the prototype!

// The Person 'class'
function Person (name, age) {
    this.name = name;
    this.age = age;
}

// NEVER touch the Function's prototype!!!!!!!
Person.prototype.greet = function () {
    console.log(`Hi, I'm ${this.name}. And I'm ${this.age} yo.`);
}

let p = new Person('John Doe', 20);

// it works, but it is a bad idea!
p.greet();

**By the way... Why are we inheriting from functions?***

console.log(typeof p); // object
console.log(typeof Person); // function
// Why? Never inherit objects from functions!

How can we do inheritance?
It's a freaking hell!

// The Person 'class'
function Person (name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.greet = function () {
    return `Hi, I'm ${this.name}. And I'm ${this.age} yo.`;
}

function Worker (name, age, job) {
    // Wat?
    Person.call(this, name, age);
}

// Wat?
Worker.prototype = Object.create(Person.prototype);
Worker.prototype.sayHi = function () {
    console.log(`${this.greet()} And I works as a ${this.job}`);
};

let w = new Person('John Doe', 20, 'godinez');
w.sayHi();

What about module pattern?
Same problem, more complexity, more code.

// Too much code!
const Person = (function () {
    function Person (name, age) {
        this.name = name;
        this.age = age;
    }

    Person.prototype.greet = function () {
        console.log(`Hi, I'm ${this.name}. And I'm ${this.age} yo.`);
    }

    return Person;
})();

var p = new Person('John Doe', 20);
p.greet();

5. The solution: OLOO

  1. Prototypes
  2. Factories
// 1. Objects as a base to inherit from.
const person = {
    name: 'Johhn Doe',
    age: 20,
    init(name, age) {
        this.name = name;
        this.age = age;
    }
};

const worker = {
    __proto__: person,
    job: 'godinez',
    init(name, age, job) {
        this.__proto__.init(name, age);
        this.job = job;
    }
};

// 2. Factories insted of constructors
var p = Object.create(person);
p.init('Jenny Doe', 19);

console.log(p); // { name: 'Jenny Doe', age: 19 }
console.log(p.__proto__); // { name: 'John Doe', age: 20, init: [Function] };
console.log(p.prototype); // undefined, nothing to inherit.

var w = Object.create(worker);
w.init('J.D.', 21);

console.log(w); // { name: 'J.D.', age: 21,job: 'godinez' }
console.log(w.__proto__); // { job: 'godinez', init: [function] }
console.log(w.__proto__.__proto__); // { name: 'John Doe', age: 20, init: [Function] }
console.log(w.prototype); // undefined, nothing to inherit.

Best practices

  1. Avoid 'this'
  2. Create your own factories
  3. Always assign functions to variables, don't declare them!
// 1. Objects as a base to inherit from.
const person = {
    name: 'Johhn Doe',
    age: 20
};

const worker = {
    __proto__: person,
    job: 'godinez'
};

// 2. Factories insted of constructors
const createPerson = (name, age) => {
    var proto = Object.create(person);
    var props = { name, age };

    return Object.assign(proto, props);
}

const createWorke = (name, age, job) => {
    var proto = Object.create(worker);
    var props = { name, age, job };

    return Object.assign(proto, props);
}

// Own factories
var p = createPerson('Jenny Doe', 19);

console.log(p); // { name: 'Jenny Doe', age: 19 }
console.log(p.__proto__); // { name: 'John Doe', age: 20 };
console.log(p.prototype); // undefined, nothing to inherit.

var w = createWorker('J.D.', 21);

console.log(w); // { name: 'J.D.', age: 21,job: 'godinez' }
console.log(w.__proto__); // { job: 'godinez' }
console.log(w.__proto__.__proto__); // { name: 'John Doe', age: 20 }
console.log(w.prototype); // undefined, nothing to inherit.

Conclusion

I love OLOO.

unRob commented 9 years ago

No me queda muy claro el razonamiento detrás de esta práctica, y creo que por eso tampoco me queda muy claro de qué se trataría la charla. Me gustaría leer una síntesis sobre qué es tu plática y porqué es importante presentarla en vivo, ¿qué opinan @javascriptmx/fellows?

Sparragus commented 9 years ago

Lei esto y aun no entiendo que es OLOO. Me gustaba más el tema de jQuery (https://github.com/javascriptmx/chelajs/issues/2) Quizas ahi puedes introducir algunos conceptops de aquí como high-order functions.

jeduan commented 9 years ago

Yo estoy muy entre dos lados, por un lado está buenísimo que nos hayas mandado una propuesta tan detallada, y como curador de propuestas eso me hace muy feliz. Por otro lado como ingeniero veo que hay enunciados muy fuertes cuyo razonamiento nunca se explica, como:

// NEVER touch the Function's prototype // it works, but it is a bad idea!

y veo que el código usa la propiedad __proto__ para establecer el prototipo de un objeto cuyo uso de acuerdo a MDN está fuertemente desalentado porque es muy lento. Se referencia su estandarización en ES6 únicamente como opción para código legado y en los links que encuentro hablan de que es hasta 90% más lento que usar simplemente objetos y modificar los prototipos.

A mi entender en JS en 2015 hay dos corrientes que han tomado mucha popularidad:

Creo que podría ir hacia allá si te apasiona el tema de la creación de objetos en JS.

Sparragus commented 9 years ago

Estoy de acuerdo con los comentarios de Jeduan. Entonces, tomando del final de esos comentarios digo...

Uuuuuu! Me encantaría que alguien hablará sobre programación funcional en JavaScript. Por lo que he visto en tu Twitter, a ti también te gusta el tema. Que piensas sobre ese tema?

On Tuesday, November 10, 2015, Jeduan Cornejo notifications@github.com wrote:

Yo estoy muy entre dos lados, por un lado está buenísimo que nos hayas mandado una propuesta tan detallada, y como curador de propuestas eso me hace muy feliz. Por otro lado como ingeniero veo que hay enunciados muy fuertes cuyo razonamiento nunca se explica, como:

// NEVER touch the Function's prototype

y veo que el código usa la propiedad proto para establecer el prototipo de un objeto cuyo uso de acuerdo a MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FObject%2Fproto está fuertemente desalentado porque es muy lento. Se referencia su estandarización en ES6 únicamente como opción para código legado y en los links que encuentro http://blog.getify.com/sanity-check-object-creation-performance hablan de que es hasta 90% más lento que usar simplemente objetos y modificar los prototipos.

A mi entender en JS en 2015 hay dos corrientes que han tomado mucha popularidad:

Creo que podría ir hacia allá si te apasiona el tema de la creación de objetos en JS.

— Reply to this email directly or view it on GitHub https://github.com/javascriptmx/chelajs/issues/29#issuecomment-155616087 .

Richard Kaufman

unRob commented 8 years ago

Mark-to-sweep por inactividad. Este issue se cerrará en 30 días salvo que se alguien adopte la charla.

Sparragus commented 8 years ago

Cerrando por inactividad.