深入理解JavaScript特性

最近在读《JavaScript高级程序设计》这一本书,里面提到了JavaScript的特征,倍感兴趣,于是结合自己的认识,在这里进行一下总结。

 

1、JavaScript的垃圾回收机制

javaScript中的5种数据类型存放在栈中(Undefined、Null、Boolean、Number、String),非基本数据类型存放在堆中,占用内存,堆不会被程序自动释放。

一张图看懂JS中数据类型的存放位置:基本数据类型存放在栈中,非基本数据类型(对象)存放在堆中,变量obi1在栈中存储的只是堆中对象的地址。

声明变量a=对象,只是声明一个指针地址指向存储该对象的内存空间,每多一个指向同一内存空间的指针地址,该对象的引用计数就会加1。

如果代码在运行过程中有一个对象不再被需要了,但是引用计数不为零,垃圾回收机制就不能释放这块内存,就被称为内存泄漏。

释放内存的方法就是 接触对该内存地址的引用,将引用他的指针地址设置为null,如:a=null;

 

2、JavaScript 单线程(同一个时间只能做一件事)核心特征

JS除了主线程之外还存在一个任务队列,(js单线程所有任务必须排队完成)。

js计算能力很弱如果存在一个耗时较长的任务,后一个任务就必须等待很长时间让前一个任务执行完毕,,如果是网络请求他的耗时完全取决于网络状况,(Ajax)不符合js设计逻辑。

主线程可以忽略io(input/output)设备,挂起处于等待中的任务(监听事件绑定的任务,ajax网络请求)先运行排在后面的任务,,等到io设备有了返回结果,再回过头把挂起任务执行下去 (异步事件)。

 

所有任务分两种synchronous同步事件asynchronous异步事件,在js中:

同步事件在主线程上排队执行(前一个执行完毕,后一个才能执行)。

异步事件不进入主线程,而进入任务队列(task queue),只有任务任务队列通知主线程,某个异步任务可以执行了,该任务才会从任务队列中取出进入主线程。

 

3、JavaScript运行机制步骤

(1)所有同步任务都在主线程上依次执行,形成(执行栈)。栈的定义:先进后出,后进先出。

举个例子:定义三个函数,sayHello函数直接在student函数体内调用,isAdult函数作为参数传给了sayHello函数,在这里isAdult也是一个回调函数。

三个函数进入执行栈的顺序依次是:student,sayHello,isAdult

        function student(){
            var age = 18;
            var name = '小李'
            sayHello(name,age,isAdult(age))
            console.log("student函数")   //最后出栈
        }

        function isAdult(age){
            var result = age >= 18 ? '成年':'未成年'
            console.log("isAdult函数")   //最先出栈
            return result;
        }

        function sayHello(name,age,reust){
            console.log('hello!This is '+name+' '+age+'years old 我' + reust)
            console.log("sayHello函数")
        }
        student();

看输出结果:三个函数出栈的顺序依次是:isAdult,sayHello,student

 

(2)主线程之外,存在一个任务队列,只要异步任务有了返回结果,该任务就会被放入任务队列中。

(3)执行栈中所有任务执行完毕后,就会访问任务队列,检查队列中有哪些事件,获取任务队列中最先等待的事件,让该事件进入执行栈,开始执行。

(4)不断重复第三步。

 

4、JavaScript中回调函数callback(事件绑定函数)

例:绑定点击事件,当点击事件触发时 js会调用事件绑定的函数该函数称为事件的回调函数(异步任务必须指定回调函数)。

任务队列 先进先出数据结构,排在前面的事件会先被主线程读取,所以如果队列中有'定时器',定时器未必准时触发,取决于前一个任务队列中的函数执行的结束。

 

5、JavaScript中内存区域

程序运行时,需要内存空间存放数据,分别为stack(栈)和heap(堆)。

栈是有结构的,每个区块按照一定的顺序取存放,可以明确的知道每个区块的大小,而堆是没有结构的,数据任意存放,因此栈的调用要快于堆。

每个线程分配一个栈,每个进程分配一个堆,stack是线程独占,heap是线程公用的。

栈是系统自动开辟的自动释放的, 堆是程序员手动开辟和释放的。

posted @ 2017-09-13 10:56  Eamon-Luo  阅读(504)  评论(0编辑  收藏  举报