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寫服務時,只要服務開着,全局就不會回收閉包