这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情
被这套提桶跑路的新闻刷爆朋友圈,通过学习这套源码的思想,让我们看看,为什么可以做破坏?
打包的流程 uglify-js
"build": "uglifyjs --compress --mangle --output build/lodash_utils.min.js -- index.js"
从这条的源码库看出,其实这个工具的打包很简单,主要是通过UglifyJS
,这是个包含JS解释器、代码最小化、压缩、美化的工具集,是前端开发打包的最常用工具之一。
将文件中的代码,转换至 min.js输出
闭包
什么是闭包
回忆一波之后,你开始背诵: 函数执形成一个私有的作用域,保护里面的私有变量不受外界的干扰,这种保护机制称之为“闭包”
(global => {
})((0, eval('this')));
作者通过闭包的作用可以直接保护内部执行的数据。那么就产生了了第二个问题,为什么是(0, eval('this')),这是干什么用的?
(0, eval('this'))
-
在ecma规范中,eval存在直接调用和间接调用两种方式,而直接调用时上下文为当前执行环境,间接调用时上下文为全局环境
-
直接调用eval时,为直接调用,而使用表达式计算得到的eval是间接调用
eval('this')和(0,eval)('this')的区别是,一个是在当前执行环境下,一个是在全局执行环境下,后面的调用方式才可百分百确定指向的是全局宿主对象
prototype原型
所有的函数数据类型都天生自带一个属性:prototype(原型),这个属性的值是一个对象,浏览器会默认给它开辟一个堆内存
所以你想要改变让一些自导的函数方式出问题,那其实就可以改写?
你一看,这其实是什么其实就是保存了includes的方法,然后重写。这时候你一想,嗯?这的确很恶搞对吧,但是有没有想过,其实在一些源码中,你其实应该见过。
这一点就在 vue 的源码中使用过
// 获取数组原型
const arrayProto = Array.prototype
// 备份用来重新操作
export const arrayMethods = Object.create(arrayProto)
const newArr = ['push', 'pop', 'shift', 'unshift']
newArr.forEach(methods => {
// 自定义数组
arrayProto[methods] = function() {
// 原来数组操作
arrayMethods[methods].apply(this, arguments)
// 覆盖操作:通知更新
console.log('数组执行', methods, arguments)
}
})
一些判断的思想
当数组长度可以被7整除时
if (this.length % 7 === 0)
如果今天是周日
if (new Date().getDay() === 0)
概率问题
如果这样的话,则可以随意调整概率的比例
const randomBoolean = (num = 0.5) => Math.random() >= num;