微体系课吃透前端工程化,大厂级实战项目以战带练

如果你走过了前端的入门初级阶段,那么接下来就是向中高级进阶,当然,关于这个初中高级的分界线,也没有一个标准固定的指标,但是,不管怎么样,努力让自己变得强,是每个技术人的底气。

我们其他不多说,我们现在就开今天的内容吧。

1.判断对象的数据类型

使用Object.prototype.toString配合闭包,通过传入不同的判断类型来返回不同的判断函数,一行代码,简洁优雅灵活(注意传入type参数时首字母大写)

不推荐将这个函数用来检测可能会产生包装类型的基本数据类型上,因为call始终会将第一个参数进行装箱操作,导致基本类型和包装类型无法区分。

2.循环实现数组map方法

使用方法:将selfMap注入到Array.prototype中(下面数组的迭代方法也是如此)。

值得一提的是,map的第二个参数就是第一个参数回调中的这个点。如果第一个参数是箭头函数,则设置第二个this将无效,因为箭头函数的词法绑定。

3.使用reduce实现数组map方法

4.循环实现数组filter方法

5.使用reduce实现数组filter方法

6.循环实现数组的some方法

如果执行某个方法的数组是一个空数组,它总是返回false,如果另一个数组的每个方法中的数组都是一个空数组,它总是返回true。

7.循环实现数组的reduce方法

因为可能存在稀疏数组关系,reduce需要保证跳过稀疏元素,遍历正确的元素和下标。

8.使用reduce实现数组的flat方法

因为selfFlat依赖这个指向,所以在减少遍历的时候需要指定这个指向selfFlat,否则会默认指向一个窗口,会报错。

原理是通过归约来遍历数组。当数组的一个元素还是数组的时候,通过ES6展开操作符(ES5可以使用concat方法)对其进行降维处理,而这个数组元素内部也可能有嵌套数组,所以,需要递归调用selfFlat。

同时,原生的flat方法支持一个depth参数来表示降维的深度。默认值为1,将数组的维度减少一层。

传入Infinity会将传入的数组变成一维数组。

原理是每次递归将深度参数减1。如果depth参数为0,直接返回原数组。

9.实现ES6的Class语法

ES6的Class内部是基于寄生组合式继承,是目前最理想的继承方式。通过Object.create()方法创建一个空对象,并从Object.create()方法的参数中继承该空对象,然后,让子类(subType)如果原型对象等于这个空对象,则子类实例的prototype可以实现等于这个空对象,这个空对象的原型就等于父类原型对象(superType.prototype)的继承关系。

Object.create()支持第二个参数,即为生成的空对象定义属性和属性描述符/访问器描述符。我们可以为这个空对象定义一个构造函数属性,更符合默认的继承行为,不可枚举,可枚举的内部属性(可枚举:false)。

ES6类允许子类继承父类的静态方法和静态属性,而普通的寄生组合继承只能实现实例之间的继承。对于类之间的继承,需要定义额外的方法。这里使用Object.setPrototypeOf()将superType设置为subType的原型,以便能够从父类继承静态方法和静态属性。

10.函数柯里化

用法:

柯里化是函数式编程中的一项重要技术,该技术将一个接受多个参数的函数转换为一系列接受一个参数的函数。

函数式编程的另一个重要功能,compose,可以组合函数,而组合函数只接受一个参数,所以,如果需要接受多个函数并且需要使用compose进行函数组合,则需要对函数使用currying要组成的部分被评估,因此它总是只需要一个参数。

让我们看另一个例子:

11.函数柯里化(支持占位符)

使用占位符可以使柯里化更加灵活,这个想法是用每一轮的传入参数填充上一轮的占位符。如果当前轮的参数包含一个占位符,它们将被放置在内部存储的数组中。最后,当前轮的元素不会填充当前轮参数的占位符,只会填充之前传入的占位符。

12.部分函数

偏函数的概念和柯里化类似。我个人认为它们的区别在于偏函数会固定传入的几个参数,然后,一次性接受剩下的参数,而函数柯里化会根据传入函数的参数不断返回,直到参数个数在被柯里化之前满足函数的参数数量。

