前言
PS: 2018/04/26 优化一下排版, 重新梳理一下方法, 补充一些信息, 删除 JQuery 库用法, 只讲解 Javascript 自带的,
for in
语句用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。主要用于枚举对象, 数组遍历效率最低的方法。
var ary = [1, 2, 3],
obj = {
name: 'Tom',
age: 18
},
i;
for (i in ary) {console.log(i);
}
for (i in obj) {console.log(obj[i]);
}
注意:
1, 遍历数组时, i 表示当前索引值,ary[i]对应的元素遍历对象时, i 表示 key 值, obj[i]表示 key 值对应的 value 值;
2, 跳出循环的方式有如下几种:return
函数执行被终止, break
循环被终止, continue
循环被跳过;
缺点:
1, 遍历所有属性包括原型链;
2, 忽略 enumerable 为 false 的属性;
// 构造函数
function Person() {this.name = 'mike';};
// 原型链属性
Person.prototype.age = 18;
// 实例赋值
var mike = new Person,
i;
mike.sex = 'man';
mike.height = '180';
// 设置不可枚举
Object.defineProperty(mike, 'height', {enumerable: false});
for (i in mike) {console.log(mike[i]);
}
优化方案:
hasOwnProperty:是用来判断一个对象是否有你给出名称的属性或对象。不过需要注意的是, 此方法无法检查该对象的原型链中是否具有该属性, 该属性必须是对象本身的一个成员;
// 构造函数
function Person() {this.name = 'mike';};
// 原型链属性
Person.prototype.age = 18;
// 实例赋值
var mike = new Person,
i;
mike.sex = 'man';
for (i in mike) {
// 过滤出对象自身的属性
if (mike.hasOwnProperty(i)) {console.log(mike[i]);
}
}
注意: 这里依然会遍历所有属性, 只是过滤出操作属性而已
For
循环可以将代码块执行指定的次数。
var ary = [1, 2, 3],
i = 0,
len = ary.length;
for (; i < len; i++) {console.log(ary[i]);
}
注意:
1, (如果使用 var 声明的话),for 循环中的 i 在循环结束之后依然存在于作用域中, 为了避免影响作用域中的其他变量, 通常使用闭包或其他方式做处理
2, 避免使用 for(var i=0, len = ary.length;i < len; i++){} 的方式, 数组长度每次循环都被计算, 效率低。将变量声明放在 for 的前面来执行
3, 跳出循环的方式有如下几种:return
函数执行被终止, break
循环被终止, continue
循环被跳过;
有种稍高逼格写法:
var ary = [1, 2, 3],
i = ary.length - 1;
for (; i <= 0; i--) {console.log(ary[i]);
}
不考虑顺序情况下还不错, 少一个变量并且能唬到一些新手
forEach(function(currentValue, index, arr), thisValue)
按照原始数组元素顺序依次处理元素.
参数 | 描述 |
---|---|
function(currentValue, index, arr) | 匿名函数, 默认传参第 1 个是遍历的数组内容;第 2 个是对应的数组索引, 第 3 个是数组本身 |
thisValue | 可选。对象作为该执行回调时使用, 传递给函数, 用作 “this” 的值。如果省略了 thisValue , “this” 的值为 “undefined” |
注意: forEach() 对于空数组是不会执行回调函数的。
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9];
ary.forEach(function (_ele, _index, _ary) {console.log(_ele, _index, _ary);
})
// 1 0 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 2 1 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 3 2 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 4 3 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 5 4 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 6 5 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 7 6 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 8 7 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 9 8 [1, 2, 3, 4, 5, 6, 7, 8, 9]
简单实现兼容写法:
Array.prototype._forEach = function (callback, context) {
// 指定指向, 默认 window
context = context || window;
// 浏览器支持直接调用方法, 终止后续操作
if ('forEach' in Array.prototype) {this.forEach(callback, context);
return;
}
// 保证回调函数
if (typeof callback !== 'function') throw 'callback must be a function'
// 遍历数组, 设置指向
var i = 0,
len = this.length;
for (; i < len; i++) {callback.call(context, this[i], i, this)
}
}
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9];
ary._forEach(function (_ele, _index, _ary) {console.log(_ele, _index, _ary);
})
map(function(currentValue,index,arr), thisValue)
按照原始数组元素顺序依次处理元素并返回一个新数组, 数组中的元素为原始数组元素调用函数处理后的值。
参数 | 描述 |
---|---|
function(currentValue, index, arr) | 匿名函数, 默认传参第 1 个是遍历的数组内容;第 2 个是对应的数组索引, 第 3 个是数组本身 |
thisValue | 可选。对象作为该执行回调时使用, 传递给函数, 用作 “this” 的值。如果省略了 thisValue , “this” 的值为 “undefined” |
注意: map() 对于空数组是不会执行回调函数的。
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var _ary = ary.map(function (_ele, _index, _ary) {console.log(_ele, _index, _ary);
return _ele * 2
})
console.log('原数组:' + ary);
console.log('返回数组:' + _ary);
// 1 0 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 2 1 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 3 2 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 4 3 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 5 4 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 6 5 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 7 6 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 8 7 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 9 8 [1, 2, 3, 4, 5, 6, 7, 8, 9]
// 原数组:1,2,3,4,5,6,7,8,9
// 返回数组:2,4,6,8,10,12,14,16,18
简单实现兼容写法:
Array.prototype._map = function (callback, context) {
// 指定指向, 默认 window
context = context || window;
// 浏览器支持直接调用方法, 终止后续操作
if ('map' in Array.prototype) {return this.map(callback, context);
}
// 保证回调函数
if (typeof callback !== 'function') throw 'callback must be a function'
// 遍历数组, 返回操作过的数组
var _ary = [],
i = 0,
len = this.length;
for (; i < len; i++) {_ary[i] = callback.call(context, this[i], i, this);
}
return _ary;
}
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9],
_ary = ary._map(function (_ele, _index, _ary) {return _ele * 10});
console.log('原数组:' + ary);
console.log('返回数组:' + _ary);
filter(function(currentValue,index,arr), thisValue)
使用指定的函数测试所有元素, 并创建一个包含所有通过测试的元素的新数组。
参数 | 描述 |
---|---|
function(currentValue, index, arr) | 匿名函数, 默认传参第 1 个是遍历的数组内容;第 2 个是对应的数组索引, 第 3 个是数组本身 |
thisValue | 可选。对象作为该执行回调时使用, 传递给函数, 用作 “this” 的值。如果省略了 thisValue , “this” 的值为 “undefined” |
注意: filter() 对于空数组是不会执行回调函数的。
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9],
_ary = ary.filter(function (_ele, _index, _ary) {return _ele < 5});
console.log('原数组:' + ary);
console.log('返回数组:' + _ary);
// 原数组:1,2,3,4,5,6,7,8,9
// 返回数组:1,2,3,4
简单实现兼容写法:
Array.prototype._filter = function (callback, context) {
// 指定指向, 默认 window
context = context || window;
// 浏览器支持直接调用方法, 终止后续操作
if ('filter' in Array.prototype) {return this.filter(callback, context);
}
// 保证回调函数
if (typeof callback !== 'function') throw 'callback must be a function'
// 遍历数组, 返回操作过的数组
var _ary = [],
i = 0,
len = this.length;
for (; i < len; i++) {if (callback.call(context, this[i], i, this)) {_ary.push(this[i])
}
}
return _ary;
}
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9],
_ary = ary._filter(function (_ele, _index, _ary) {return _ele & gt; 3});
console.log('原数组:' + ary);
console.log('返回数组:' + _ary);
every(function(currentValue,index,arr), thisValue)
用于检测数组所有元素是否都符合指定条件, 返回布尔值.
参数 | 描述 |
---|---|
function(currentValue, index, arr) | 匿名函数, 默认传参第 1 个是遍历的数组内容;第 2 个是对应的数组索引, 第 3 个是数组本身 |
thisValue | 可选。对象作为该执行回调时使用, 传递给函数, 用作 “this” 的值。如果省略了 thisValue , “this” 的值为 “undefined” |
注意: every() 对于空数组是不会执行回调函数的。
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9],
bol = ary.every(function (_ele, _index, _ary) {return _ele < 5});
console.log(bol); // false
简单实现兼容写法:
Array.prototype._every = function (callback, context) {
// 指定指向, 默认 window
context = context || window;
// 浏览器支持直接调用方法, 终止后续操作
if ('every' in Array.prototype) {return this.every(callback, context);
}
// 保证回调函数
if (typeof callback !== 'function') throw 'callback must be a function'
// 遍历数组, 返回操作过的数组
var _ary = [],
i = 0,
len = this.length;
for (; i < len; i++) {if (callback.call(context, this[i], i, this)) {return false;}
}
return true;
}
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9],
bol = ary._every(function (_ele, _index, _ary) {return _ele & gt; 5});
console.log(bol);
reduce/reduceRight(function(previousValue, currentValue, currentIndex, array), initialValue)
reduce 对数组中的所有元素调用指定的回调函数。该回调函数的返回值为累积结果, 并且此返回值在下一次调用该回调函数时作为参数提供。
reduceRight 反向操作.
参数 | 描述 |
---|---|
function(previousValue, currentValue, currentIndex, array) | previousValue:通过上一次调用回调函数获得的值。如果向 reduce 方法提供 initialValue, 则在首次调用函数时, previousValue 为 initialValue。currentValue:当前数组元素的值。currentIndex:当前数组元素的数字索引。array:包含该元素的数组对象。 |
initialValue | 可选。传递给函数的初始值, |
注意: reduce() 对于空数组是不会执行回调函数的。
先来打印看看里面的传参和没初始值的情况:
var ary = [1, 2, 3, 4],
sum = ary.reduce(function (previousValue, currentValue, currentIndex, array) {console.log(previousValue, currentValue, currentIndex, array);
return previousValue + currentValue
});
console.log(sum);
// 1 2 1 [1, 2, 3, 4]
// 3 3 2 [1, 2, 3, 4]
// 6 4 3 [1, 2, 3, 4]
// 10
var ary = [1, 2, 3, 4],
sum = ary.reduce(function (previousValue, currentValue, currentIndex, array) {console.log(previousValue, currentValue, currentIndex, array);
return previousValue + currentValue
}, 10);
console.log(sum);
// 10 1 0 [1, 2, 3, 4]
// 11 2 1 [1, 2, 3, 4]
// 13 3 2 [1, 2, 3, 4]
// 16 4 3 [1, 2, 3, 4]
// 20
两者区别在于多了一层运算, 文档说明如下
在第一次调用回调函数时, 作为参数提供的值取决于 reduce 方法是否具有 initialValue 参数。
1, 有:
1) previousValue 参数为 initialValue。2) currentValue 参数是数组中的第一个元素的值。
2, 没有:
1) previousValue 参数是数组中的第一个元素的值。2) currentValue 参数是数组中的第二个元素的值。
简单实现兼容写法:
Array.prototype._reduce = function (callback, initValue) {
// 浏览器支持直接调用方法, 终止后续操作
if ('reduce' in Array.prototype) {this.reduce(callback, context);
return;
}
// 保证回调函数
if (typeof callback !== 'function') throw 'callback must be a function'
// 遍历数组, 设置指向
var add = initValue || this.unshift(initValue),
i = 0,
len = this.length;
for (; i < len; i++) {add = callback.call(null, add, this[i], i, this)
}
}
var ary = [1, 2, 3, 4],
sum = ary.reduce(function (previousValue, currentValue, currentIndex, array) {return previousValue + currentValue}, 20);
console.log(sum);
entries(), keys()和 values()
它们都返回一个遍历器对象, 可以用 for…of 循环进行遍历, 唯一的区别是 keys()是对键名 / 索引值的遍历、values()是对键值的遍历, entries()是对键 / 索引值值对的遍历
var ary = [1, 2, 3, 4];
for (let elem of ary.keys()) {console.log(elem);
}
for (let elem of ary.values()) {console.log(elem);
}
for (let elem of ary.entries()) {console.log(elem);
}
写到这里就差不多了,ES5 还有壹些筛选方法例如 find(), includes()等其实都是大同小异就不继续写了,ES6 还会涉及到叠代器的知识点, 大家有兴趣自行研究吧.