Zrozumieć JavaScript #1

Prototypy i klasy

@MichalZalecki

JavaScript

  • high-level
  • dynamic
  • untyped
  • interpreted/JIT
  • prototype-based
  • first-class functions
  • multi-paradigm (OO, FP)

JavaScript

  • high-level
  • dynamic
  • untyped
  • interpreted/JIT
  • prototype-based
  • first-class functions
  • multi-paradigm (OO, FP)

Prototype based

Nie istnieje coś takiego jak dziedziczenie
w JavaScript w rozumieniu w jakim istnieje np. w Java

JavaScript ma potężniejszy odpowiednik...

prototype chain

object-oriented

const obj1 = { a: 1, b: 2 };
const obj2 = { a: 10, c: 3 };
const obj3 = {};

obj1.__proto__; // {}
obj1.__proto__.__proto__; // null

Object.getPrototypeOf(obj1); // {}
Object.getPrototypeOf(
  Object.getPrototypeOf(obj1)); // null

Object.setPrototypeOf(obj2, obj1);
Object.setPrototypeOf(obj3, obj2);

Object.getPrototypeOf(obj3); // {a: 10 c: 3}
Object.getPrototypeOf(
  Object.getPrototypeOf(obj3)); // {a: 1 b: 2}

obj3.a; // 10
obj3.b; // 2
obj3.c; // 3

class-oriented

function Form(selector) {
  this.form = document.querySelector(selector);
  this.form.addEventListener("submit", ::this.handleSubmit);
}

Form.prototype.handleSubmit = function (e) {
  e.preventDefault();
}

new Form("#signup");
function Form(selector) {
  this.form = document.querySelector(selector);
  this.form.addEventListener("submit", ::this.handleSubmit);
}

Form.prototype.handleSubmit = function (e) {
  e.preventDefault();
}

function SignupForm(/* ? */) {
  // ?
}

SignupForm.prototype = // ?
SignupForm.prototype.constructor = // ?

new SignupForm("#signup");
function Form(selector) {
  this.form = document.querySelector(selector);
  this.form.addEventListener("submit", ::this.handleSubmit);
}

Form.prototype.handleSubmit = function (e) {
  e.preventDefault();
}

function SignupForm(...args) {
  Form.apply(this, args);
}

SignupForm.prototype = Object.create(Form.prototype);
SignupForm.prototype.constructor = SignupForm;

new SignupForm("#signup");
Form.prototype.isValid = function () {
  return this.form.checkValidity();
}

Form.prototype.gatherData = function () {
  return Array.from(this.form.elements)
    .filter(({ name }) => name)
    .reduce((akk, input) =>
      ({...akk, [input.name]: input.value}), {});
}

Form.prototype.gatherErrors = function () {
  return Array.from(this.form.elements)
    .filter(input => input.name && input.validationMessage)
    .reduce((akk, input) =>
      ({...akk, [input.name]: input.validationMessage}), {});
}
SignupForm.prototype.handleSubmit = function (e) {
  // ?
  if (this.isValid()) {
    console.log(this.gatherData());
  } else {
    console.warn(this.gatherErrors())
  }
}
SignupForm.prototype.handleSubmit = function (e) {
  Form.prototype.handleSubmit.call(this, e);
  if (this.isValid()) {
    console.log(this.gatherData());
  } else {
    console.warn(this.gatherErrors())
  }
}

ES2015 class-oriented

class Form {
  constructor(selector) {
    this.form = document.querySelector(selector);
    this.form.addEventListener("submit", ::this.handleSubmit);
  }
  
  handleSubmit(e) {
    e.preventDefault();
  }
}

new Form("#signup");
class Form {
  constructor(selector) {
    this.form = document.querySelector(selector);
    this.form.addEventListener("submit", ::this.handleSubmit);
  }
  
  handleSubmit(e) {
    e.preventDefault();
  }
}

class SignupForm extends Form {}

new SignupForm("#signup");
class Form {
  constructor(selector) {
    this.form = document.querySelector(selector);
    this.form.addEventListener("submit", ::this.handleSubmit);
  }
  
  handleSubmit(e) {
    e.preventDefault();
  }
}

class SignupForm extends Form {
  handleSubmit(e) {
    // ?
    if (this.isValid()) {
      console.log(this.gatherData());
    } else {
      console.warn(this.gatherErrors())
    }
  }
}
class Form {
  constructor(selector) {
    this.form = document.querySelector(selector);
    this.form.addEventListener("submit", ::this.handleSubmit);
  }
  
  handleSubmit(e) {
    e.preventDefault();
  }
}

class SignupForm extends Form {
  handleSubmit(e) {
    super.handleSubmit(e);
    if (this.isValid()) {
      console.log(this.gatherData());
    } else {
      console.warn(this.gatherErrors())
    }
  }
}
Made with Slides.com