一图理清原型
蓝色线表示原型链
词法作用域
函数的作用域在函数定义的时候就决定
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f();
}
checkscope();
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
checkscope()();
闭包
核心就是: 函数的作用域在函数定义的时候就决定了
真正理解这句话的时候闭包什么的也就理解了。
在全局作用域中“定义”一个函数到时候,只会创建包含全局作用域的作用域链。
只有“执行”该函数的时候,才会复制创建时的作用域,并将当前函数的局部作用域放在作用域链的顶端。
易错点
0.1+0.2!==0.3
IEE754计数法,损失精度 解决方法:
0.1+0.2-0.3<Number.EPSILON
parseFloat((0.1 + 0.2).toFixed(10))
DOMContentLoaded VS window.onload
DOMContentLoaded是在DOM解析完成后触发/$document.ready() window.onload 是在页面加载完毕触发
-
解析HTML结构。
-
加载外部脚本和样式表文件。
-
解析并执行脚本代码。//js之类的
-
DOM树构建完成。//DOMContentLoaded
-
加载图片等外部文件。
-
页面加载完毕。//load
在第4步的时候DOMContentLoaded事件会被触发。
在第6步的时候load事件会被触发。
async/defer
defer 在 DOMContentLoaded 事件之前执行。具有 defer 特性的脚本保持其相对顺序,就像常规脚本一样。
async 下载完就执行,当我们将独立的第三方脚本集成到页面时,此时采用异步加载方式是非常棒的:计数器,广告等,因为它们不依赖于我们的脚本,我们的脚本也不应该等待它们,先加载先执行
动态脚本
默认情况下,动态脚本的行为是“异步”的。
也就是说:
- 它们不会等待任何东西,也没有什么东西会等它们。
- 先加载完成的脚本先执行(“加载优先”顺序)。
如果我们显式地设置了 script.async=false,则可以改变这个规则。然后脚本将按照脚本在文档中的顺序执行,就像 defer 那样。
模块化
CommonJS: node规范,同步的 ES6:
CommonJS VS ES6
- CommonJS 同步 ES6 异步
- 前者值导入,引入后就不会改变 后者指向内存的一块地址,改变值也会改变导入
- 前者支持动态导入,也就是
require(${path}/xx.js),后者目前不支持,但是已有提案 - 后者会编译成
require/exports来执行的
proxy
缓存
https
优化
垃圾回收机制
宏任务VS微任务
Vue
vue3的变化
vite原理
当冷启动开发服务器时,基于打包器的方式启动必须优先抓取并构建你的整个应用,然后才能提供服务。
Vite 通过在一开始将应用中的模块区分为 依赖 和 源码 两类,改进了开发服务器启动时间。
vuex/vue-route源码及原理
diff 算法
vNode 同层比较,广度优先比较同层Node,当数据改变时,会触发setter,并且通过Dep.notify去通知所有订阅者Watcher,订阅者们就会调用patch方法,给真实DOM打补丁,更新相应的视图。### patchVnode方法
这个函数做了以下事情:
- 找到对应的
真实DOM,称为el - 判断
newVnode和oldVnode是否指向同一个对象,如果是,那么直接return - 如果他们都有文本节点并且不相等,那么将
el的文本节点设置为newVnode的文本节点。 - 如果
oldVnode有子节点而newVnode没有,则删除el的子节点 - 如果
oldVnode没有子节点而newVnode有,则将newVnode的子节点真实化之后添加到el - 如果两者都有子节点,则执行
updateChildren函数比较子节点,这一步很重要
updateChildren
为什么不用key来做v-for的index存在性能问题
unshift了一个