JS基础知识杂记
8种: null,undefined,boolean,number,string,object,symbol,bigint
null 表示值就是空,如原型链的终点
undefined 表示尚未被赋值,却尝试读取,如变量声明,函数无返回值
Symbol 接收一个参数表示对Symbol值的一种描述,const s1 = Symbol('foo'),
传入相同的参数,生成的Symbol也不同
const s2 = Symbol.for('foo')方法会检测上文中是否已存在相同参数创建的Symbol,存在则返回该Symbol,不存在则新建
最常见是在开源库内作为常量,比如用来自定义一个类型 比如 react源码内的 const REACT_ELEMENT = Symbol.for('react.element')
或者是作为开源库内的 对象属性,Object.keys 和Object.getOwnPropertyNames 均不会返回Symbol,
Object.getOwnPropertySymbols可以返回对象所有Symbol属性
BigInt 真没怎么用过,只知道是用来表示 大于 2^53-1 的数的,末尾加n就行
JS没有整数类型,所有数字均以 双精度64位浮点格式 表示. 由 8Byte,64bit 组成。
bit63 符号位, bits62-52 指数位(移码), bits51-0 尾数位.
53位精度: 52位尾数位,并且隐含一个最高有效位 1,可表示 53位1 即 2^53-1
大于53位精度的数, 超出的尾部位会被忽略,因而存在数不同但截去部分尾部位后相同的情况。
安全,代表精度没有损失,需要双精度展示 和 十进制数是一对一对应的。
Number.MAX_SAFE_INTEGER Number.POSITIVE_INFINITY Number.MAX_VALUE Infinity
9007199254740991 = 90亿亿
计算机采用科学计数法储存数,科学计数法 与 原码 反码 补码 移码 计算机原理,大学学过。
二进制1 = 2^1-1,二进制 11 = 2^2-1,二进制 111 = 2^3-1, 二进制 53位1 = 2^53-1
2^53 - 1 双精度64位浮点格式 默认整数位1, 加上52位尾数位全为 1,共 53位1, 为最大安全整数
2^53 指数位储存53, 尾数位需要储存53个0, 但最后1位0被忽略, 能被JS正常储存
2^53 + 1 指数位储存53,尾数位需要储存52个0, 和最后1位1被忽略, 因此与 2^53 相等。
0.1 和 0.2 数学上二进制表示时 是无限循环的,有限储存位的情况下,出现了精度丢失
0.1 ≈ 0.0001100110011001100110011001100110011...(无限)
0.2 ≈ 0.0011001100110011001100110011001100110...(无限)
至于,为什么相加后是 0.30000000000000004 ?
因为相加后储存 再次出现了精度丢失 ,或者说
在 0.3 这个量级下,相邻可表示浮点数之间的间距,大于 0.0000000000000001
1B = 8b, Byte(字节) 是硬件能访问的最小单位, bit(位) 是 储存数据的最小单位
一是因为ASCII规范,二是因为物理上 内存的最小管理单位就是8bit, 1元素 管理8个小电容。
计算机只认识01, 人类认识数字字母, 建立规范将数字字母与01对应, 将字母编码为01给计算机执行。
为什么最初设计硬件的时候,不是4bit,6bit?
ASCII编码(American Standard Code for information Interchange 美国信息交换标准码)
包含数字 字母 标点符号, 共计 128个, 2^7, 并扩容为 2^8, 8 bit, 1 Byte。
typeof instanceof toString
typeof 能判断8种基本类型,及function类型,Object的衍生类型都只能返回object(全部小写字符串)
typeof null === 'object' 历史遗留 bug
instanceof 能判断实例的对象类型,不能判断8种基本数据类型,原理是顺着原型链找,也就是prototype
console.log(people1 instanceof People); // true
仅for/in返回 原型链属性,仅 Reflect.ownKeys()返回 Symbol
for ... in ... 继承,可枚举
Object.keys() 非继承,可枚举
Object.entries() 非继承,可枚举
Object.getOwnPropertyNames() 非继承,可枚举,不可枚举
Reflect.ownKeys() 非继承,可枚举,不可枚举,Symbol
可枚举属性 指 enumerable 标志设置为 true 的属性
Object.defineProperty定义的属性,enumerable 标志默认为 false
js的内置方法和属性几乎都不可枚举
=== 与 == 的区别 : == 类型不同时会发生类型的自动转换,转换为相同的类型后再做比较
Object.assign() 将所有可枚举属性的值从一个或多个源对象复制到目标对象,并返回目标对象
Object.create() 创建一个新对象,将第一个参数作为其原型链的原型,第二个参数为其属性配置。
JS垃圾回收机制就是 定期找出 不再用到的变量 释放其内存。
不再用到的变量,即 对没有被其他对象引用到 的对象
被引用, 即内被另一个对象访问到, 或称处于另一个对象的闭包内, 包括 原型链 this链 作用域。
缺点: 内存碎片化 分配速度慢,需要标记整理法
内存泄漏: 系统执行没用到的内存,却一直没释放。
全局变量、定时器、回调函数、事件监听器、递归、console
减少全局变量,使用完数据及时解除引用,理清代码逻辑减少逻辑嵌套
利用事件冒泡机制,将DOM事件在其父节点处注册的机制。
多个事件只绑定一次,减少事件绑定,减少DOM交互次数
抹平平台差异,浏览器兼容,ReactNative也可使用
切片编程,统一进行事件处理,
批量更新,交互触发多个事件状态变化,可进行一次更新。
CommonJS(NodeJS): exports/require 模块作用域,同步加载,值的拷贝
AMD(RequireJS): define/require 异步加载,加载完立即执行解析依
CMD(SeaJS): define/use 异步加载,需要的时候才执行依赖
UMD: 判断用的是哪种规范,再执行返回输出
ES6Module: export/import 异步加载,值的引用
异步的一些 API,比如 setTimeout,setInterval,requestIdleCallback 和 requestAnimationFrame 还有 Promise,这几个有什么区别?
浏览器和node的
理解闭包的产生比理解闭包的概念更重要,
闭包的产生
根据词法作用域规则,函数的作用域链由函数声明位置决定,声明位置在内部的函数总是可以访问外部函数的变量,
即使内部函数的调用位置,不在其声明的外层函数内,甚至外部函数已经执行结束,
但内部函数 引用的外部函数变量依旧保存在内存中,这些变量的集合称为闭包.
闭包
函数与其引用的外部函数词法环境的集合.(函数,自己内部的变量,外部词法环境,可访问的外部变量)
闭包存在两种情况,一种是 内部函数正常在内部执行时,外部词法环境变量均存在,只要函数执行就存在闭包
一种是 内部函数执行时外部函数执行上下文已被销毁,
当外部函数已被销毁,内部函数 引用了的外部变量依旧会被保存,
而 未被引用的外部变量 会通过 tree-shaking的方式 被销毁。
重绘:某些元素的外观被改变
重排:局部或者整体布局发生改变,需要重新生成布局,重新排列元素。
导致重排的场景:
添加或删除可见的DOM元素
元素的位置发生变化
元素的尺寸发生变化(包括外边距、内边框、边框大小、高度和宽度等)
内容发生变化,比如文本变化或图片被另一个不同尺寸的图片所替代
页面一开始渲染的时候(这避免不了)
浏览器的窗口尺寸变化(因为回流是根据视口的大小来计算元素的位置和大小的)
如何减少重排:
避免频繁操作样式
减少重排范围,尽可能将样式加在具体元素上,而不是它的父级
对于那些复杂的动画,对其设置 position: fixed/absolute,尽可能地使元素脱离文档流,从而减少对其他元素的影响
动画样式启用GPU加速,transform、opacity、filters这些动画不会引起回流重绘
history模式下,url发生改变并刷新页面,浏览器会认为是请求了一个新的页面,发起http 请求,而新的页面是不存在的(后端没配置的话),所以就会导致404。
nginx 配置静态资源代理,告诉服务器返回什么静态文件。
server{
listen 8080;
server_name localhost;
root /usr/share/nginx/lhtml/dist;
try_files $uri /index.html; // 添加这一条
index index.html;
charset utf-8;
}
使用webpack解决本地运行
devServer:{ historyApiFallback:true }
Map 和Weakmap 的区别
WeakMap是ES6中新增的一种集合类型,叫做弱映射。它和Map是兄弟关系,与Map的区别在于这个弱字,API还是Map那套API。
Map的键可以是任意类型,WeakMap只接受对象作为键,不接受其它类型的值作为键
Map的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键;WeakMap的键是弱引用,如果创建了一个弱引用对象,不会被垃圾回收关注,如果不再需要,weakmap中的键名对象和所对应的键值对会自动消失,不再手动删除引用。
Map可以被遍历,WeakMap不能被遍历
JS由于其特殊的 JS运行机制 事件循环机制 ,没有设置exit函数,
但是存在中断函数运行的方法,
可以将整个脚本包裹为自执行函数,再 throw 或 return,
上述两个方法都不能阻止异步任务的继续执行