前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • JavaScript Part 1

    • Ajax总结篇
    • Canvas 绘制八大行星
    • DOM编程之API学习总结篇
    • JavaScript事件机制
    • JavaScript代码片段100个
    • JavaScript作用域分析总结
    • JavaScript原型链回顾
    • JavaScript及jQuery中的各种宽高属性图解
    • JavaScript工程项目的一系列最佳实践
    • JavaScript常用API合集
    • JavaScript数组、字符串、对象常用方法
    • JavaScript数组方法总结篇
    • JavaScript深浅拷贝
    • JavaScript运动框架之速度时间版本
    • JavaScript运行机制Event Loop
    • JavaScript防抖节流原理
    • Javascript中的复制粘贴功能
    • Javascript数组详解
    • OOP之原型与原型链
    • Object.defineProperty详解
    • V8源码浅析JS数组常见方法
      • Array基础
        • 创建一个数组
        • 构造函数上的方法
          • Array.of()
          • Array.isArray()
          • Array.from()
            • 参数
            • 用法
            • 思路
      • 常见方法
        • 遍历方法
          • forEach()
          • every()
          • some
          • filter
          • map
          • reduce
          • reduceRight
          • find findIndex
          • keys & values & entries
        • 改变原始数组方法
          • splice
          • sort
          • pop
          • shift
          • unshift
          • push
          • reverse
          • copyWithin
          • fill
        • 不改变原始数组方法
          • slice
          • join
          • toString
          • concat
          • indexOf
          • lastIndexOf
    • await 在 forEach 中不生效解决方案
    • iframe+表单跨域提交POST请求
    • javascript笔记总结篇
    • 业务中处理数据结构常用的JS方法
    • 作用域
    • 你真的掌握变量和类型了吗
    • 前后端分离之数据Mock
    • 原型与原型链
    • 原生JS补给(上)
    • 如何写出一个惊艳面试官的深拷贝
    • 带你填一些JS容易出错的坑
    • 彻底弄懂 JavaScript 执行机制
    • 执行上下文 执行栈
    • 正则回顾总结
    • 正则基础知识
    • 正则完整篇
    • 正则表达式
    • 浅析Promise原理
    • 浅谈JavaScript中的异步处理
    • 深拷贝 vs 浅拷贝
    • 聊一聊typeof instanceof 实现原理.
    • 聊一聊闭包
    • 高阶函数map reduce filter
  • JavaScript Part 2

  • CSS

  • HTML

  • Jquery

  • ES6

  • 小程序

  • Vue

  • React

  • 深入React

  • React Native

  • NodeJS

  • Angular

  • TypeScript

  • Webpack

  • 浏览器

  • 移动端

  • 前端工程化

  • Electron

  • HTTP

  • Nginx

  • Linux

  • 数据结构与算法

  • LeetCode算法题

  • 综合

完整面试题地址:
作者:程序员poetry
扫码关注作者公众号:「前端进阶之旅」 每天分享技术干货
前端进阶之旅公众号二维码

V8源码浅析JS数组常见方法|博客系列

# Array基础

要想手写数组方法,先补一补基础,得先会使用它们api

# 创建一个数组

			//字面量
            let demo = [1, 2, 3]
            // 构造器
            let demo1 = Array(),
                demo2 = Array(3),
                demo3 = Array(1,2,3),
                demo4 = new Array(1,2,3);
@前端进阶之旅: 代码已经复制到剪贴板

# 构造函数上的方法

# Array.of()

简单理解就是创建一个新数组的实例,可以看看与Array构造函数区别

语法:

Array.of(element0[, element1[, ...[, elementN]]])
@前端进阶之旅: 代码已经复制到剪贴板

用法:

Array.of(7);       // [7] 
Array.of(1, 2, 3); // [1, 2, 3]

Array(7);          // [ , , , , , , ]
Array(1, 2, 3);    // [1, 2, 3]
@前端进阶之旅: 代码已经复制到剪贴板

两者区别:Array.of(7) 创建一个具有单个元素 7 的数组,而 Array(7) 创建一个长度为7的空数组(**注意:**这是指一个有7个空位(empty)的数组,而不是由7个undefined组成的数组)。


# Array.isArray()

Array.isArray() 用于确定传递的值是否是一个 Array。

Array.isArray([1, 2, 3]);  
// true
Array.isArray({foo: 123}); 
// false
Array.isArray("foobar");   
// false
Array.isArray(undefined);  
// false
@前端进阶之旅: 代码已经复制到剪贴板

手动实现

			// Array.isArray
            if(!Array.isArray){
                Array.isArray = obj => Object.prototype.toString.call(obj) === '[object Array]'
            }
@前端进阶之旅: 代码已经复制到剪贴板

判断JS数据类型,可以看看我之前写的博客 聊一聊typeof instanceof 实现原理