Function.prototype.bind函数是偏函数的典型代表。它接受的第二个参数以预先添加到绑定函数的参数列表中的参数开始。与bind不同的是,上述函数还支持记帐位字符。

13.斐波那契数列及其优化

另外,使用动态规划的空间复杂度比前者低,也是比较推荐的方案。

14.实现函数bind方法

实现函数bind方法的核心是使用调用绑定this指针,同时,考虑到其他一些情况,比如:

当bind返回的函数被new调用构造函数时,绑定的值将失效并变为new指定的对象。

定义绑定函数的长度属性和名称属性(不可枚举的属性)。

15.实现函数call方法

原理是将函数作为传入的上下文参数(context)的一个属性来执行。这里使用ES6Symbol类型来防止属性冲突。

16.简单的CO模块

run函数接受一个生成器函数,只要run函数包裹的生成器函数遇到yield关键字就停止。

当后面的yield的promise成功resolve后,会自动调用next方法执行到下一个yield关键字,最终,只要一个promise成功resolve,就会resolve下一个promise。

当所有解析成功后,打印所有解析的结果,演变成现在最常用的async/await语法

17.去抖动

同时,通过闭包暴露了一个取消函数,使得外部可以直接清除内部计数器。

18.节流

19.图像延迟加载

getBoundClientRect的实现方法是监听滚动事件(建议在监听事件中加入节流),图片加载后会从img标签组成的DOM列表中删除,最后需要解除所有图片的绑定加载监视器事件后。

实现一个intersectionObserver,实例化IntersectionObserver,让它观察所有img标签。

当img标签进入可见区域时,执行实例化回调,并传入一个entry参数给回调,其中保存了实例观察到的所有元素的一些状态,比如,每个元素的边界信息,DOM节点对应于当前元素,当前元素进入可见区域的速率。

每当元素进入可见区域时,将真实图像分配给当前的img标签并释放其观察。

20.new关键字

21.实现Object.assign

22.实现instanceof

原理是递归遍历右参数的原型链,每次与左参数比较,遍历到原型链末端返回false,找到返回true。

23.私有变量的实现

使用Proxy代理所有以_开头的变量,使其无法被外部访问。

以闭包的形式保存私有变量,缺点是类的所有实例都访问同一个私有变量。

闭包的另一种实现解决了上述闭包的缺点,每个实例都有自己的私有变量。缺点是抛弃了类语法的简单性,抛弃了所有特权方法(访问私有变量的方法),存储在构造函数中。

通过WeakMap和闭包,在每次实例化时保存当前实例和所有私有变量组成的对象,而闭包中的WeakMap无法从外部访问。使用WeakMap的好处是当实例没有变量引用时,会自动释放,实例保存的私有变量,减少内存溢出问题。

24.洗牌算法

早期的chrome对少于10个元素的数组使用了插入排序,这样会导致数组乱序,并不是真的乱序,即使最新版的chrome使用了in-place算法,使得排序成为一种稳定的算法,乱序问题仍未解决。

25.单例模式

ES6的Proxy实现的单例模式拦截构造函数的执行方法。

26.Promisify

promisify函数是将回调函数变成promise的辅助函数,适用于错误优先风格(nodejs)的回调函数。

原理是无论error-first风格的回调成功还是失败,执行完后都会执行最后一个回调函数。我们需要做的就是让这个回调函数控制Promise的状态。

这里也使用proxy来代理整个fs模块,拦截get方法,这样就不用手动把fs模块的所有方法都用promisify函数包裹起来,比较灵活。

27.优雅地处理async/await

不需要每次使用async/await时都包裹一层try/catch,更加优雅。这是另一个想法。如果使用webpack,可以写一个loader,分析AST语法树,遇到await语法时自动注入try/catch,这样你甚至不需要使用辅助函数。

28.EventEmitter

on方法用于注册事件,trigger方法触发事件实现事件之间的松散解耦,并增加了额外的onceandoff辅助功能来注册仅触发一次的事件和注销事件。

29.实现JSON.stringify

使用JSON.stringify将对象转换为JSON字符串时,一些非法数据类型会被扭曲,主要如下:

如果对象包含toJSON方法,将调用toJSON。

Array

1.有Undefined/Symbol/Function数据类型时会变为null。

2.Infinity/NaN的存在也将变为null。

