setTimeout(function(){ console.log('set1'); }) new Promise(function(resolve){ console.log('pr1'); // 至关于同步代码 resolve() }).then(function(){ console.log('then1'); }) setTimeout(function(){ console.log('set2'); }) new Promise(function(resolve){ resolve() }).then(function(){ console.log('then2'); }) console.log(3) // 微 ['then1','then2'],宏 ['set1','set2'] // pr1 3 then1 then2 set1 set2
// 加强版 setTimeout(function(){ console.log('set1'); new Promise(function(resolve){ resolve() }).then(function(){ console.log('then3'); }) }) new Promise(function(resolve){ console.log('pr1'); // 至关于同步代码 resolve() }).then(function(){ console.log('then1'); }) setTimeout(function(){ console.log('set2'); }) new Promise(function(resolve){ resolve() }).then(function(){ console.log('then2'); }) console.log(3) // 第一遍 微 ['then1','then2'],宏 ['set1','set2'] // 第2遍,执行宏任务时会再次把微任务插入到微任务队列 微 ['then3'],宏 ['set1','set2'] // pr1 3 then1 then2 set1 then3 set2
微任务会先于宏任务执行node
微任务队列空了才去执行下一个宏任务c++
async function a(){ console.log('async') } a(); console.log(3) // async 3
async function a(){ // await 从使用上来讲,必须等待一个promise var b = await new Promise(function(resolve){ resolve(7) }) console.log(5) console.log(b) } a(); console.log(3) // 3 5 7
for(var i = 0; i < 10; i++){ setTimeout(() => { console.log(i) }); } // 10次10 // 闭包解决 for(var i = 0; i < 10; i++){ (function(i){ console.log(i) })(i) } // 最好是使用let造成块级做用域
var a = [1,2,3] function f(){ a[3] = 4; a = [100]; } f(); console.log(a) // [100]
var a = [1,2,3] function f(a){ a[3] = 4; a = [100]; } f(a); console.log(a) // [1,2,3,4]
// 解读 var a = [1,2,3] function f(a){ var a = a; // 隐式有句代码 把外部的a 赋值给 局部的a a[3] = 4; // 由于是引用类型,外部的a和内部的a都变成 [1,2,3,4] a = [100]; // 给局部的a赋值,局部的a切断了和外部a的联系 console.log(a) // 打印的是局部的a [100] } f(a); console.log(a) // 是所有的 a [1,2,3,4]
let a = [1,2,3]; let b = a; // 是把数组的内存地址指向b a[3] = 4; // 全部修改a b也会变,由于内存地址变掉了
从当前做用域出发,逐级向上查找,直到window,若是window也没有,那就是undefined数组
var c = 123; function a(){ console.log(c); // 123 }
var c = 123; function a(){ var c = 456; console.log(c); // 456 }
var a = { n: 1 } var b = a; a.x = a = { n: 2 } console.log(a.x); // undefined console.log(b.x); // {n: 2}
// 解析 var a = { n: 1 } var b = a; // a.x .号运算优先级别最高 // a.x 会在原来的内存地址中,申请一块新的内存地址 a.x = a = { n: 2 }
var size = 20*1024*1024; var arrAll = []; for(var i = 0; i < 20; i++){ arrAll.push(new Array(size)); }
知识点:v8引擎64位只有1.4g的内存能够支配,node可使用C加加的内存,node源码是用c++写的promise
由于JavaScript进行一次回收要把整个js暂停,因此不能常常回收,回收100m内存,大概须要10ms浏览器
function getMemory() { var mem = process.memoryUsage(); var format = function(bytes) { return (bytes / 1024 / 1024).toFixed(2) + "MB"; } console.log('heapTotal' + format(mem.heapTotal) + 'heapUsed:' + format(mem.heapUsed)); } var size = 20 * 1024 * 1024; var arrAll = []; for (var i = 0; i < 20; i++) { getMemory(); arrAll.push(new Array(size)); }
若是不确认本身的数据放在全局是否是很大,可作一些大小的限制缓存
var size = 20 * 1024 * 1024; var arrAll = []; for (var i = 0; i < 20; i++) { if(arrAll.length > 4){ arrAll.shift(); } arrAll.push(new Array(size)); getMemory(); }
由上图能够看出,虽然数据进行了限制,被删除了,仍是在内存中的,尚未被回收,直到内存快满的时候才进行的回收,把没用的回收掉,内存才回归到一个真实可以使用的状态数据结构
总结:在用node写服务时,只要服务开着,全局就不会回收闭包