3 - forEach、filter、map使用与重写

259 阅读1分钟

知识点:

forEach、filter、map三者用法相同的地方:

语法:arr.forEach(callback(currentValue [, index [, array]])[, thisArg]);

用法:arr.forEach(function(){(elem, index, array)},thisArg);

  1. callback:为数组中每个元素执行的函数,该函数接收一至三个参数;
  2. elem:数组中正在处理的当前元素
  3. index:数组中正在处理的当前元素的索引
  4. array:forEach() 方法正在操作的数组
  5. thisArg:可选参数,可用来改变this指向;(这个参数可不填
  • 这里的this指向一个对象;
  • 如果是对象(例如:{name:'test'}),this就指向这个对象({name:'test');
  • 如果是number,string,boolean类型的,会强制转换成包装类
  • 如果是undefined、null类型的,this还是指向window

一、forEach()

1.1 页面布局:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>forEach、filter、map使用与重写</title>
</head>
<body>
<div id="data" class="data" style="display: none">
    [
    {"id":"1","course":"前端开发1","is_free":"1"},
    {"id":"2","course":"前端开发2","is_free":"0"},
    {"id":"3","course":"前端开发3","is_free":"1"}
    ]
</div>
<div class="list">
    <ul>
        <li></li>
        <li></li>
        <li></li>
    </ul>
</div>
</body>
</html>  

效果:

1.2 用forEach()将data中的数据渲染出来

<script type="text/javascript">
    var data = JSON.parse(document.getElementById('data').innerHTML), 
        oLi = document.getElementsByTagName('li');
    // forEach 遍历
    Array.prototype.forEach
    data.forEach(function (elem, index, array) {
        console.log('this', this); // li
        this[index].innerHTML = elem.course;
    }, oLi);
</script>

1.3 在原型上重写forEach()方法

//在原型上重写forEach()方法
Array.prototype.myForEach = function (fn) {
    var arr = this,  //保存要遍历的数组
        arrLen = arr.length, 
        arg2 = arguments[1] || window; //判断thisArg是否传值,不传默认指向window
    for (var i = 0; i < arrLen; i++) {
        fn.apply(arg2, [arr[i], i, arr]); //将this指向arg2,[]里面为参数
    }
}

1.4 调用重写后的forEach()方法

//调用原型上自定义的myForEach()
data.myForEach(function (elem, index, array) {
    console.log('elem', elem); // li
    this[index].innerHTML = elem.course;
}, oLi)

二、 filter() 筛选、过滤,返回一个新的数组

2.1 用filter()过滤出免费课程

var data = [
              {"id":"1","course":"前端开发1","is_free":"1"},
              {"id":"2","course":"前端开发2","is_free":"0"},
              {"id":"3","course":"前端开发3","is_free":"1"}
           ];
var newArr = data.filter(function (elem, index, array) {
    console.log(this); //window;
    return elem.is_free === '1';
}, false);
console.log(newArr);

2.2 在原型上重写filter()方法

Array.prototype.myFilter = function (fn) {
    var arr = this,
        arrLen = arr.length,
        arg2 = arguments[1] || window,
        newArr = [],
        item;
    for (var i = 0; i < arrLen; i++) {
        // 复制引用值的时候要用深拷贝,防止修改数据时,更改了原数组的数据
        item = deepClone(arr[i]); //深拷贝,deepClone()封装在utils.js中
        fn.apply(arg2, [arr[i], i, arr]) ? newArr.push(item) : '';
    }
    return newArr;
}

2.3 调用重写后的filter(方法

var fn = function (elem, index, array) {
    return elem.is_free === '0';
}
var newArr1 = data.myFilter(fn, false);
console.log(newArr1);

三、map()映射

3.1 用map()修改数据

var newArr = data.map(function (elem, index, array) {
    console.log(this)
    elem.course = this.name + elem.course; //在课程字段前面拼接【前端js++】
    return elem;
}, {name: '【前端js++】'});
console.log(newArr, data); //data的数据也被改变了

3.2 在原型上重写map方法

Array.prototype.myMap = function (fn) {
    var arr = this,
        arrLen = arr.length,
        arg2 = arguments[1] || window,
        newArr = [],
        item;
    for (var i = 0; i < arrLen; i++) {
        // 复制引用值的时候要用深拷贝,防止修改数据时,更改了原数组的数据
        item = deepClone(arr[i]); //深拷贝,deepClone()封装在utils.js中
        newArr.push(fn.apply(arg2, [arr[i], i, arr]));
    }
    return newArr;
}

3.3 调用重写后的map()方法

var fn = function (elem, index, array) {
    return this.name + elem.course; //在课程字段前面拼接【前端js++】
}
var newArr = data.myMap(fn, {name: '【前端js++】'});
console.log(newArr); //data中的数据不会被改变,因为复制的时候使用了深拷贝

4. 案例-tab切换列表

4.1 页面布局:

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>forEach、filter、map使用与重写</title>
</head>
<body>
<div id="J_data" class="data" style="display: none">
    [
    {"id":"1","course":"前端开发1","is_free":"1"},
    {"id":"2","course":"前端开发2","is_free":"0"},
    {"id":"3","course":"前端开发3","is_free":"1"}
    ]
</div>
<div class="J_nav">
    <a href="javascript:;" data-field="all">全课程</a>
    <a href="javascript:;" data-field="free">免课程</a>
    <a href="javascript:;" data-field="vip">VIP课程</a>
</div>
<div class="list">
    <ul class="J_list"></ul>
</div>
<script type="text/html" id="J_tpl">
    <li>{{course}}</li><hr />
</script>
</body>
</html>

效果:

4.2 css样式:

<style>
    .warp {
        margin: 100px;
    }

    .J_nav {
        height: 42px;
        line-height: 42px;
        background: #000;
        color: #fff;
        padding: 0 20px;
    }

    .J_nav::after {
        content: "";
        clear: both;
    }

    .J_nav a {
        display: block;
        float: left;
        color: #fff;
        margin-right: 20px;
        font-size: 14px;
    }

    .J_nav a.active {
        color: #409eff;
    }

    .list {
        margin-top: 20px;
    }

    .list li {
        height: 42px;
        line-height: 42px;
        border-bottom: 1px solid #eee;
        font-size: 14px;
    }
</style>

4.3 js代码:

<script type="text/javascript">
    ;(function () {
        var oNav = document.getElementsByClassName('J_nav')[0],
            oList = document.getElementsByClassName('J_list')[0],
            data = JSON.parse(document.getElementById('J_data').innerHTML),
            tpl = document.getElementById('J_tpl').innerHTML;
        var init = function () {
            oList.innerHTML = renderList(filterData(data, 'all')); //默认加载全部数据
            oNav.getElementsByTagName('a')[0].className = 'active';
            bindEvent();
        }

        function bindEvent() {
            //点击nav的事件委托
            oNav.addEventListener('click', navClick, false);
        }

        function navClick(e) {
            var e = e || window.event,
                tar = e.target || window.srcElement,
                tagName = tar.tagName.toLowerCase(), //将大写字母转换成小写
                oA = oNav.getElementsByTagName('a'), // 获取nav里的a标签的集合
                oNavLen = oA.length,
                item;
            if (tagName === 'a') {
                var field = tar.getAttribute('data-field'); //获取课程的类型
                oList.innerHTML = renderList(filterData(data, field));
                for (var i = 0; i < oNavLen; i++) {
                    item = oA[i];
                    item.className = '';
                }
                tar.className = 'active';
            }
        }

        // 列表渲染
        function renderList(data) {
            var list = '';
            data.forEach(function (elem, index, array) {
                list += tpl.replace(/{{(.*?)}}/g, function (node, key) {
                    return {
                        course: elem.course
                    } [key];
                })
            })
            return list;
        }

        //筛选对应的数据
        function filterData(data, field) {
            var arr = data.filter(function (elem, index, array) {
                switch (field) {
                    case 'all':
                        return true;
                        break;
                    case 'free':
                        return elem.is_free === '1';
                        break;
                    case 'vip':
                        return elem.is_free === '0';
                        break;
                    default:
                        return true;
                }
            })
            return arr;
        }

        init();
    })()
</script>