# Array.from()

Array.from() 方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。

Array.from(arrayLike[, mapFn[, thisArg]])
@前端进阶之旅: 代码已经复制到剪贴板
# 参数
  • arrayLike: 必选,可以传入 1、类数组(argumentg) 2、可迭代对象(set,map)。
  • mapFn: 可选,相当于Array.from(arrayLike).map(mapFn, thisArg)。
  • thisArg: 可选,执行回调函数mapFn时候的this对象。非常有用,利于解耦。可以把被处理的数据和对象分离,thisArg中定义处理函数handle,用来在mapFn中返回调用handle之后的结果。
# 用法

String

			// Array.from()
            const demo = Array.from('123')
            console.log(demo) //[ 'a', 'b', 'c' ]
@前端进阶之旅: 代码已经复制到剪贴板

new Set()

			const Array_demo = Array.from(new Set([1,2,3,4,1,2,3]))
            console.log(Array_demo)  // [1,2,3,4]
@前端进阶之旅: 代码已经复制到剪贴板

new Map()

const map = new Map([[1, 2], [2, 4], [4, 8]]);
Array.from(map);
// [[1, 2], [2, 4], [4, 8]]
@前端进阶之旅: 代码已经复制到剪贴板

类数组

const fn = (function() {
    const demo = Array.from(arguments);
    console.log(demo);
})(1,2,3); // [ 1, 2, 3 ]
@前端进阶之旅: 代码已经复制到剪贴板

数组去重合并

			let fn = function () {
                console.log(arguments)
                const Arr_new = [].concat.apply([],arguments)
                return Array.from(new Set(Arr_new))
            }
            const   demo1 = [1, 2, 3, 4],
                    demo2 = [4,5,6,2,2,2],
                    demo3 = [1,2,3,4,2,2,3,4];
            console.log(fn(demo1,demo2,demo3))
            // [1,2,3,4,5,6]
@前端进阶之旅: 代码已经复制到剪贴板

充分利用第三个参数thisArg

		const obj = {
            handle: x => x * 4 
        }
        console.log(Array.from([11, 22, 33], function (x) {
            return this.handle(x)
        }, obj))
        // [44, 88, 132]
@前端进阶之旅: 代码已经复制到剪贴板
# 思路
  • 判断arrayLike是否为空
  • 根据mapFn判断是否为构造函数,为构造函数,每次遍历时,让arr[i] = mapFn(iValue,i), 不是构造函数时,arr[i] = iValue
  • 判断thisArg是否存在,存在的话 arr[i] = mapFn.call(thisArg, iValue,i)

参考源码在V8中 array.js第1763行开启Array.from之旅

		/**
         * 实现Array.from
         * toInteger方法:返回一个整数
         * toLength方法: 保证len数字合法[0~Number.MAX_SAFE_INTEGER]
         * Number.MAX_SAFE_INTEGER = Math.pow(2,53) - 1
         * 判断arrayLike 为 空 抛出错误
         * mapFn非空并且不是构造函数抛出错误
         * 每次遍历arrayLike,如果mapFn存在, arr[i] = mapFn(iValue,i) 不存在的话 arr[i] = iValue
         * 判断thisArg是否存在,存在的话 arr[i] = mapFn.call(thisArg, iValue,i)
         * */
        Array.myfrom = (function () {
            const toStr = Object.prototype.toString
            const isCallable = fn => typeof fn === 'function' || toStr.call(fn) === '[object Function]'
            
            const toInteger = value => {
                const v = Number(value)
                if(isNaN(v))    return 0
                // 无穷大或者0 直接返回
                if(v === 0 || !isFinite(v)) return v
                return (v > 0 ? 1 : -1) * Math.floor(Math.abs(v))
            }
            // 最大的范围Number.MAX_SAFE_INTEGER
            const maxSafeInteger = Number.MAX_SAFE_INTEGER
            
            const toLength = value => {
                const len = toInteger(value)
                return Math.min(maxSafeInteger, Math.max(0, len))
            }
            return function myfrom (arrayLike/*, mapFn, thisArg*/) {
                const that = this
                if(arrayLike === null) throw new TypeError("Array.from requires an array-like object - not null or undefined")
                
                const items = Object(arrayLike)
                let thisArg = ''
                // 判断mapFn是否undefined, 这里最好不要直接使用undefined,因为undefined不是保留字,
                // 很有可能undefined是个值  最好用 void 0 或者 void undefined 
                const mapFn = arguments.length > 1 ? arguments[1] : void 0
                if( typeof mapFn !== 'undefined') {
                    // 接下来判断第二个参数是不是构造函数
                    if( !isCallable(mapFn) ) throw new TypeError("Array.from when provided mapFn must be a function")
                    if( arguments.length > 2) thisArg = arguments[2]
                }
                const len = toLength(items.length)
                const arr = isCallable(that) ? Object(new that(len)) : new Array(len)

                let i = 0,
                    iValue;
                while ( i < len) {
                    iValue = items[i]
                    if(mapFn) arr[i] = typeof thisArg === 'undefined' ? mapFn(iValue,i) : mapFn.call(thisArg, iValue, i)
                    else 
                        arr[i] = iValue
                    i++
                }
                arr.length = len
                return arr
            }
        })()
