JavaScript Modularization: ES2015 “export” & “import” solution

// file "./module.js"
export { calculator }

let calc = { 
  add 
  , substract 
  , get isStore() { return store } 
  , set isStore(bolean) { store = bolean } 
}
let mem = []
let isStore = true

function storeResult(result){
  if(isStore){ mem.push(result) }
}

function add(a,b){
  let result = a+b
  storeResult(result)
  return result
}
function substract(a,b){
  let result = a-b
  storeResult(result)
  return result
}
// file "/app.js"
import { calc } from "./module.js"

calculator.add(1,2) // 3

JavaScript Modularization: IIFE Reveal pattern

let calc = (function(){
  let mem = []
  let isStore = true

  function storeResult(result){
    if(isStore){ mem.push(result) }
  }

  function add(a,b){
    let result = a+b
    storeResult(result)
    return result
  }

  function substract(a,b){
    let result = a-b
    storeResult(result)
    return result
  }

  return { 
    add
    , substract

    , get isStore() { return store }
    , set isStore(bolean) { store = bolean }
  }
})()

calc.add(1,2)

JavaScript OOP: ES6 class pattern

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName
    this.lastName = lastName
  }
  // methods defined here are in the prototype chain
  get fullName(){ return this.firstName + " " + this.lastName }
  greet(person){ console.log(`Hi, I'm ${this.fullName}`) }
  // static methods won't be inherited
  // they can be accessed via "Person.nameOfMethod" directly
  static helloWorld(){ console.log(`Hello World`) }
}
let johnSnow = new Person("John", "Snow")
johnSnow.greet()

// extending the class
class Employee extends Person {
  constructor(firstName, lastName, position) {
    super(firstName, lstName)
    this.position = position
  }
}

// For Information Security, you may want use
// IIFE, symbol and getter
// to make your values private
let anotherPerson = (function(){
  const firstNameSymbol = Symbol("firstName")
  const lastNameSymbol = Symbol("lastName")

  class Person{
    constructor(firstName, lastName){
      this[firstNameSymbol] = firstName
      this[lastNameSymbol] = lastName
    }
    static greet(person){ console.log(`Hi, ${person[firstNameSymbol]}`)}
    get fullName(){ return this[firstNameSymbol] + " " + this[lastNameSymbol]}
    get firstName(){ return this[firstNameSymbol] }
    get lastName(){ return this[lastNameSymbol] }
  }
  return Person
})()

let johnDoe = new anotherPerson("John", "Doe")
johnDoe.fullName
// this is not 100% perfect
console.log(Object.getOwnPropertySymbols(johnDoe))

// If you want super security, try WeakMap:
let yetAnotherPerson = (function(){
  const privateData = new WeakMap()

  class Person{
    constructor(firstName, lastName){
      privateData.set(this, {firstName, lastName})
  }

  static greet(person){ console.log(`Hi, ${privateData.get(person).firstName}`) }

  get fullName(){ return privateData.get(this).firstName + " " + privateData.get(this).lastName }
  get firstName(){ return privateData.get(this).firstName }
  get lastName(){ return privateData.get(this).lastName }
  }
  return Person
})()

let evanEvans = new yetAnotherPerson("Evan", "Evans")
evanEvans.fullName

JavaScript OOP: Example of the Factory Pattern

let style = "color: gray"
console.log(`%c Playing with constructor function`, style)
function personFactory(firstName, lastName){
    return {
        firstName
        , lastName
        , get fullName() { return `${this.firstName} ${this.lastName}` }
        , greet: function() { return `Hi, my name is ${this.fullName}` }
    }
}

let johnSnow = personFactory("John", "Snow")
console.log(johnSnow.greet())

console.log(`%c Extending personFactory()`, style)
function kingFactory(firstName, lastName, title){
    let person = personFactory(firstName, lastName)
    person.title = title
    person.sayTitle = function(){
        console.log(`I am ${this.fullName}, and I am ${this.title}`)
    }

    return person
}

johnSnow = kingFactory("John", "Snow", "King of the North")
johnSnow.sayTitle()

// for lowering RAM load and minimal namespace polution
let anotherPersonFactory = (function(){
    let personPrototype = {
        get fullName() {return this.firstName + " " + this.lastName}
        , greet: function(person){console.log(`Hi, my name is ${this.fullName}`)}
    }

    return function(firstName, lastName){
        let person = Object.create(personPrototype, {
            firstName: {writable: false, value: firstName}
            , lastName: {writable: false, value: lastName}
        })
        return person
    }
})()

