奇舞javaScript 第零课程

推荐书籍: javascript高级程序设计 和犀牛书

版本1

    <ul id="user-list">
        <li>001</li>
        <li>002</li>
        <li>003</li>
        <li>004</li>
    </ul>
    body {
        background-color: white;
        font-size: 24px;
    }

    #user-list {
        line-height: 1.5em;
    }

    #user-list>li:hover {
        background-color: rgba(0, 0, 0, .3);
    }
    let list = document.querySelector('#user-list')
    let items = list.querySelectorAll('#user-list > li');

    list.addEventListener('click', function(e) {
        if (e.target.tagName === 'LI') {
            let item = e.target;
            items.forEach(function(item) {
                item.style.background = 'inherit';
                item.style.color = 'inherit'
            });
            item.style.background = 'black';
            item.style.color = 'white';

            console.log(item.innerHTML);

        }
    })

版本2

    <ul id="user-list">
        <li>001</li>
        <li>002</li>
        <li>003</li>
        <li>004</li>
    </ul>
    body {
        background-color: white;
        font-size: 24px;
    }

    #user-list {
        line-height: 1.5em;
    }

    #user-list>li:hover {
        background-color: rgba(0, 0, 0, .3);
    }

    #user-list>li.active {
        background-color: black;
        color: white;
    }
    let list = document.querySelector('#user-list')
    let items = list.querySelectorAll('#user-list > li');

    list.addEventListener('click', function(e) {
        if (e.target.tagName === 'LI') {
            let item = e.target;
            items.forEach(function(item) {
                item.className = '';
            });
            item.className = "active";
            console.log(item.innerHTML);

        }
    })

版本3

    <ul id="user-list">
        <li>
            <input type="radio" name="item" id="item0" value="001">
            <label for="item0">001 </label>
        </li>
        <li>
            <input type="radio" name="item" id="item1" value="002">
            <label for="item1">002</label>
        </li>
        <li>
            <input type="radio" name="item" id="item2" value="003">
            <label for="item2">003</label>
        </li>
        <li>
            <input type="radio" name="item" id="item3" value="004">
            <label for="item3">004</label>
        </li>
    </ul>
    * {
        margin: 0;
        padding: 0;
    }

    body {
        background-color: white;
        font-size: 24px;
    }

    #user-list {
        line-height: 1.5em;
    }

    #user-list input {
        display: none;
    }

    #user-list label {
        display: block;

    }

    #user-list>li:hover {
        background-color: rgba(0, 0, 0, .3);
    }

    #user-list input:checked+label {
        background-color: black;
        color: white;
    }
    let list = document.querySelector('#user-list')
    list.addEventListener('click', function(e) {
        if (e.target.tagName === 'INPUT') {
            let chedkedItem = list.querySelector('input:checked');
            console.log(chedkedItem.value);
        }
    })

思考 ?

写javaScript 操作DOM 要注意什么?
javaScript 与HTML CSS 的指责如何分离?
在复杂性放在那一头 ,为什么?

问题2:API的设计

三个状态红(stop)绿(pass) 黄(wait)表示

要求用javaScript 让三个状态轮流切换

每个状态停留时间2秒

版本1

    <ul id="traffic" class="wait">
        <li> <span></span> </li>
        <li> <span></span> </li>
        <li> <span></span> </li>
    </ul>
    #ttraffic>li {
        display: block;
    }

    #traffic span {
        display: inline-block;
        width: 50px;
        height: 50px;
        background-color: gray;
        margin: 5px;
        border-radius: 50%;
    }

    #traffic.stop li:nth-child(1) span {
        background-color: #a00;
    }

    #traffic.wait li:nth-child(2) span {
        background-color: #aa0;
    }

    #traffic.pass li:nth-child(3) span {
        background-color: #0a0;
    }
 const traffic =document.getElementById("roundness");
       (function reset() {
          traffic.className = "wait";
            setTimeout(function(){
               traffic.className="stop";
               setTimeout(function(){
                traffic.className="pass";
                 setTimeout(reset,2000);
               },2000)
            },2000)
       })()

版本1 的问题?
如果需求增加到5盏,10盏灯?

过程耦合 + Callback Hell 。。。差评 !!!

版本2

 const traffic = document.getElementById('traffic');
    var stateList = ['wait', 'stop', 'pass'];
    var currentStateIndex = 0;
    setInterval(function() {
        var state = stateList[currentStateIndex]
        traffic.className = state;
        currentStateIndex = (currentStateIndex + 1) % stateList.length;
    }, 2000)

依赖外部变量 stateList currentStateIndex

封装行不好。。。差评!!

版本3

const traffic = document.getElementById('traffic');
     function start(traffic, stateList) {
         var currentStateIndex = 0;
         setInterval(function () {
             var state = stateList[currentStateIndex]
             traffic.className = state;
             currentStateIndex = (currentStateIndex + 1 ) % stateList.length
         },2000)
     }

     start(traffic, ['wait','stop', 'pass']);

虽然中规中矩
但其实可复用性差!