@前端进阶之旅: 代码已经复制到剪贴板

👍不得不说,把Array.from()实现出来后,其实收获很多东西的。


# 常见方法

为了简单记忆,方便查找,将主要方法分为三类 : 数组可遍历方法,会修改原数组方法,返回新数组方法。

# 遍历方法

js中遍历数组并不会改变原始数组的方法总共有12个:

 	ES5:
    forEach、every 、some、 filter、map、reduce、reduceRight、
    ES6:
    find、findIndex、keys、values、entries
@前端进阶之旅: 代码已经复制到剪贴板

# forEach()

语法:

    array.forEach(callback(currentValue, index, arr), thisArg)
@前端进阶之旅: 代码已经复制到剪贴板

参数:

 callback:为数组中每个元素执行的函数,该函数接收一至三个参数
 		  currentValue 数组中正在处理的当前元素
 		  index (可选)  数组中正在处理的当前元素的索引
 		  arr (可选)    forEach() 方法正在操作的数组
 thisArg      可选参数,当执行回调函数callback,用作this值
@前端进阶之旅: 代码已经复制到剪贴板

讲一讲thisArg用法吧

← Object.defineProperty详解await 在 forEach 中不生效解决方案 →

fe
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片NEW
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 业务场景题真实业务问题与追问
  • 查漏补缺常见问题解析
  • AI 模拟面试NEW模拟真实面试 + 报告
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
    • AI 定制路线NEW按你的简历现排
    • AI 知识地图NEW串起全站知识点
  • 动态
    • AI 热点NEWAI 每日动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
AI 助手NEW
旧版
  • JavaScript Part 1

    • Ajax总结篇
    • Canvas 绘制八大行星
    • DOM编程之API学习总结篇
    • JavaScript事件机制
    • JavaScript代码片段100个
    • JavaScript作用域分析总结
    • JavaScript原型链回顾
    • JavaScript及jQuery中的各种宽高属性图解
    • JavaScript工程项目的一系列最佳实践
    • JavaScript常用API合集
    • JavaScript数组、字符串、对象常用方法
    • JavaScript数组方法总结篇
    • JavaScript深浅拷贝
    • JavaScript运动框架之速度时间版本
    • JavaScript运行机制Event Loop
    • JavaScript防抖节流原理
    • Javascript中的复制粘贴功能
    • Javascript数组详解
    • OOP之原型与原型链
    • Object.defineProperty详解
    • V8源码浅析JS数组常见方法
      • Array基础
        • 创建一个数组
        • 构造函数上的方法
          • Array.of()
          • Array.isArray()
          • Array.from()
            • 参数
            • 用法
            • 思路
      • 常见方法
        • 遍历方法
          • forEach()
          • every()
          • some
          • filter
          • map
          • reduce
          • reduceRight
          • find findIndex
          • keys & values & entries
        • 改变原始数组方法
          • splice
          • sort
          • pop
          • shift
          • unshift
          • push
          • reverse
          • copyWithin
          • fill
        • 不改变原始数组方法
          • slice
          • join
          • toString
          • concat
          • indexOf
          • lastIndexOf
    • await 在 forEach 中不生效解决方案
    • iframe+表单跨域提交POST请求
    • javascript笔记总结篇
    • 业务中处理数据结构常用的JS方法
    • 作用域
    • 你真的掌握变量和类型了吗
    • 前后端分离之数据Mock
    • 原型与原型链
    • 原生JS补给(上)
    • 如何写出一个惊艳面试官的深拷贝
    • 带你填一些JS容易出错的坑
    • 彻底弄懂 JavaScript 执行机制
    • 执行上下文 执行栈
    • 正则回顾总结
    • 正则基础知识
    • 正则完整篇
    • 正则表达式
    • 浅析Promise原理
    • 浅谈JavaScript中的异步处理
    • 深拷贝 vs 浅拷贝
    • 聊一聊typeof instanceof 实现原理.
    • 聊一聊闭包
    • 高阶函数map reduce filter
  • JavaScript Part 2

  • CSS

  • HTML

  • Jquery

  • ES6

  • 小程序

  • Vue

  • React

  • 深入React

  • React Native

  • NodeJS

  • Angular

  • TypeScript

  • Webpack

  • 浏览器

  • 移动端

  • 前端工程化

  • Electron

  • HTTP

  • Nginx

  • Linux

  • 数据结构与算法

  • LeetCode算法题

  • 综合