@anonymous/

MiniCornyEditors

Nodejs

No description

fork
loading
Files
  • index.js
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
class Thing {
  constructor(name) {
    this.state = { name }
    return proxify(this, this.state)
  }
}

function enterBooleanMode(receiver, state, booleanValue) {
  state.inBooleanMode = true
  state.booleanValue = booleanValue
  return receiver
}

function setBoolean(receiver, state, prop) {
  state.booleans = {...state.booleans, [prop]: state.booleanValue }
  state.inBooleanMode = false
  state.booleanValue = null
  
  return receiver
}

function enterDefineMethodMode(receiver, state) {
  state.inDefineMethodMode = true
  return receiver
}

function setMethod(receiver, state, prop) {
  state.inDefineMethodMode = false
  return phrase => {
    const f = () => `${state.name} ${conjugate(prop)}: ${phrase}`
    state.methods = { ...state.methods, [prop]: f }
  }
}

function conjugate(word) {
  return word + 's'
}

// Hàm proxify() nhận vào một target và một object chứa state.
// State này sẽ được sử dụng để giải quyết những yêu cầu tiếp theo.
function proxify(target, state) {
  return new Proxy(target, {
    get(target, prop, receiver) {
      if (state.inBooleanMode) return setBoolean(receiver, state, prop)
      if (state.inDefineMethodMode) return setMethod(receiver, state, prop)

      if (prop === 'name') return state[prop]
      if (prop === 'is_a') return enterBooleanMode(receiver, state, true)
      if (prop === 'is_not_a') return enterBooleanMode(receiver, state, false)     
      if (prop === 'can') return enterDefineMethodMode(receiver, state)
      
      if (prop.startsWith('is_a_')) return state.booleans[prop.replace('is_a_', '')]
      
      if (state.methods[prop]) return state.methods[prop]

      // Còn lại thì sử dụng hành vi mặc định
      return target[prop]
    }
  })
}

const t = new Thing('Phương')

// Khai báo các thuộc tính boolean
t.is_a.singer
t.is_not_a.man

t.can.sing('Yêu hay không yêu không yêu hay yêu nói một lời')

console.log(`t.name: ${t.name}`)
console.log(`t.is_a_singer: ${t.is_a_singer}`)
console.log(`t.is_a_man: ${t.is_a_man}`)
console.log(t.sing())