求数组极值、方法封装、箭头函数
一、求数组极值
- 需求:求数组中的最大值和最小值
 
let ary = [1, 9, 18, 234, 23];
1. 先升序排序,排序后,数组的第一项就是最小值
ary.sort(function (a, b) {return a - b;});let min = ary[0];// 接着降序排列,排序后数组的第一项就是最大值;ary.sort(function (a, b) {return b - a;});
2. 假设法
- 求最小值:假设第一项就是最小值;
 
let min1 = ary[0];for (let i = 1; i < ary.length; i++) {ary[i] < min ? min = ary[i] : void 0;}console.log(min1);
- 求最大值:假设第一项最大值
 
let max1 = ary[0];for (let j = 0; j < ary.length; j++) {ary[j] > max1 ? max1 = ary[j] : void 0;}console.log(max1);
3. 排序算法
4. Math.max() 和 Math.min()
- Math.max() 从一堆数字中取出最大值
 - Math.min() 从一堆数字中取出最小值
 
let min3 = Math.min(2, 3, 5, 0, -1);let max3 = Math.max(12, 4, 1);console.log(min3);console.log(max3);
- ? 思考 ? 但是这个时候我们要处理的一个数组,但是 max 和 min 方法都是接收的一个一个的参数,有没有什么办法把数组变成一个一个的或者让 max 和 min 接受一个数组参数呢?
 - 把数组变成一个一个的
 
- ES6 扩展运算符 …对象
 
let min4 = Math.min(...ary); // ...ary -> 1, 9, 18, 234let max4 = Math.max(...ary); //console.log(min4);console.log(max4);
- 让 max 和 min 接受一个数组用 apply 方法:
 
let min5 = Math.min.apply(null, ary);let max5 = Math.max.apply(null, ary);console.log(min5);console.log(max5);
4.数组转成字符串 再使用 eval 求值
let aryStr = ary.toString();let min6 = eval(`Math.min(${aryStr})`);let max6 = eval(`Math.max(${aryStr})`);// eval() 方法是 js 解释器,可以把字符串转换成代码并执行
二、数组方法模拟实现
1. push 方法:向数组末尾追加项,返回数组的新长度
let ary = [1, 3, 5, 7];var r = ary.push(9);console.log(ary);console.log(r);
- push 原理:
 
