美文网首页
一个JavaScript项目的研究-1

一个JavaScript项目的研究-1

作者: 高大强19 | 来源:发表于2020-05-23 20:31 被阅读0次

    通过研究和阅读项目是学习最快的路径。现在接触js后,拿到成熟的项目看起来。这是基于socket.io和redis转发机制的IM项目。

    1.阅读js文件遇到require('http'),查之。阮一峰阮大神的文章很详细,层次感强。

    Node.js 自2009年诞生以来,遵循CommonJS格式。npmjs.com 中已经存放了15w+的模块大部分是CommonJS的,该模式的核心就是require语句,模块通过他加载,类似python的import。

    (1)如果 X 是内置模块(比如 require('http'))

    1)返回该模块。

    2)不在继续执行。

    (2)如果 X 以 "./" 或者 "/" 或者 "../" 开头

      a. 根据 X 所在的父模块,确定 X 的绝对路径。

      b. 将 X 当成文件,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。

    X

    X.js

    X.json

    X.node

      c. 将 X 当成目录,依次查找下面文件,只要其中有一个存在,就返回该文件,不再继续执行。

    X/package.json(main字段)

    X/index.js

    X/index.json

    X/index.node

    (3)如果 X 不带路径

      a. 根据 X 所在的父模块,确定 X 可能的安装目录。

      b. 依次在每个目录中,将 X 当成文件名或目录名加载。

    (4) 抛出 "not found"

    2.Node.js Domain(域) 简化异步代码的异常处理,可以捕捉处理try catch无法捕捉的异常。引入 Domain 模块 语法格式如下:

    var domain = require("domain")

    domain模块,把处理多个不同的IO的操作作为一个组。注册事件和回调到domain,当发生一个错误事件或抛出一个错误时,domain对象会被通知,不会丢失上下文环境,也不导致程序错误立即退出,与process.on('uncaughtException')不同。

    Domain 模块可分为隐式绑定和显式绑定:

    隐式绑定: 把在domain上下文中定义的变量,自动绑定到domain对象

    显式绑定: 把不是在domain上下文中定义的变量,以代码的方式绑定到domain对象

    3. require('request')

    -- 如何在javascript中获取请求转发后的request对象传递的数据?

    4.var fs = require('fs');

    fs模块用于对系统文件及目录进行读写操作。

    一、同步和异步

    使用require('fs')载入fs模块,模块中所有方法都有同步和异步两种形式。

    异步方法中回调函数的第一个参数总是留给异常参数(exception),如果方法成功完成,该参数为null或undefined。

    异步写法demo:有一个回调函数。

    var fs = require('fs'); // 载入fs模块

    fs.unlink('/tmp/shiyanlou', function(err) {

        if (err) {

            throw err;

        }

        console.log('成功删除了 /tmp/shiyanlou');

    });

    var fs = require('fs');

    fs.unlinkSync('/tmp/shiyanlou'); // Sync 表示是同步方法

    console.log('成功删除了 /tmp/shiyanlou');

    同步方法执行完并返回结果后,才能执行后续的代码。而异步方法采用回调函数接收返回结果,可以立即执行后续代码。

    二、readFile读取文件

    fs.readFile(filename,[option],callback) 方法读取文件。

    参数说明:

    filename String 文件名

    option Object

    encoding String |null default=null

    flag String default='r'

    callback Function

    5.server.on('request',function(req,res) 中req 和res

    服务器:

    在服务端接收方面来说:

    使用http.Server()方法。再绑定request这个事件。他会返回有两个实例一个是

    http.ServerRequest  req客户端请求的内容都在这个对象中

    和 http.Reponse res  要发送给客户端的属性和方法都在这个对象中

    也就是这个函数第二个参数中的两个参数

    其中:http.ServerRequest对象中有data事件,data事件的中有一个参数chunk这个参数就是

    服务器所接收到的内容

    var http = require('http')

    var server = http.Server();

    server.on('request',function(req,res){

      req.on('data',function(chunk){

        //这里的 chunk 就是客户端表单提交过来的东西

          res.write(内容)要回显示给客户端的内容

          在客户端页面的http.ClientRepsonse这个对象负责接收这个信息

    })

    })

    6. __dirname 总是指向被执行 js 文件的绝对路径

    fs.readFile(__dirname + '/index.html',

    ./ 会返回你执行 node 命令的路径,例如你的工作路径。

    7.例子中用时间戳加随机数id作为唯一标识。

    在用的,若是用redis则是用了他的转发机制,和它的生成唯一uuid的机制。

    客户端:

    8.CSS1Compat 标准兼容模式

    var d = document,

      dd = d.documentElement,

      db = d.body,

      dc = d.compatMode == 'CSS1Compat',

      dx = dc ? dd: db;

    9:msgObj.style.minHeight

    10:

    //添加系统消息

    var html = '';

    html += '<div class="msg-system">';

    html += user.username;

    html += (action == 'login') ? ' 加入了聊天室' : ' 退出了聊天室';

    html += '</div>';

    var section = d.createElement('section');

    section.className = 'system J-mjrlinkWrap J-cutMsg';

    section.innerHTML = html;

    this.msgObj.appendChild(section); 

    msg-system 是css中定义的样式

    createElement(nodename)方法通过指定名称创建一个元素,创建元素的名称

    jr link Wrap cut  初级环套剪切

    11: 打开一个WebSocket:

    //连接websocket后端服务器

    this.socket = io.connect('ws://127.0.0.1:3001');

    12

     //监听消息发送

    this.socket.on('message', function(obj){

        var isme = (obj.userid == CHAT.userid) ? true : false;

        var contentDiv = '<div>'+obj.content+'</div>';

        var usernameDiv = '<span>'+obj.username+'</span>';

        var section = d.createElement('section');

        if(isme){

            section.className = 'user';

            section.innerHTML = contentDiv + usernameDiv;

        } else {

            section.className = 'service';

            section.innerHTML = usernameDiv + contentDiv;

        }

        CHAT.msgObj.appendChild(section);

        CHAT.scrollToBottom();  

    });

    如果是自己,执行section.className = 'user'; 。。。

    section.className = 'system J-mjrlinkWrap J-cutMsg';

    section中的class这个

    13

      e = e || event;

            if (e.keyCode === 13) {

                CHAT.usernameSubmit();

            }

    e = e || window.event 是我们在做事件处理时候区分IE和其他浏览器事件对象时常用的写法。

    14 var const let

    https://www.jianshu.com/p/4e9cd99ecbf5

    随着ES6规范的到来,Js中定义变量的方法已经由单一的 var 方式发展到了 var、let、const 三种之多。var 众所周知,可那俩新来的货到底有啥新特性呢?到底该啥时候用呢?

    Js没有块级作用域

    请看这样一条规则:在JS函数中的var声明,其作用域是函数体的全部。

        for(var i=0;i<10;i++){

              var a = 'a';

        }

        console.log(a);

    明明已经跳出 for 循环了,却还可以访问到 for 循环内定义的变量 a ,甚至连 i 都可以被放访问到,尴尬~

    2.** 循环内变量过度共享 **

    你可以猜一下当执行以下这段代码时会发生什么

    for (var i = 0; i < 3; i++) {

          setTimeout(function () {

            console.log(i)

          }, 1000);

    }

    在浏览器里运行一下,看看和你预想的结果是否相同?

    没错,控制台输出了3个3,而不是预想的 0、1、2。

    事实上,这个问题的答案是,循环本身及三次 timeout 回调均共享唯一的变量 ** i 。当循环结束执行时,i 的值为3。所以当第一个 timeout 执行时,调用的 i 当让也为 3 了。

    话说到这儿,想必客官已经猜到 let 是干嘛用的。

    你没猜错,就是解决这两个bug的。你尽可以把上述的两个例子中的 var 替代成 let 再运行一次。

    注意:必须声明 'use strict' 后才能使用let声明变量,否则浏览并不能显示结果

    let是更完美的var

    let声明的变量拥有块级作用域。 也就是说用let声明的变量的作用域只是外层块,而不是整个外层函数。let 声明仍然保留了提升特性,但不会盲目提升,在示例一中,通过将var替换为let可以快速修复问题,如果你处处使用let进行声明,就不会遇到类似的bug。

    let声明的全局变量不是全局对象的属性。这就意味着,你不可以通过window.变量名的方式访问这些变量。它们只存在于一个不可见的块的作用域中,这个块理论上是Web页面中运行的所有JS代码的外层块。

    形如for (let x...)的循环在每次迭代时都为x创建新的绑定。

    这是一个非常微妙的区别,拿示例二来说,如果一个for (let...)循环执行多次并且循环保持了一个闭包,那么每个闭包将捕捉一个循环变量的不同值作为副本,而不是所有闭包都捕捉循环变量的同一个值。

    所以示例二中,也以通过将var替换为let修复bug。

    这种情况适用于现有的三种循环方式:for-of、for-in、以及传统的用分号分隔的类C循环。

    用let重定义变量会抛出一个语法错误(SyntaxError)。

    这个很好理解,用代码说话

    let a = 'a';

    let a = 'b';

    上述写法是不允许的,浏览器会报错,因为重复定义了。

    ** 在这些不同之外,let和var几乎很相似了。举个例子,它们都支持使用逗号分隔声明多重变量,它们也都支持解构特性。 **

    const

    ES6引入的第三个声明类关键词:const

    一句话说明白,const 就是用来定义常量的!任何脑洞(fei)大(zhu)开(liu)的写法都是非法的

    比如这样:

    //只声明变量不赋值

    const a

    这样:

    //重复声明变量

    const a = 'a';

    const a = 'b';

    还有这样:

    //给变量重新赋值

    const a = 'a';

    a = 'b'

    再来个黑科技:

    //不过不推荐这么干,实在没啥意思,常量常量,不变的才叫常量嘛~

    const a = {a:'a'};

    //重新赋值当然是行不通的了

    a = {a:'b'};

    //嘿嘿嘿科技

    a.a = 'b'

    const 确实没啥说的,普通用户使用完全没问题,高(dou)端(bi)用户咋用都是问题。

    相关文章

      网友评论

          本文标题:一个JavaScript项目的研究-1

          本文链接:https://www.haomeiwen.com/subject/mmnlahtx.html