知识点:
forEach、filter、map三者用法相同的地方:
语法:arr.forEach(callback(currentValue [, index [, array]])[, thisArg]);
用法:arr.forEach(function(){(elem, index, array)},thisArg);
- callback:为数组中每个元素执行的函数,该函数接收一至三个参数;
- elem:数组中正在处理的当前元素;
- index:数组中正在处理的当前元素的索引;
- array:forEach() 方法正在操作的数组;
- 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>