let jackyChan = anotherPersonFactory("Jacky", "Chan")
jackyChan.greet()

JavaScript面试题(28):中高级JavaScript问题(原型)

  1. 原型继承(Prototypal Inheritance )
    // 原型继承可以通过提高代码的复用性,提高程序的效率。
    // JavaScript的对象是原型继承的,它没有类(class)的概念
    // 下面是ES2016的class出来之前的写法
    
    
    // 构造函数法(Constructor Function pattern)
    "use strict"
    
    function objCreator(id, name){
        this.id = id
        this.name = name
        this.selfDescribe = function(){
            console.log(`I am ${this.name} with ID ${this.id}.`)
        }
        this.fixedByClousure = function(){
            // 这里要log的是被传进来的两个参数
            // 两个参数在下面“obj”实例化的时候,也就是这行代码:
            // let obj1 = new objCreator(1, "Adam")
            // 这两个参数就被固定了下来
            // obj1.name是可变的,但是参数name是不可变的
            console.log(`I am ${name} with ID ${id}.`)
        }
    }
    
    // 没有关键词“new”的话,
    // 在严格模式下,this指向undefined
    // 这里不作演示
    let obj1 = new objCreator(1, "Adam")
    console.log(obj1)
    obj1.selfDescribe()
    
    // 有关键词“new”的话,
    // 对象“obj1”的“__proto___”指向函数“objCreator”的“prototype”
    // 因此,给函数“objCreator”的“prototype”加入一个属性与值的对后,
    // 所有“__proto__”指向函数“objCreator”的“prototype”的对象们,
    // 会一起多出这个属性与值的对
    objCreator.prototype.sayId = function(){
        console.log(`My Id is ${this.id}.`)
    }
    obj1.sayId() // "My Id is 1."
    obj1.id = 2
    obj1.sayId()
    obj1.fixedByClousure()
    
    // 当然,我们可以改写继承来的东西
    obj1.__proto__.sayId = function(){
        console.log(`${this.id} is my Id.`)
    }
    obj1.sayId()
    
    // 我们可以在一个构造函数的基础上构建新的构造函数
    // 常见的实现方法是“.call()”方法法
    // 注意,函数“Person”的“prototype”不是“objCreator()”
    function Person(id, name, profession){
        objCreator.call(this, id, name)
        this.profession = profession
    }
    let magician = new Person(2, "Jessie", "Magician")
    console.log(magician)
    
    // 因为(构造)函数“Person”的“prototype”不是“objCreator()”
    // 通过下面的代码,我们可以让函数“Person”的“prototype”的“prototype”
    // 等于函数“objCreator”的“prototype”
    // 这样可以让函数“Person”继承后来才加进函数“objCreator”的“prototype”的方法等
    
    objCreator.prototype.sayHelloWorld = function(){ console.log("Hello Wolrd")}
    
    Person.prototype = Object.create(objCreator.prototype)
    
    let wizard = new Person(3, "Elisa", "Wizard")
    
    if(wizard.sayHelloWorld) wizard.sayHelloWorld()
    else console.log(".sayHelloWorld is not availabl")
    
    // 但是在此前已经实例化了的对象(比如“magician”),
    // 它们不会继承这个新的方法
    if(magician.sayHelloWorld) magician.sayHelloWorld()
    else console.log(".sayHelloWorld is not available")
    
    
    // 下面为“原型模式(Prototypal Pattern)”:
    // Object.create()是的原型模式的核心语法
    // 它将下面正在被声明的变量“derrenBrown”的“__proto__”指向了
    // 参数“GreateMan”的“__proto__”
    let GreatMan = {
        init: function(firstName, lastName){
            this.firstName = firstName
            , this.lastName = lastName
        }
        , sayFullName: function(){
            console.log(`I am ${this.firstName} ${this.lastName}`)
        }
    }
    let derrenBrown = Object.create(GreatMan)
    derrenBrown.init("Derren", "Brown")
    derrenBrown.sayFullName()
    
    // 我们也可以这样写
    let GreatMan = {
        sayFullName: function(){
            console.log(`I am ${this.firstName} ${this.lastName}`)
        }
    }
    function GreatManFactory(firstName, lastName){
        let greatMan = Object.create(GreatMan)
        greatMan.firstName = firstName
        greatMan.lastName = lastName
        return greatMan
    }
    let derrenBrown = GreatManFactory("Derren", "Brown")
    derrenBrown.sayFullName()
    
    // 原型模式下的原型继承也是通过Object.create()实现的,
    // 这里略去,留作大家思考