Javascript基础
1. 箭头函数和普通函数的差异
1.1 不能通过 new 关键字调用, 没有原型
- 不能使用 new,箭头函数没有 Construct 方法,不能被用作构造函数
- 不能通过 new 关键字调用函数,没有构建原型的需求,所以箭头函数内部也不会存在 prototype 属性,所以箭头函数没有原型
- ES6 新增的 new.target 也没有,自然而然也不能通过 super 来访问原型属性
// 箭头函数和普通函数的区别示例 var Foo = () => {}; console.log(Foo.prototype); // undefined
1.2 不可以改变 this 绑定,由外层非箭头函数决定,所以使用 call, apply, bind 也不会影响
- function 函数(优先级按序号从高到低)
- 在调用函数时使用 new 关键字,函数内的 this 是一个全新的对象。
- 如果 apply、call 或 bind 方法用于调用、创建一个函数,函数内的 this 就是作为参数传入这些方法的对象。
- 当函数作为对象里的方法被调用时,函数内的 this 是调用该函数的对象。
- 如果调用函数不符合上述规则,那么 this 的值指向全局对象(global object)。
- 浏览器环境下 this 的值指向 window 对象,但是在严格模式下’use strict’,this 的值为 undefined。
- 箭头函数
- 无论如何执行或在何处执行,箭头函数内部的 this 值始终等于离它最近的外部函数的 this 值。换句话说,箭头函数可按词法解析 this,箭头函数没有定义自己的执行上下文。
- 熟悉 React 的同学都知道,之前如果在类里面使用方法我们需要先 bind 一下 this, 但箭头函数都给我们解决了
-
const obj = { value: 2, callback: function(arr) { var self = this // 在嵌套函数里面使用外面的 this 需要先定义变量的情况 function showThis() { console.log(self.value) } showThis() } } const obj2 = { value: 2, callback: function(arr) { showThis = () => { console.log(this.value) } showThis() } } obj.callback() // 2 obj2.callback() // 2
1.3 不支持 arguments,所以根据作用域链,会拿到外层函数的 arguments
- 常规函数
- 有一个arguments 的类数组对象,包含了函数的所有参数
- 经常使用在我们没有具体定义参数的情况下
- 箭头函数
- 箭头函数是不支持arguments 的类数组对象
- 如果你在箭头函数里面使用,按照作用域链的查找规则,会一直查询到最近的非箭头函数,然后实际使用的是非箭头函数里面的 arguments
- 为此,ES6 也提供了这种不定参数情况下的参数的操作,看下面的例子
// ...args 会把不定参数转换成一个数组, // 但使用这个也要注意,只能使用一次且放在所有参数末尾 const add = (...args) => { return args.reduce((cur, i) => cur + i, 0) } add(5, 10, 15) // 30
1.4 不支持重复命名参数
- 无论在严格还是非严格模式下,箭头函数都不支持重复的命名参数,而传统函数只有在严格模式下才不支持重复的命名参数。
var a = (b, b)=>{
b = 100
console.log(this)
console.log(b)
} // Uncaught SyntaxError: Duplicate parameter name not allowed in this context
1.5 隐式返回
- 函数内部一直都有一个隐藏的返回值,使用
function
如果什么都不定义,其实默认就会返回undefined
,我理解这是终止函数的执行,用代码来表示
function noReturn() {
console.log('aaa')
return // 这个不需要手动写,不写默认就是
// 如果你在函数中没有需要 return 的,就会自动给你加上一个
}
- 箭头函数省了一个 return,适合这种函数体内只有一行代码的情况,多行还是需要写的
- 如果 return 的是一个值,不需要 {}
- 如果返回的是一个字面量, 需要加 ()
const add = (a, b) => a + b const obj = () => ({ a: 1 })
2. 数组方法整理
方法名 | 对应版本 | 功能 | 原数组是否改变 |
---|---|---|---|
concat() | ES5- | 合并数组,并返回合并之后的数据 | n |
join() | ES5- | 使用分隔符,将数组转为字符串并返回 | n |
pop() | ES5- | 删除最后一位,并返回删除的数据 | y |
shift() | ES5- | 删除第一位,并返回删除的数据 | y |
unshift() | ES5- | 在第一位新增一或多个数据,返回长度 | y |
push() | ES5- | 在最后一位新增一或多个数据,返回长度 | y |
reverse() | ES5- | 反转数组,返回结果 | y |
slice() | ES5- | 截取指定位置的数组,并返回 | n |
sort() | ES5- | 排序(字符规则),返回结果 | y |
splice() | ES5- | 删除指定位置,并替换,返回删除的数据 | y |
toString() | ES5- | 直接转为字符串,并返回 | n |
valueOf() | ES5- | 返回数组对象的原始值 | n |
indexOf() | ES5 | 查询并返回数据的索引 | n |
lastIndexOf() | ES5 | 反向查询并返回数据的索引 | n |
forEach() | ES5 | 参数为回调函数,会遍历数组所有的项,回调函数接受三个参数,分别为value,index,self;forEach没有返回值 | n |
map() | ES5 | 同forEach,同时回调函数返回数据,组成新数组由map返回 | n |
filter() | ES5 | 同forEach,同时回调函数返回布尔值,为true的数据组成新数组由filter返回 | n |
every() | ES5 | 同forEach,同时回调函数返回布尔值,全部为true,由every返回true | n |
some() | ES5 | 同forEach,同时回调函数返回布尔值,只要由一个为true,由some返回true | n |
reduce() | ES5 | 归并,同forEach,迭代数组的所有项,并构建一个最终值,由reduce返回 | n |
reduceRight() | ES5 | 反向归并,同forEach,迭代数组的所有项,并构建一个最终值,由reduceRight返回 | n |
## 3. 数组浅拷贝方法 | |||
序号 | 方式 | 例子 | 说明 |
—— | ———— | ———— | — |
1 | concat | let res = arr.concat(); | 连接数组返回一个新数组 |
2 | slice | let res = arr.slice(); | 返回选定的元素默认从0开始到结尾 |
3 | 解构 | let res = […arr]; | 创建了一个新的数组赋值为当前数组的值 |
4 | 解构2 | let […res] = arr; | 同上 |
5 | map | let res = arr.map(i=>i); | 遍历数组逐个返回元素给res |
6 | Array.of | let res = Array.of(…arr); | 该方式将一堆数字转化成数组返回 |
2.Webpack
2.1 webpack 性能优化-构建速度
1. 优化babel-loader
module: {
rules: [
{
test: /\.js$/,
use: ['babel-loader?cacheDirectory'], // 开启缓存
include: path.resolve(__dirname, 'src') // 明确范围
// // 排除范围,include 和 exclude 两者选一个即可
// exclude: path.resolve(__direname, 'node_modeles')
}
]
}
2. IgnorePlugin 忽略无用文件
- 用IngorePlugin忽略无用文件 例如:moment会支持多语言,如何只引入中文模块?
// 忽略 moment 下的 /locale目录
new webpack.IgnorePlugin(/\.\/locale/, /moment/)
// 业务代码中动态引入语言包
import 'moment/locale/zh-cn'
3. noParse 避免重复打包
- noParse避免重复打包
module: {
noParse: [/react\.min\.js$/]
}
- IgnorePlugin、noParse区别:
- IgnorePlugin直接不引入,代码中没有
- noParse(类似vue.min.js已经模块化处理过)引入,但不打包
4. happypack 多进程打包工具
- JS 单线程,开启多进程打包
- 提高构建速度(特别是多核CPU)
const HappyPack = require('happypack')
// 步骤1 module.rules下-将对.js的文件交给id为label的HappyPack实例
{
test: /\.js$/,
use: ['happypack/loader?id=babel']
}
// 步骤2 happyPack开启多进程打包
new HappyPack({
// 用唯一的标识符 id 来代表当前的HappyPack 是用来处理一类特定的文件
id: 'babel',
// 如何处理.js 文件,用法和Loader 配置一样
loaders: ['babel-loader?cacheDirectory']
})
5. ParalleUglifyPlugin 多进程代码压缩
- webpack 内置 Uglify 工具压缩JS
- JS单线程,开启多进程压缩更快
- 和happyPack 同理,多进程
// 使用 ParallelUglifyPlugin 并行压缩输出的 JS 代码
const ParallelUglifyPlugin = require('ParallelUglifyPlugin')
new ParallelUglifyPlugin({
// 传递给 UglifyJS 的参数
// (还是使用 UglifyJS 压缩,只不过帮助开启了多进程)
uglifyJS: {
output: {
beautify: false, // 最紧凑的输出
comments: false // 删除所有的注释
},
compress: {
// 删除所有的 `console` 语句,可以兼容ie浏览器
drop_console: true,
// 内嵌定义了但是只用到一次的变量
collapse_vars: true,
// 提取出出现多次但是没有定义成变量去引用的静态值
reduce_vars: true
}
}
})
6.自动刷新
- 自动刷新:整个网页都刷新,速度较慢
- 自动刷新:状态会丢失(表单内数据会丢失)
7. 热更新
- 热更新:新代码生效,网页不刷新,状态不丢失
- HotModuleReplacementPlugin插件在webpack/lib下
// 配置 在entry中的index中
index: [
'webpack-dev-server/client?http://localhost:8080/',
'webpack/hot/dev-server',
path.join(srcPath, 'index.js')
]
// 配置2
在plugins中new HotModuleReplacementPlugin()
// 配置3
在devServer加hot: true
// 配置4
业务中加module.hot来确定哪些范围需要触发热更新
8. DllPlugin 动态链接库插件
- 使用原因
- 前端框架Vue、React 体积大 构建慢
- 较稳定,不常升级版本
- 同一个版本只构建一次即可,不用每次都重新构建
- webpack已经内置DllPlugin支持
- DllPlugin – 打包出dll文件
- DllReferencePlugin – 使用dll文件
- 使用方式
// 新建webpack.dll.js 文件
const path = require('path')
const DllPlugin = require('webpack/lib/DllPlugin')
const { srcPath, distPath } = require('./paths')
module.exports = {
mode: 'development',
// JS 执行入口文件
entry: {
// 把 React 相关模块的放到一个单独的动态链接库
react: ['react', 'react-dom']
},
output: {
// 输出的动态链接库的文件名称,[name] 代表当前动态链接库的名称,
// 也就是 entry 中配置的 react 和 polyfill
filename: '[name].dll.js',
// 输出的文件都放到 dist 目录下
path: distPath,
// 存放动态链接库的全局变量名称,例如对应 react 来说就是 _dll_react
// 之所以在前面加上 _dll_ 是为了防止全局变量冲突
library: '_dll_[name]',
},
plugins: [
// 接入 DllPlugin
new DllPlugin({
// 动态链接库的全局变量名称,需要和 output.library 中保持一致
// 该字段的值也就是输出的 manifest.json 文件 中 name 字段的值
// 例如 react.manifest.json 中就有 "name": "_dll_react"
name: '_dll_[name]',
// 描述动态链接库的 manifest.json(索引文件) 文件输出时的文件名称
path: path.join(distPath, '[name].manifest.json'),
}),
],
}
- DllReferencePlugin(记得 rules 中忽略打包的node_modules这个dll 代码)
plugins: [
new webpack.DefinePlugin({
// window.ENV = 'production'
ENV: JSON.stringify('development')
}),
// 第三,告诉 Webpack 使用了哪些动态链接库
new DllReferencePlugin({
// 描述 react 动态链接库的文件内容
manifest: require(path.join(distPath, 'react.manifest.json')),
}),
],
2.2 webpack性能优化-产出代码
作用
- 打包出的体积更小
- 合理分包,不重复加载
- 速度更快,内存使用更少
优化方式
- 小图片base64编码(对图片使url-loader配置options.limit)
- bundle加hash值([name].[contentHash:8].js)
- contentHash:8 是根据内容算出的 8位hash值
- 懒加载()=>import(”)
- 提取公共代码splitChunks:公共代码和三方代码
- IgnorePlugin: 忽略文件不引入打包
- 用cdn加速:
- 在output中加publicPath
- 在url-loader中的options中也加入publicPath , 设置图片
- 使用production
- Scope Hosting
- 改变打包作用域,使占用更新写,打包更快些
- 开启 gzip
今天的文章这些前端问题你都会吗?分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/14705.html