JS底层机制

时间: 2019-11-20阅读: 406标签: 机制

JavaScript的执行机制-eventloop

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


微任务:Promise,process.nextTick宏任务:整体代码script,setTimeout,setInterval

微任务会先于宏任务执行

微任务队列空了才去执行下一个宏任务

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也会变,因为内存地址变掉了
参数在方法内,相当于一个局部变量

思考:

问题一:js是如何查找变量的?

从当前作用域出发,逐级向上查找,直到window,如果window也没有,那就是undefined

var c = 123;
function a(){
    console.log(c);  // 123
}
var c = 123;
function a(){
    var c = 456;
    console.log(c);  // 456
}
问题二:JavaScript的数组并不是数据结构意义上的数组,为什么?
数据结构意义上的数组是连续相等的内存变量,定义的时候就规定大小,类型真正的数组是不可以扩容的。
问题三:数据结构上扩容一个数组,内存做了啥?
重新申请一个要扩容大小的内存再把扩容前的内容复制过来,然后再写入要扩容的内容

难题来喽

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
}



V8引擎内存问题

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++写的

内存如何回收?


为什么等内存满了后才回收?

因为JavaScript进行一次回收要把整个js暂停,所以不能经常回收,回收100m内存,大概需要10ms

内存查看

浏览器 window.performanceNode process.memoryUsage()
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写服务时,只要服务开着,全局就不会回收

容易引发内存使用不当的场景

滥用全局变量缓存不限制操作大文件


站长推荐

1.阿里云: 本站目前使用的是阿里云主机,安全/可靠/稳定。点击领取2000元代金券、了解最新阿里云产品的各种优惠活动点击进入

2.腾讯云: 提供云服务器、云数据库、云存储、视频与CDN、域名等服务。腾讯云各类产品的最新活动,优惠券领取点击进入

3.广告联盟: 整理了目前主流的广告联盟平台,如果你有流量,可以作为参考选择适合你的平台点击进入

链接: http://www.fly63.com/article/detial/6958

Javascript中的执行机制_Event Loop

众所周知,Javascript是单线程语言, 这就意味着,所有的任务都必须按照顺序执行,只有等前面的一个任务执行完毕了,下一个任务才能执行。如果前面一个任务耗时很长,后一个任务就得一直等着,因此,为了实现主线程的不阻塞,就有了Event Loop。

PHP中session机制解析

php默认用磁盘文件来实现session,在php.ini中session.save_handler = files定义session机制,sesson_start()函数是启动session的开始,session默认存放在文件中,且具有一定概率触发session的垃圾回收机制。

vue---由nextTick原理引出的js执行机制

最开始查看nextTick这个方法的时候,眼瞎看成了nextClick。。。我还在疑问难道是下一次click之后处理事件。。。然后用这个方法的时候,就只知道是用在DOM更新之后调用回调方法。

JS垃圾回收机制

找出不再继续使用的变量,然后释放掉其占用的内存。当变量进入环境(可以理解为一个函数开始执行了)时,就将这个变量标记为“进入环境”,从逻辑上讲,不能释放掉进入环境的变量,而当变量离开环境的的时候,则将其标记为离开环境。

深入解析 Node.js 事件循环工作机制

本文从对线程、事件循环、事件循环常见的问题和错误上分别进行说明,进一步探索了 Node 的核心工作原理。每当人们谈论 Node.js 时,都会出现很多问题,比如它 究竟是什么 、这项技术有什么用、它是否 有未来 等等。

JS代码在nodejs环境下执行机制和事件循环

nodejs是单线程执行的,同时它又是基于事件驱动的非阻塞IO编程模型。这就使得我们不用等待异步操作结果返回,就可以继续往下执行代码。当异步事件触发之后,就会通知主线程,主线程执行相应事件的回调。

JavaScript预解释是一种毫无节操的机制

js代码执行之前,浏览器首先会默认的把所有带var和function的进行提前的声明或者定义:1.理解声明和定义、2.对于带var和function关键字的在预解释的时候操作不一样的、3.预解释只发生在当前的作用域下

React事件机制-事件分发

之前讲述了事件如何绑定在document上,那么具体事件触发的时候是如何分发到具体的监听者呢?我们接着上次注册的事件代理看。当我点击update counter按钮时,触发注册的click事件代理。topLevelType为click,nativeEvent为真实dom事件对象。

浅谈小程序运行机制

接触小程序有一段时间了,总得来说小程序开发门槛比较低,但其中基本的运行机制和原理还是要懂的。“比如我在面试的时候问到一个关于小程序的问题,问小程序有window对象吗?

浏览器JS事件触发机制

事件会从最外层开始发生,直到最具体的元素,也就是说假如父元素与子元素都绑定有点击事件,又互相重叠,那么先出发的会是父元素的事件,然后再传递到子元素。事件会从最内从的元素开始发生,再向外传播,正好与事件捕获相反。

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!

文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全运营推广