JavaScript 扯几句单线程相关

JavaScript 扯几句单线程相关

众所周知,Javascript是单线程执行的,这也就是说:JavaScript在同一个时间上只能处理一件事。他不像C,Java等这些多

线程的,可以开不同的线程去同时处理多件事情。

那么为什么别的语言都可以这么方便的去开多个线程去同时执行多个任务,JavaScript却不行呢?

“天将降大任于斯人也,必先苦其心志,劳其筋骨,饿其体肤,空乏其身,行指乱其所为,所以动心忍性,曾益其所不能”
                                                --《孟子》

正是因为JavaScript背负着重大的使命,所以他只能默默的看着别人拥有多线程。他作为浏览器脚本语言,只要是在于和用户进

行交互/处理前端数据/操作DOM。

以代码举例吧:

  function addDom(){
    var html = document.createElement("div");
    html.innerHTML = "This is div "+i;
    document.getElementById("myDiv").appendChild(html);
  }
  function deleteDom(){
    var myDiv = document.getElementById("myDiv");
    //if(myDin.childNodes[0]){
        myDiv.removeChild(myDin.childNodes[0]);
    //}
  }

注意:以上代码注释部分可以让逻辑变的更严谨,此处需要报错已证明观点,所以加以注释。

按照以上代码执行addDom函数是能正确的生成这么一个DOM的吧,即便是在addDom函数还在执行过程中去执行

deleteDom,deleteDom也将会在addDom执行完后才执行,那么就能完整的走完一个DOM的添加和删除操作了,这正是因

为JavaScript是单线程。

现在我们假如JavaScript可以有多线程,那么我们让一个线程执行addDom函数的时候,在addDom还在执行的过程中再去执

行deleteDom,这时候将会再开一个线程来执行,这时候浏览器脑子短路了,它不知道以哪个为主了...如果先执行完了

deleteDom,那么效果就是即报了错还没达到想要的效果。

综上所述,JavaScript确实不适用于多线程,为了交互,他只能独自忍受了(所以当报错不会继续向下执行的时候,各位就别喷

JavaScript了,好好检查自己写的代码才是这时候该做的)。

事件列队和异步执行

既然JavaScript是单线程执行的,那么有很多事件需要执行的时候,肯定需要排好队一个个来的吧。接下来我们就扯扯事件队列

和异步。

JavaScript的事件队列里就是编排着接下来将要被逐个执行的事件,只有当前一个任务被执行完了,才会接下来执行后面一个任

务。当我们触发一个事件,那么这个事件会被加入到事件列表末尾,当然不能插队咯,毕竟都是良民呐~

以上就是对事件队列的简单介绍,那么异步又是怎么回事呢?

Javascript语言将任务的执行模式分成两种:同步(Synchronous)和异步(Asynchronous)。

同步就是按照事件队列的顺序,有条不紊的执行下来。

异步则不同,每个任务都可以有一或多个回调函数(callback),当前面那一个任务执行完后,不去执行下一个任务,先执行其本

身存在的回调函数,而下一个任务不等前一个任务结束,自顾自的开始执行了,这时候执行顺序就不一样的,产生异步了。

奉上代码:

  var num = 0;
  function firstFn(){
      num +=1;
  };
  function secondFn(value){
      if(value === 1){
          console.log("The num is 1"); //The num is 1
      } else{
          console.log("The num still 0");
      }
  }
  firstFn();
  secondFn(num);

以上是能正常打印出来的,因为先执行了第一个函数,所以这时num已经被加1了,所以判断生效。

  var num = 0;
  function firstFn(){
      setTimeout(function(){
         num +=1;
      },0);  // 这里我们用setTimeout做了异步处理
  };
  function secondFn(value){
      if(value === 1){
          console.log("The num is 1");
      } else{
          console.log("The num still 0"); //The num still 0
      }
  }
  firstFn();
  secondFn(num);

这时候,再这样执行就没用了。因为setTimeout将num++的事件放到了事件列表的末尾去了,second(num)是在它的前面,

所以现在执行是打印 The num still 0。那么怎么证明该事件被放到最后了呢?看下面的代码:

  <div id="myDiv" onclick="addEvent()">click me</div>

  var num = 0;
  function firstFn(){
      setTimeout(function(){
         num +=1;
      },0);
  };
  function secondFn(value){
      if(value === 1){
          console.log("The num is 1"); //The num is 1
      } else{
          console.log("The num still 0");
      }
  }
  firstFn();
  function addEvent(){
      secondFn(num);
  } 

当我们点击id为myDiv的div的时候,将触发click事件吧,该事件会调用addEvent函数吧,addEvent函数会在事件队列的末尾

加入新的需要执行的事件吧。这时候我们点击该div,就会打印 The num is 1 了。

同理理解setInterval。

下面顺便贴一段有小伙伴提问过的问题代码:

正常的代码:

  var i = 3;
  for(;i>0;i--){
    console.log(i);  //打印顺序:3   2   1
  };

