Map和Object的区别
Objects和Maps类似的是,它们都允许你按键存取一个值、删除键、检测一个键是否绑定了值。因此(并且也没有其他内建的替代方式了)过去我们一直都把对象当成Maps使用。不过Maps和Objects有一些重要的区别,在下列情况里使用Map会是更好的选择:
Map | Object | |
---|---|---|
意外的键 | Map默认情况不包含任何键。只包含显式插入的键。 | 一个Object有一个原型, 原型链上的键名有可能和你自己在对象上的设置的键名产生冲突。注意: 虽然 ES5 开始可以用Object.create(null)来创建一个没有原型的对象,但是这种用法不太常见。 |
键的类型 | 一个Map的键可以是任意值,包括函数、对象或任意基本类型。 | 一个Object的键必须是一个 String 或是Symbol。 |
键的顺序 | Map中的 key 是有序的。因此,当迭代的时候,一个Map对象以插入的顺序返回键值。 | 一个Object的键是无序的注意:自ECMAScript 2015规范以来,对象确实保留了字符串和Symbol键的创建顺序; 因此,在只有字符串键的对象上进行迭代将按插入顺序产生键。 |
Size | Map的键值对个数可以轻易地通过.size 属性获取 | Object的键值对个数只能手动计算:Object.keys(obj).length |
迭代 | Map是 iterable 的,所以可以直接被迭代,比如for of或者.for each()迭代 | 只能使用for in 循环进行访问,或者使用 Object.keys(o)、Object.values(o)、Object.entries(o) 来取得表示键或值的数字)迭代时的顺序就是上面提到的顺序。 |
性能 | 在频繁增删键值对的场景下表现更好。 | 在频繁添加和删除键值对的场景下未作出优化。 |
语法区别,创建时:
//Object创建
const o={};//对象字面量
const o=new Object()//调用构造函数创建
const o = Object.create(null); // 调用静态方法 Object.create
//Map创建
const m=new Map();//调用构造函数创建
对于 Object
来说,我们在 95%的情况下都会选择对象字面量,它不仅写起来最简单,而且相较于下面的函数调用,在性能方面会更为高效。对于构建函数,可能唯一使用到的情况就是显式的封装一个基本类型;而 Object.create
可以为对象设定原型。
和 Object
不同,Map
没有那么多花里胡哨的创建方法,通常只会使用其构造函数来创建。
使用 Map
:
- 储存的键不是字符串/数字/或者
Symbol
时,选择Map
,因为Object
并不支持 - 储存大量的数据时,选择
Map
,因为它占用的内存更小 - 需要进行许多新增/删除元素的操作时,选择
Map
,因为速度更快 - 需要保持插入时的顺序的话,选择
Map
,因为Object
会改变排序 - 需要迭代/遍历的话,选择
Map
,因为它默认是可迭代对象,迭代更为便捷
使用 Object
:
- 只是简单的数据结构时,选择
Object
,因为它在数据少的时候占用内存更少,且新建时更为高效 - 需要用到
JSON
进行文件传输时,选择Object
,因为JSON
不默认支持Map
- 需要对多个键值进行运算时,选择
Object
,因为句法更为简洁 - 需要覆盖原型上的键时,选择
Object
虽然 Map
在很多情况下会比 Object
更为高效,不过 Object
永远是 JS
中最基本的引用类型,它的作用也不仅仅是为了储存键值对。
Token放在 cookie, sessionStorage 和 localStorage 中的区别?
Token 其实就是访问资源的凭证
一般是用户通过用户名密码登录成功之后,服务器将登录凭证作为数字签名,加密之后得到的字符串就是 Token。
Token 在用户登录成功之后返回给客户端,客户端组要有三种存储方式:
- 储存在 localStorage 中,每次调用接口时放在http请求头里面,长期有效;
- 储存在 sessionStorage 中,每次调用接口时,把它当为一个字段传给后台,浏览器关闭自动清除;
- 储存在 cookie 中,每次调用接口会自动发送,不过缺点是不能跨域;
深入了解Token存储
- 将 Token 存储在 webStorage(localStorage,sessionStorage) 中可以通过同域的js访问,这样导致很容易受到 xss 攻击,特别是项目中引入很多第三方js库的情况下,如果js脚本被盗用,攻击者就可以轻易访问你的网站。
xss攻击:是一种注入代码攻击,通过在网站里注入script代码,当访问者浏览网站的时候通过注入的script代码窃取用户信息,盗用用户身份等
- 将 Token 存储在 cookie 中,可以指定 httponly 来防止 js 被读取,也可以指定 secure 来保证 Token 只在 HTTPS 下传输,缺点是不符合 RestFul 最佳实践,容易受到 CSRF 攻击。
CSRF: 跨站点请求伪造,攻击者盗用已经认证过的用户信息,以用户信息的名义进行操作(转账,购买商品等),由于身份已经认证过了,所以网站会认为此操作是用户本人操作。 CSRF 并不能拿到用户信息,但它可以盗用用户的凭证进行操作。
webpack的loader和plugin的区别?
loader
loader
是文件加载器,能够加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一起打包到指定的文件中,处理一个文件可以使用多个loader
,loader
的执行顺序和配置中的顺序是相反的,即最后一个loader
最先执行,第一个loader
最后执行,第一个执行的loader
接收源文件内容作为参数,其它loader
接收前一个执行的loader
的返回值作为参数,最后执行的loader
会返回此模块的JavaScript
源码。
编写自己的loader
时需要引用官方提供的loader-utils
,调用loaderUtils.getOptions(this)
拿到webpack
的配置参数,然后进行自己的处理。
Loader
本身仅仅只是一个函数,接收模块代码的内容,然后返回代码内容转化后的结果,并且一个文件还可以链式的经过多个loader
转化(如 scss-loader => css-loader => style-loader
)。
一个Loader
的职责是单一的,只需要完成一种转化。如果一个源文件需要经历多步转化才能正常使用,就通过多个Loader
去转化。在调用多个Loader
去转化一个文件时,每个Loader
会链式的顺序执行,第一个Loader
将会拿到需要处理的原内容,上一个Loader
处理后的结果会传给下一个接着处理,最后的Loader
将处理后的最终结果返回给Webpack
。
plugin
plugin
功能更强大,loader
不能做的都是它做。它的功能要更加丰富。从打包优化和压缩,到重新定义环境变量,功能强大到可以用来处理各种各样的任务。
plugin
让webpack
的机制更加灵活,它在编译过程中留下的一系列生命周期的钩子
,通过调用这些钩子来实现在不同编译结果时对源模块进行处理。它的编译是基于事件流来编译的,主要通过tapable
来实现插件的绑定和执行的,tapable
主要是基于发布订阅的插件架构,是用来创建生命周期钩子的库。调用compiler.hooks.run.tap
开始注册,创建compilation
,基于配置创建chunks
,在通过parser
解析chunks
,使用模块和依赖管理模块之间的依赖关系,最后使用template
基于compilation
数据生成结果代码。
plugin
的实现可以是一个类,使用时传入相关配置来创建一个实例,然后放到配置的plugins
字段中,而plugin
实例中最重要的方法是apply
,该方法在webpack compiler
安装插件时会被调用一次,apply
接收webpack compiler
对象实例的引用,你可以在compiler
对象实例上注册各种事件钩子函数,来影响webpack
的所有构件流程,以便完成更多其他的构建任务。
常见的loader
和plugin
1. 常见loader
loader | 作用 |
---|---|
url-loader | 文件加载,可以设置阈值,小于时把文件base64 编码 |
file-loader | 文件加载 |
image-loader | 加载并压缩图片 |
json-loader | webpack`默认已经包含了 |
babel-loader | ES6+转成 ES5 |
ts-loader | 将ts 转成 js |
awesome-typescript-loader | 比ts-loader 性能好一些 8. css-loader :处理@import 和url 这样的外部资源 |
style-loader | 在head 创建style 标签把样式插入 |
postcss-loader | 扩展css 语法,使用postcss 各种插件autoprefixer,cssnext,cssnano |
eslint-loader, tslint-loader | 通过这两种检查代码,tslint 不再维护 |
vue-loader | 加载vue 单文件组件 |
i18n-loader | 国际化 |
cache-loader | 性能开销大的loader 前添加,将结果缓存到磁盘 |
svg-inline-loader | 压缩后的svg 注入代码 |
source-map-loader | 加载source map 文件,方便调试 |
expose-loader | 暴露对象为全局变量 |
raw-loader | 可以将文件以字符串的形式返回 |
mocha-loader、jshint-loader | 校验测试 |
eslint-loader | 语法校验 |
imports-loader、exports-loader | 等可以想模块注入变量或者提供导出模块功能 |
2. 常见plugin
plugin | 作用 |
---|---|
ignore-plugin | 忽略文件 |
uglifyjs-webpack-plugin | 不支持ES6 压缩(webpack4 以前使用) |
terser-webpack-plugin | 支持压缩ES6(webpack4) |
webpack-arallel-uglify-plugin | 多进程执行代码压缩,提升构建速度 |
mini-css-extract-plugin | 分离样式文件,css 提取为独立文件,支持按需加载 |
serviceworker-webpack-plugin | 为网页应用增加离线缓存功能 |
clean-webpack-plugin | : 目录清理 |
speed-measure-webpack-plugin | 可以看到每个Loader 和Plugin 执行耗时 |
webpack 内置UglifyJsPlugin | 压缩和混淆代码 |
webpack 内置CommonsChunkPlugin | 提高打包效率,将第三方库和业务代码分开打包。 |
ProviderPlugin | 自动加载模块,代替require 和import |
html-webpack-plugin | 可以根据模板自动生成html 代码,并自动引用css 和js 文件 |
extract-text-webpack-plugin | 将js 文件中引用的样式单独抽离成css 文件 |
DefinePlugin | 编译时配置全局变量,这对开发模式和发布模式的构建允许不同的行为非常有用 |
HotModuleReplacementPlugin | 热更新 |
optimize-css-assets-webpack-plugin | 不同组件中重复的css 可以快速去重 |
webpack-bundle-analyzer | 一个webpack 的bundle 文件分析工具,将bundle 文件可以交互缩放的treemap 的形式展示 |
compression-webpack-plugin | 生产环境可以采用gzip 压缩js 和css |
happypack | 通过多进程模式,来加速代码构建 |