Array.prototype.myPush = function () {// this 指向数组的实例for (let i = 0; i < arguments.length; i++) {this[this.length] = arguments[i];}return this.length;};let r2 = ary.myPush(11);console.log(ary);console.log(r2);
2. pop 原理:
Array.prototype.myPop = function () {// this 就是数组实例let last = this[this.length - 1];this.length--;return last;};let r3 = ary.myPop();console.log(r3);
3.forEach
Array.prototype.myForEach = function (callback) {for (let i = 0; i < this.length; i++) {callback(this[i], i);}};ary.myForEach(function (item, index) {console.log(item, index);});
4.map
Array.prototype.myMap = function (cb) {let newArr = [];for (let i = 0; i < this.length; i++) {let result = cb(this[i], i);newArr.push(result);}return newArr;};let r6 = ary.myMap(function (item, idx) {return item * 2;});console.log(r6);
作业:模拟实现 slice 方法
三、类数组转数组
- 类数组:有索引有 length 的对象;
常见的类数组:arguments、DOM 集合
因为类数组不是数组,没办法使用数组中的方法,操作起来不方便,那么有没有办法把类数组转成数组呢? 
常见的类数组转数组方法:
1. 准备一个空数组,遍历类数组,把类数组中的每一项 push 到新数组
function sum() {let ary = []; // 准备一个新数组// 遍历 argumentsfor (let i = 0; i < arguments.length; i++) {ary.push(arguments[i]);}console.log(ary);}sum(1, 2, 3, 4);
2. 扩展运算符(将 arguments 中的内容展开到一个新的数组中)
function sum2() {let ary = [...arguments];console.log(ary)}sum2(1, 4, 5, 7);
3. slice.call() 使用 call 借用数组 slice 方法复制一个数组
- Array.prototype.slice.call()
 - [].slice.call() 这种写法在 IE 低版本会报错
 
function sum3() {var ary = Array.prototype.slice.call(arguments); // 借用数组中的 slice 方法,在 slice 方法执行的时候把 slice 方法中的 this 修改成 arguments// var ary = [].slice.call(arguments); // 利用 [].slice 找到数组原型上的 slice 方法,然后把 slice 中的 this 修改成 argumentsconsole.log(ary)}sum3(2, 3, 4);
4. Array.from() ES6新增的方法,将类数组结构(类数组、iterator 对象)转换成数组
function sum4() {let ary = Array.from(arguments);console.log(ary);}sum4(1, 3, 4, 5);
方法封装与容错处理
- 封装一个将类数组转换成数组的方法
 - 版本1
 
function arrLikeToAry(arg) {return Array.from(arg);}
但是上面的代码有兼容性问题,因为 Array.from 是 ES6 新的方法,IE 低版本不兼容,一旦在 IE 低版本执行会报错,而js单线程,一旦报错后面的代码就不执行了,因此需要做容错处理:
JS的容错语句
try-catch 语句,会先 try,如果 try 过程中报错了,会捕获错误继续执行容错处理,而不会停止执行;
try {// 这里是尝试执行的语句;// 通常这里是第一方案} catch (e) {// 这里是异常情况的处理,如果上面// catch是捕获异常,异常信息// 上面代码执行报错后胡执行这里的代码,所以这里一般设置方案二console.log(e);}
- 版本2 改写方法
 
function arrLikeToAry(arg) {// 使用 try-catch 语句try {// 首先执行这里,如果浏览器支持 ES6,不会报错正常执行,下面的 catch 语句就不会执行了return Array.from(arg)} catch (e) {// 如果浏览器不支持 es6,就执行这里的代码,我们使用最原始的方式转数组console.warn(e);var ary = [];for (var i = 0; i < arg.length; i++) {ary.push(arg[i])}return ary;}}
箭头函数
- 箭头函数:ES6的新语法
 
function fe(a, b) {return a + b;}let add = (a, b) => {return a + b;};
注意事项:
- 函数体里面只有一行代码时,可以省略 return 和花括号
 
如果函数需要 return 一个对象时,对象需要用小括号包裹;
let sum = (a, b) => a + b;let getObj = (a, b) => ({a: a, b: b});
- 只有一个形参时,可以省略小括号
 
let say = msg => console.log(msg);
- 箭头函数里面没有 arguments,但是可以使用不定参数(剩余参数)
 
let allIn = (...arg) => {let total = 0;for (let i = 0; i < arg.length; i++) {total += arg[i];}return total;};
不定参数(剩余参数):在函数形参中 …形参名
- 不定参数是一个数组,可以使用数组方法
 - 不定参数可以用作非必传参数
 
let fn = (a, b, ...arg) => {console.log(arg);};fn(1, 2); // arg = []fn(1, 2, 3); // arg =[3]fn(1, 3, 5, 7, 9, 11); // arg = [5, 7, 9, 11]
- 箭头函数中的 thi s指向其声明时所在作用域中的 this;
原理:箭头函数没有自己的 this; 
- this 和 arguments 是两个特殊的变量,是在函数执行时 js 解析引擎传入给函数的,但是箭头函数执行时,解析引擎给箭头函数;
 - 箭头函数没有自己的 this,所以不能用作构造函数;
 - 箭头函数不能用 call、apply、bind 修改 this
 
四、utils 工具包封装
window.utils = (function () {function arrLikeToAry(args) {try {return Array.from(args);} catch (e) {var arr = [];for (var i = 0; i < args.length; i++) {arr.push(args[i])}return arr;}}return {arrLikeToAry // arrLikeToAry: arrLikeToAry}})();
【发上等愿,结中等缘,享下等福,择高处立,寻平处住,向宽处行】
