通过Evil.js的思想-学习前端基础

1,288 阅读2分钟

这是我参与「掘金日新计划 · 8 月更文挑战」的第24天,点击查看活动详情

image.png

被这套提桶跑路的新闻刷爆朋友圈,通过学习这套源码的思想,让我们看看,为什么可以做破坏?

打包的流程 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;