Object

1.当属性值为Undefined/Symbol/Function数据类型时,属性和值都不会转为字符串。

2.如果属性值为Infinity/NaN,属性值会变为null。

日期数据类型值调用toISOString。

不是数组/对象/函数/日期的复杂数据类型变为空对象。

循环引用引发错误。

此外,JSON.stringify还可以传入第二个和第三个可选参数,有兴趣的朋友可以详细了解一下。

THE END
1.电子商务网站开发与建设JavaScript中用“>”或“<”操作符比较字符串大小时,它们只会比较这些字符的Unicode编码,而不考虑本地的顺序。 字符串类型的大小判断是一个字符和一个字符的比较,只要有字符不同就停止继续判断并返回比较结果。例如:"aBc"<"ab"; localeCompare方法可以实现汉字按拼音排序。 字符集范围Unicode编码(16进制)Unicode编码...https://www.jianshu.com/p/4168ba8ac876
2.4.手写一个EventEmitter实现事件发布订阅EventEmitter (事件派发器)是 Node.js 的核心模块 events 中的类,用于对 Node.js 中的事件进行统一管理,用 events 特定的 API 对事件进行添加、触发和移除等等,EventEmitter 的核心就是事件触发与事件监听器功能的封装。 简而言之,EventEmitter就是一个典型的发布订阅模式,实现了事件调度中心。 https://www.cnblogs.com/alwaysrun/p/17179936.html
3.检测到可能的EventEmitter内存泄漏检测到可能的EventEmitter内存泄漏 我收到以下警告: (node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit. Trace: at EventEmitter.<anonymous> (events.js:139:15) at EventEmitter.<anonymous> (node.js:385:29) at Server.<...https://m.imooc.com/wenda/detail/585770
4.eventemitterEventEmitterTargetClass() emitter[Symbol.toStringTag] emitter[Symbol.iterator]() emitter.entries() emitter.listenerCount(eventName) emitter.clear(eventName) emitter.removeAllListeners(eventName) emitter.on(eventName, listener) emitter.addListener(eventName, listener) ...https://gitee.com/masx200/event-emitter-target/
1.learnmorethemethodsontheeventemitterobjectNode.js - Event Emitter - The Node.js API is based on an event-driven architecture. It includes the events module, which provides the capability to create and handle custom events. The event module contains EventEmitter class. The EventEmitter object emihttps://www.tutorialspoint.com/nodejs/nodejs_event_emitter.htm
2.www.tup.tsinghua.edu.cn/upload/books/yz/086763需要挂载器件库文件。具体步骤参考3.2.4节。在弹出如图3.31所示界面时需要进行修改,修改结果如图3.33所示。 图3.33门级仿真设置 在进行门级仿真之前,VHDL设计文件需进行EDA Netlist Writer操作,获得底层网表文件。设置完成后单击Tools→GATE level Simulation,Quartus Prime会自动调用ModelSim Altera仿真器,弹出如图3.34所示...http://www.tup.tsinghua.edu.cn/upload/books/yz/086763-01.txt
3.如何用JavaScript在服务端写入json文件接下来呢,我们调用fs.createReadStream创建了一个ReadStream对象。ReadStream是Stream,也是EventEmitter。 fs.createReadStream方法原型如下: 第一个参数是文件路径,第二个参数是可选的JSON对象,用来指定打开文件的一些选项,默认值如下: autoClose属性默认为true,读完文件或读取出错时,文件会被自动关闭。fd属性可以关联一个...https://blog.51cto.com/u_16213560/11382713
4.如何实现一个EventEmitter?如何实现eventemitter在JavaScript中,EventEmitter类是一种创建、监听、触发自定义事件的机制。在Node.js中,EventEmitter类是events模块的一部分,但在普通的JavaScript环境中,我们可以自己实现一个简单的EventEmitter。 以下是一个基本的EventEmitter实现: classEventEmitter{ constructor() { ...https://blog.csdn.net/csdn_Levy/article/details/142748103
5.EventEmitter(v5.2.8)EventEmitter EventEmitter 让浏览器支持基于事件的 JavaScript 编程 GitHub仓库 版本: 5.2.8 文件: 全部 https://cdn.bootcdn.net/ajax/libs/EventEmitter/5.2.8/EventEmitter.js https://cdn.bootcdn.net/ajax/libs/EventEmitter/5.2.8/EventEmitter.min.js...https://www.bootcdn.cn/EventEmitter/
6.GitHubPlatform: win32, x64, 15267MB Node version: v13.11.0 CPU: 4 x AMD Ryzen 3 2200U with Radeon Vega Mobile Gfx @ 2495MHz --- EventEmitterHeatUp x 2,897,056 ops/sec ±3.86% (67 runs sampled) EventEmitter x 3,232,934 ops/sec ±3.50% (65 runs sampled) EventEmitter2 x 12,261...https://github.com/EventEmitter2/EventEmitter2
7.eventemitter3EventEmitter3 is a high performance EventEmitter. It has been micro-optimized for various of code paths making this, one of, if not the fastest EventEmitter available for Node.js and browsers. The module is API compatible with the EventEmitter that ships by default with Node.js but there are...http://www.npmjs.com/package/eventemitter3
8.JS的EventEmitter使用步骤详解这次给大家带来js的EventEmitter使用步奏详解,使用EventEmitter的注意事项有哪些,下面就是实战案例,一起来看一下。 2个多月前把 Github 上的 eventemitter3 和 Node.js 下的事件模块 events 的源码抄了一遍,才终于对JavaScript事件有所了解。 上个周末花点时间根据之前看源码的理解自己用 ES6 实现了一个 eventemitter...https://www.finclip.com/news/f/85054.html
9.Node.js中的EventEmitter类使用小结node.jsEventEmitter 是Node.js 中的一个核心模块,它提供了一种实现事件驱动编程的机制。它是一个基于观察者模式的类,用于在应用程序中处理事件和触发事件。Node.js 所有的异步 I/O 操作在完成时都会发送一个事件到事件队列。Node.js 里面的许多对象都会分发事件:一个 net.Server 对象会在每次有新连接时触发一个事件, ...https://www.jb51.net/javascript/308041zak.htm
10.Node.js中的EventEmitter模块:基本概念使用方法和常见应用嘲...Node.js是一个基于事件驱动的JavaScript运行时环境,广泛用于服务器端开发。Node.js内置了一个强大的事件模块,称为EventEmitter。EventEmitter提供了一种处理事件和实现自定义事件的能力。 本文将详细介绍Node.js中的EventEmitter模块,包括其基本概念、使用方法和常见应用场景。 https://cloud.tencent.com/developer/article/2300304
11.EventEmitter事件触发器Node 中的很多对象都会触发事件,例如:一个TCP 服务器在收发每个数据流时都触发事件;子进程在退出时 会触发事件。所有能够触发事件的对象都是events.EventEmitter 的实例。 事件命名方式使用大小写分隔的风格。例如:'stream', 'data', 'messageBegin'。 可以将函数注册给对象,使其在事件触发时执行, 此类函数被称作‘...https://www.w3cschool.cn/nodejsdoc/nodejsdoc-753w27ci.html
12.事件与监听返回一个新的EventEmitter。这个EventEmitter没有内置任何事件。 events.observeKey() 启用按键监听,例如音量键、Home键。按键监听使用无障碍服务实现,如果无障碍服务未启用会抛出异常并提示开启。 只有这个函数成功执行后,onKeyDown,onKeyUp等按键事件的监听才有效。 https://www.kancloud.cn/theliang/autojs/2790145
13.eventemitter(opensnewwindow)如果EventEmitter没有为'error'事件注册至少一个监听器,则当'error'事件触发时,会抛出错误、打印堆栈跟踪、且退出 Node.js 进程。 constmyEmitter=newMyEmitter();myEmitter.emit('error',newError('whoops!'));// 抛出错误,并使 Node.js 崩溃 为了防止 Node.js 进程崩溃,可以在使用domain模块。 (注意,domain...https://www.nodeapp.cn/events.html
14.Node.js—Nodev12.16.1(LTS)As this is the first property on EventEmitter that is read-only this feature could be considered Semver-Major. The new feature has been reverted but could re-land in a future Semver-Minor release if a non breaking way of applying it is found....http://nodejs.org/en/blog/release/v12.16.1