记录每天自我学习转前端的碎碎念,仅作加强记忆的笔记和自我监督打卡使用。
关于npx和webpack
npx是nodejs自带的一个命令行工具(terminal tooL),全称为 node package executor 包执行器,什么文件可以被执行 可执行文件(.sh,.exe ...)
-
npm:Node 官方标配,负责“安装、卸载、发布”包。
-
pnpm:社区实现的“高性能 npm”,磁盘省 70 %+、安装最快、Monorepo 体验最好。
-
npx:npm 5.2+ 自带的“临时命令执行器”,不想全局装包时就靠它。
iife 立即执行函数 immediately invoked function expression
node环境获取命令行参数: process.env
npx webpack 用来执行webpack打包,那么我们要执行webpack让webpack帮我们打包,那么必须要有webpack的这个可执行文件,webpack的可执行文件在/node_modules/.bin/webpack这个位置,没有npx的话,你直接敲webpack的话 系统不知道你在干嘛
对于ES6的模块化语法import和export,虽然大部分浏览器已经支持,但是还是有一些钉子户浏览器不支持,但是使用webpack打包依然可以运行,这是为什么?因为webback内部实现了一套自己的模块化require,会将ES6的import和export替换成自己的那套,这套模块化可以兼容低版本浏览器,但是对于其他的ES6的语法,比如箭头函数、对象解构等,webpack没有做转换,需要安装babel等语法降级库来处理 webpack是如何将import和export替换成对应自己的模块化函数require的呢? 先通过node的fs读取文件内容,读取的内容是一个buffer,然后通过buffer.toString()转换成字符串,但是这里不是通过replace方式将import xxx from "" 替换成require的,这样做效率低且不准确,webakck是通过AST(抽象语法树(Abstract Syntax Tree,AST),将代码转成语法树,拿到对应的起始位置和结束位置,然后通过相关方法完成替换
module.export=exports={
default:()=>XX // 代码中写的export default XX
sayHellow:()=>{} // sayHellow是代码中通过exports sayHellow
}
// 在配置webpack.config.js文件时如果没有提示,可以增加下面一行
/**@type {import("webpack").Configuration }*/
module.exports = {}
/**
* ...argsFromUser 使用 rest 运算符,将数组中剩余的所有元素(从第三个元素开始)
收集到一个新数组 argsFromUser 中。本例中,
数组 ['a','b','c'] 只有三个元素,因此 argsFromUser = ['c']。
*/
const [fst, sec, ...argsFromUser] = ['a','b','c']
// 这里argsFromUser是第三个元素,argsFromUser = 'c'
const [fst, sec, argsFromUser] = ['a','b','c']
关于script标签
1.通过js代码创建的“script”标签
let script = document.creatElement('script');
script.src = 'giberish.js'
document.head.appendChild(script)
默认async(异步加载)和defer(延迟加载)都是true,注意,async和defer都只对外部脚本有效 使用script引用的js文件,这种动态创建的脚本获取的资源对浏览器预加载器是不可见的,可能会严重影响性能,可以通过link标签显示声明它们让预加载器知道这些动态请求文件的存在
<link rel="preload" href="giberish.js">
2.如果文件内使用了import或者export,则script标签的type必须设置成module,表示这是一个ES6的模块化
变量
var与let
var声明的变量会自动提升到函数作用域顶部,声明的范围是函数作用域 let声明的变量不会在作用域中被提升,范围是块作用域
if (true) {
var name = 'hello'
console.log(name) // hello
}
console.log(name) // hello
if (true) {
let age = 18
console.log(age) // 18
}
console.log(age) // ReferenceError: age没有定义
与var关键字不同,使用let在全局作用域中声明的变量不会成为window对象的属性,var声明的变量则会 !!!
for (var i = 0; i < 5; ++i){
setTimeout(() => console.log(i), 0)
}
// 结果会是什么? 真实结果:5、5、5、5、5
// 为什么?
// 因为在退出循环时,迭代变量保存的都是导致循环退出的值:5,在之后执行超时逻辑时,所有的i都是同一个变量,所以输出的都是5
for (let i = 0; i < 5; ++i){
setTimeout(() => console.log(i), 0)
}
// 结果会是什么? 真实结果:0、1、2、3、4
// 为什么?
// 因为使用let声明的迭代变量,js引擎会在后台为每个迭代循环声明一个新的迭代变量,每个setTimeout引用的都是不同的变量,所以输出结果是0、1、2、3、4
最佳实践:
1.不使用var
2.const优先,let次之
数据类型
js默认有7种简单数据类型,也就是原始数据类型:Undifined Null Number String Symbol Boolean, BigInt(BigInt数据类型的目的是比Number数据类型支持的范围更大的整数值)和一种复杂数据类型Object
typeof是操作符,不是函数,得到的结果都是字符串
要确定一个值是不是有限大(即介于js能表示的最大值(Number.MAX_VALUE)和最小值(:Number.MIN_VALUE)之间),可以使用isFinite()函数
let result = Number.MAX_VALUE + Number.MAX_VALUE
console.log(isFinite(result)) // 输出结果:false
NaN (Not a Number)
NaN不等于包括NaN在内的任何值,要判断一个值是否是NaN,可以通过isNaN()函数判断