"不正常"的代码:

  var i = 3;
  for(;i>0;i--){
    setTimeout(function(){console.log(i);},0);  //打印顺序 0   0   0
  };

人家问的就是为什么都设置延迟时间为0了,打印出来的还是不正常的。

对于setTimeout的通常描述:给定一个回调及N毫秒的延迟,setTimeout将会在N毫秒后运行该回调。

所以大多数情况下,这个描述只能算大致正确,不能算完全正确。

而且setTimeout还附带了个隐藏的可大可小的坑(将由线程阻塞导致):

  var start = new Date;
  setTimeout(function(){
      var end = new Date;
      console.log("End Time: ",end - start," ms"); // 有几次打印的是End Time:  1001  ms ,这还是在没有其他阻塞的,只运行这一个事件的情况下出现偏差
  },1000);

所以上面那个描述的N毫秒将在某些情况下会出现偏差。
好了,就写这么多先吧。明天还得上班呢,今天算拖的很晚了...还是手机编辑的,本来打算睡觉,写一半没完成,心里怪难受的...
如理解有偏差,还望大家不吝指教,大家一起交流才能更好的进步。

时间: 2024-10-12 01:34:26

JavaScript 扯几句单线程相关的相关文章

0182 JavaScript执行机制:单线程,同步任务和异步任务,执行栈,消息队列,事件循环

以下代码执行的结果是什么? [结果是1 2 3 ] console.log(1); setTimeout(function () { console.log(3); }, 1000); console.log(2); 以下代码执行的结果是什么? [结果是1 2 3 ] console.log(1); setTimeout(function () { console.log(3); }, 0); console.log(2); 1.3.1 JS 是单线程 单线程就意味着,所有任务需要排队,前一个任

JavaScript基础 每句话后的分号要加上

镇场诗: 清心感悟智慧语,不着世间名与利.学水处下纳百川,舍尽贡高我慢意. 学有小成返哺根,愿铸一良心博客.诚心于此写经验,愿见文者得启发.------------------------------------------ code: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta http-equiv="Content-Type" content="text/html; charset=ut

JavaScript中的DOM及相关操作

一.什么是DOM JavaScript由ECMAScript.DOM和BOM三部分组成,其中DOM代表描述网页内容的方法和接口,即文档对象模型(Document Object Model).在网页上,组织页面(或文档)的对象被组织在一个树形结构中,用来表示文档中对象的标准模型就称为DOM,而树形结构就是我们常说的DOM树. 维基百科中介绍DOM更为准确:DOM是一种跨平台和语言非依赖性的应用程序编程接口,即处理现在的HTML,XHTML或XML文档作为树结构,其中每个节点是一个对象,每个节点表示

JavaScript常用語句

1.document.write(""); 输出语句2.JS中的注释为//3.传统的HTML文档顺序是:    document->html->(head,body)4.一个浏览器窗口中的DOM顺序是:    window->(navigator,screen,history,location,document)5.得到表单中元素的名称和值:    document.getElementById("表单中元素的ID号").name(或value)6

Javascript的异步与单线程

一.前言 我们都知道,javasript是一个单线程的语言:所谓单线程就是同一时间不能做两件事情,两段代码不能同时执行:因为这种机制,才避免了两段js同时对一个DOM节点进行渲染的冲突.但是也会因此产生一个问题,比如说有一个非常耗时的操作在js中执行,因为js是按顺序执行的,所以会导致代码一直卡在这个耗时的方法那里,从而造成页面假死的状态,为了解决这个问题,js也提供了一些解决方案,比 如Ajax.setTimeout.setInterval,提供了异步的解决方案.有人会说,那单线程和异步同时存

javascript中日期函数的相关操作

2016-08-03 11:41:10 new Date() new Date(milliseconds) new Date(datestring) new Date(year, month) new Date(year, month, day) new Date(year, month, day, hours) new Date(year, month, day, hours, minutes) new Date(year, month, day, hours, minutes, second

Javascript 数组(Array)相关内容总结

创建数组 var colors = new Array(); //创建新数组 var num = new Array(3); //创建包含三项的新数组 var names = new Array("Dalu"); // 创建包含一项数据"Dalu"的新数组 检测数据类型是否为数组 if(Array.isArray(value)){ // ECMAscript5新增 // 是数组 }; if(value instanceof Array){ // 是数组 } 转换数组

javascript中五句话

1.弹出框 ,小括号中就是弹出的内容 alert("我是一个弹出框"); 2.控制台输出 小括号里面就是 控制台输出的东西 console.log("我是控制台输出的内容"); 3.弹出输入框,可以接受用户输入的信息. 3.1 prompt("请输入你的名字"); 3.2 prompt("请输入你的名字","张三"); 1 function disp_prompt() 2 { 3 var name = pr

JavaScript实现排序二叉树的相关算法

1.创建排序二叉树的构造函数 /** * 创建排序二叉树的构造函数 * @param valArr 排序二叉树中节点的值 * @constructor */ function BinaryTree(valArr) { function Node(val) { this.value = val; this.left = null; this.right = null; } var root = null; valArr.forEach(function (val) { var newNode =