Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JSに不変の愛を

 JSに不変の愛を

We Are JavaScripters! @6th
https://wajs.connpass.com/event/54667/
用の資料です

boiyama

May 01, 2017
Tweet

More Decks by boiyama

Other Decks in Programming

Transcript

  1. ͱ͍͏͜ͱʹͳΔͷͰ͕͢ɺ͜ͷ࢓༷͕σϕϩούʔπʔ ϧεϖγϟϦετΛੜΈग़͢ཁҼͷҰͭʹͳ͍ͬͯ·͢ɻ const arr = ['foo', 'bar']; arr.push('baz'); console.log(arr); //

    ['foo', 'bar', 'baz'] const obj = { a: 'foo', b: 'bar' }; obj.c = 'baz'; console.log(obj); // { a: 'foo', b: 'bar', c: 'baz' } JSͷObjectܕͷ஋͸Մมʹͳ͍ͬͯ·͢ɻ
 ഑ྻ΍ΦϒδΣΫτ͸ObjectܕͳͷͰɺ
  2. ͘͝γϯϓϧͳΞϓϦέʔγϣϯΛྫʹΈ͍͖ͯ·͠ΐ͏
 ·ͣɺҎԼͷΑ͏ͳFlux෩ͷը໘ඳըؔ਺Λ࡞Γ·ͨ͠ɻ // ͜ͷؔ਺͸ɺΞϓϦέʔγϣϯͷঢ়ଶͷॳظ஋ modelɺReactίϯϙʔωϯτ Viewɺঢ়ଶߋ৽ؔ਺ update
 // Λड͚औͬͯɺͦΕΛ࢖ͬͯը໘ඳըͱঢ়ଶ؅ཧΛ͠·͢
 function

    program(id, { model, View, update }) {
 // ΞϓϦέʔγϣϯͷঢ়ଶ
 let _model = model 
 render() // ߋ৽ϝοηʔδ msgΛड͚औΓɺঢ়ଶΛߋ৽ͯ͠ඳը͢Δؔ਺
 function dispatch(msg) {
 _model = update(msg, _model)
 render()
 } // ίϯϙʔωϯτʹঢ়ଶͱdispatchؔ਺Λ౉ͯ͠ඳը function render() { ReactDOM.render(<View model={_model} dispatch={dispatch} />, document.getElementById(id)) } }
  3. Reactίϯϙʔωϯτ function View({ model, dispatch }) { return ( <div>

    <div> <input value={model.value} onInput={(e) => dispatch(changeValue(e.target.value))} /> <button onClick={() => dispatch(send())}>Send</button> </div> <ul> {model.posts.map((post, key) => (<li key={key}>{post}</li>))} </ul> </div> ) }
  4. ঢ়ଶߋ৽ؔ਺ function update(msg, model) { switch (msg.type) { case "ChangeValue":

    { model.value = msg.value return model } case "Send": { model.posts.push(model.value) model.value = "" return model } } }
  5. ςετ͸௨͍ͬͯΔͱ͠·͢ assert.deepEqual( update({ type: "ChangeValue", "foo" }, { value: "",

    posts: [] }), { value: "foo", posts: [] } ); // pass assert.deepEqual( update({ type: "Send" }, { value: "bar", posts: [] }), { value: "", posts: ["bar"] } ); // pass
  6. const model = { value: "", posts: [] } model

    = { value = "", posts = [] } ͜ͷΦϒδΣΫτͬΆ͍ͷ͸Recordͱݴ͍·ͯ͠ɺ ΄΅ΦϒδΣΫτͷΑ͏ʹ࢖͑·͢ Πϛϡʔλϒϧɾϥϒɺ஫ೖ
  7. function View({ model, dispatch }) { return ( <div> <div>

    <input value={model.value} onInput={(e) => dispatch(changeValue(e.target.value))} /> <button onClick={() => dispatch(send())}>Send</button> </div> <ul> {model.posts.map((post, key) => (<li key={key}>{post}</li>))} </ul> view model = div [] [ div [] [ input [ value model.value, onInput ChangeValue ] [] , button [ onClick Send ] [ text "Send" ] ] , ul [] (map (\post -> li [] [ text post ]) model.posts) ] ม਺ͬΆ͍Ͱ͕ؔ͢਺Ͱ͢ɻElmʹ͸ม਺͕͋Γ·ͤΜɻ `foo = bar`͸`var foo = bar`Ͱ͸ͳͯ͘`function foo() { return bar }`Ͱɺ `foo bar = bar ++ baz`͸`function foo(bar) { return bar + baz }`Ͱ͢
  8. function changeValue(value) { return { type: "ChangeValue", value } }

    function send() { return { type: "Send" } } type Msg = ChangeValue String | Send ͜Ε͸ϢχΦϯܕͱݴ͍·ͯ͠ɺ ܕ = ίϯετϥΫλ | ίϯετϥΫλ | ...ͱఆٛ͠·͢ɻ ίϯετϥΫλ͸ؔ਺ͱͯ͠࢖༻Ͱ͖·͢ɻ ͜͜Ͱ͸ߋ৽ϝοηʔδͱͯ͠࢖༻͠ɺ view͔Βupdateʹ౉͍ͯ͠·͢ɻ
  9. function update(msg, model) { switch (msg.type) { case "ChangeValue": {

    model.value = msg.value return model } case "Send": { model.posts.push(model.value) model.value = "" return model } update msg model = case msg of ChangeValue value -> { model | value = value } Send -> { value = "", posts = (model.posts ++ [ model.value ]) } Ϩίʔυͷߋ৽ํ๏͸͜Μͳײ͡Ͱɺ ৽͍͠ϨίʔυΛฦ͠·͢ɻ