版本4

    const traffic = document.getElementById('traffic');

    function poll(...fnList) {
        let stateIndex = 0;
        return function(...args) {
            let fn = fnList[stateIndex++ % fnList.length];
            return fn.apply(this, args);
        }
    }

    function setState(state) {
        traffic.className = state;
    }

    let trafficStatePoll = poll(setState.bind(null, 'wait'),
                                setState.bind(null, 'stop'),
                                setState.bind(null, 'pass'))

 setInterval(trafficStatePoll, 2000);



    function a() { return 1;}
    function b() { return 0;}

     var toggle = poll(a,b);

    console.log([toggle(),toggle(),toggle()]) //[1,0,1]

版本4 函数式 变成 抽象出poll 方法

需求更改

wait stop pass 状态时间不想等 风别改成 1秒 2秒 3秒

版本5 Promise 解决问题 抽象wait 方法

    const traffic = document.getElementById('traffic');

    function wait(time) {
        return new Promise(resolve => setTimeout(resolve, time));
    }

    function setState(state) {
        traffic.className = state;
    }

    function reset() {
        Promise.resolve()
            .then(setState.bind(null, 'wait'))
            .then(wait.bind(null, 1000))
            .then(setState.bind(null, 'stop'))
            .then(wait.bind(null, 2000))
            .then(setState.bind(null, 'pass'))
            .then(wait.bind(null, 3000))
            .then(reset)
    }

    reset()

版本6

    const trafficEl = document.getElementById('traffic');

    function TrafficProtocol(el, reset) {
        this.subject = el;
        this.autoReset = reset;
        this.stateList = []
    }

    TrafficProtocol.prototype.putState = function(fn) {
        this.stateList.push(fn);
    }

    TrafficProtocol.prototype.reset = function() {
        let subject = this.subject;

        this.setStatePromise = Promise.resolve();
        this.stateList.forEach((stateFn) => {
            this.setStatePromise = this.setStatePromise.then(() => {
                return new Promise(resolve => {
                    stateFn(subject, resolve)
                })
            })
        })
        if (this.autoReset) {
            this.setStatePromise.then(this.reset.bind(this));
        }
    }

    TrafficProtocol.prototype.start = function() {
        this.reset();
    }
    var traffic = new TrafficProtocol(trafficEl, true);

    traffic.putState(function(subject, next) {
        subject.className = 'wait';
        setTimeout(next, 1000)
    })
    traffic.putState(function(subject, next) {
        subject.className = 'stop';
        setTimeout(next, 2000)
    })
    traffic.putState(function(subject, next) {
        subject.className = 'pass';
        setTimeout(next, 3000)
    })
    traffic.start();

优点:面向对象 函数式 Promise 灵活可扩展
缺点 :复杂度 实现难度 是否过度设计
设计是把双刃剑
写代码简单
程序设计不易
且行且珍惜

问题3 javaScript 的’效率问题’?

给你一个很大的数组 ,数组里面有许多整数,用javaScript实现一个函数 要求
将数组之和为10的每一对数配对并找出,返回这些数配合对后的数组

例如 :[11,3,8,9,7,-1,1,2,4,…]
得到 : [[11,-1],[3,7],[8,2],[9,1]]

版本1

var  list = [11,4,9,3,-1,6,7,9,13]

    function map (list) {
      let ret = [] ,len = list.length;
      for(let i = 0 ;i <len;i++  ){
         for(let j=i+1;j<len;j++ ){
           if (list[i]+ list[j] ==10) {
             ret.push([list[i], list[j]])
           }
         }

      }
      return ret;
    }
    console.log(JSON.stringify(map(list)))

版本2

    var list = [11, 4, 9, 3, -1, 6, 7, 9, 13]

    function map(list) {
        let ret = [];
        list = list.sort((a, b) => a - b);

        for (let i = 0, j = list.length - 1; i < j;) {
            let a = list[i],
                b = list[j];

            if (a + b === 10) {
                ret.push([a, b]);
                i++;
                j--
            } else if (a + b < 10) {
                i++
            } else {
                j--
            }
        }
        return ret;
    }
    console.log(JSON.stringify(map(list)))

为什么版本2 比版本1 快很多
还有没有别的解发?

总结

这一课 我们学习了什么?

怎么写好的代码
1:代码职责
2:花时间思考问题API
3:好的算法

补充

在动态脚本语言中 函数是javaScript最核心的内容精髓

    function setColor(color, el) {
        el.style.color = color;
    }

正常情况下是这样调用

    setColor('red', content)

现在我们想这样调用

    setColor(content,'red')

方案一 重新写一个

    function setColor2(el, color) {
        el.style.color = color;
    }

方案2 调用

    function setColor2(el, color) {
        setColor(color, el);
    }

方案3 抽象过程

    function reverseArgs(fn) {
        return function(...args) {
            args = args.reverse();
            return fn.apply(this, args)
        }
    }
    setColor = reverseArgs(setColor);

100 毫秒延时执行的组合函数

  function delay(fn, time) {
     return function (...args) {
         setTimeout(fn.bind(this, ...args), time);
     }
  }
    setColor = delay(reverseArgs(setColor),1000)
var wait500 = reverseArgs(setTimeout).bind(null, 500)

 wait500(()=> console.log('message'));

数据抽象 用函数来解决数据问题
过程抽象 用函数来解决函数计算问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值