精选文章 Node学习总结-基础篇

Node学习总结-基础篇

作者:橙子1995 时间: 2020-07-28 11:02:05
橙子1995 2020-07-28 11:02:05

1、谈谈js中的变量类型有哪些?

答:值类型:字符串(string)、数值(number)、布尔值(boolean)、undefined、null、symbol(es6)

引用类型:对象(Object)、数组(Array)、函数(Function)

2、谈谈null和undefined的区别?

答:null是一个表示 "无" 的对象,转为数值时为 0;undefined是一个表示 "无" 的原始值,转为数值时为NaN。

3、谈谈值类型和引用类型的区别?

答:值类型:

  • 1、占用空间固定,保存在栈内存中(当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。)
  • 2、保存与复制的是值本身。
  • 3、使用typeof检测数据的类型。

引用类型:

  • 1、占用空间不固定,保存在堆中(当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。)
  • 2、保存与复制的是指向对象的一个指针
  • 3、使用instanceof检测数据类型
  • 4、使用new()方法构造出的对象是引用型

4、谈谈栈内存和堆内存的区别?

答:首先要明白数据结构中的栈和堆:

  • 栈 :这是一种连续存储的数据结构,具有先进后出的性质。
  • 堆 :是一种非连续的树形存储数据结构,每个节点都有一个值,整棵树是经过排序的。

其次,内存中的栈区和堆区:

  • 栈内存 :由程序自动向操作系统申请分配以及回收,速度快,使用方便,但程序员无法控制。
  • 堆内存 :程序员向操作系统申请一块内存,当系统收到程序的申请时,会遍历一个记录空闲内存地址的链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删除,并将该结点的空间分配给程序。分配的速度较慢,地址不连续,容易碎片化。此外,由程序员申请,同时也必须由程序员负责销毁,否则可能导致内存泄露。

5、谈谈对js作用域的认识。(可能会引出变量提升)

答:在早期的ES5中,js的作用域分为两种,分别为全局作用域和局部作用域。之后在ES6中添加了块级作用域,主要通过命令let和const来实现。

ES5只有全局作用域和函数作用域,没有块级作用域,会带来以下问题:

  • 1.变量提升导致内层变量可能会覆盖外层变量。
  • 2.用来计数的循环变量泄露为全局变量等等。

5、简要说明var、let、const的区别。

答:1.const定义的变量不可以修改(引用类型可以修改,但是引用始终不变,变得是在堆中的对象或者数组或者函数),而且必须初始化。

2.var定义的变量可以修改,如果不初始化会输出undefined,不会报错。

3.let是块级作用域,函数内部使用let定义后,对函数外部无影响。

6、js中==和===的区别。

答:简单来说: == 代表相同, === 代表严格相同(类型也必须相同)。

当进行双等号比较时候:先检查两个操作数数据类型,如果相同,则进行===比较,如果不同,则愿意为你进行一次类型转换,转换成相同类型后再进行比较,而===比较时,如果类型不同,直接就是false。

7、遍历一个json的方法。

答:1、for … in

2、Object.keys(obj).forEach(key)

3、Object.getOwnPropertyNames(obj).forEach(key)

4、Reflect.ownKeys(obj).forEach(key)

8、合并数组的方法。

答:1、for循环 + push()

2、concat()

3、ES6的扩展运算符…

当数组中有引用对象时,第2和3种是浅拷贝。

9、谈谈浅拷贝和深拷贝的区别。

答:浅拷贝:只是拷贝索引,不拷贝对象。原对象变化时,新对象也会随之变化。

深拷贝:拷贝对象。数组的JSON.parse(JSON.stringify(arr))

6、谈谈node中的require加载原理。

答:在node中,每一个js文件相当于一个module(这里node和前端是有区别的),它都会有其独自的变量空间,require相当于在自己的模块中,拿到其他模块的引用。

同一个模块被多个模块引用时,该模块的内容只执行一次,第二次加载时会直接在缓存中加载(require.cache)。

两个模块互相循环引用,并不会造成死循环。(一个模块获取另一个模块的全部引用,而一个模块只会获取另一个模块的未完成的副本)。

大概加载流程:

  • 计算绝对路径
  • 如果有缓存,取出缓存
  • 是否为内置模块
  • 生成模块实例,存入缓存
  • 加载模块
  • 输出模块的exports属性

8、谈谈module.exports和exports的区别。

答:exports只是module.exports的引用,如果module.exports被直接赋值,则exports的赋值不会起作用,例如module.exports='hanjc'。

但是如果是module.exports.name这种增加属性,则exports会起作用。

8、谈谈js中的this指向。

答:1、普通函数调用:这个情况没特殊意外,就是指向全局对象-window。

2、对象函数调用:这个相信不难理解,就是哪个函数调用,this指向哪里。

9、谈谈apply, bind, call这些方法,他们之间的区别。

答:call、apply、bind 都是用来重定义 this 这个对象的。

call、apply、bind 这三个函数的第一个参数都是 this 的指向对象,第二个参数差别就来了:call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔。apply 的所有参数都必须放在一个数组里面传进去。bind 除了返回是函数以外,它的参数和 call 一样。

13、Promise的几种状态。

答:promise有三种状态:pending状态(进行中)reslove状态(已成功)reject状态(已失败)

14、Promise.all的功能及实现。

答:Promise.all接受一个Promise数组,并行执行数组中的所有异步操作,返回结果集。数组里面的promise是并行执行的。

15、async/await相比于promise的优点。

答:1. 简洁(if判断,嵌套等等地方)。2.错误处理(直接用try/catch)。

16、async/await大致的实现原理。

答:async函数是Generator函数的语法糖,用function*定义,方法内用yeild标识,用return返回({value,done}),执行时用next进行下一个步骤。

co 模块:用于 Generator 函数的自动执行,返回一个Promise对象。

17、谈谈express中的中间件。

答:express是一个自身功能极简,完全是路由和中间件构成一个web开发框架:从本质上来说,一个Express应用就是在调用各种中间件。

  • 1、中间件结构app.use([path],function)
  • 2、中间件分类:内置中间件(express.static唯一的内置中间件)、自定义中间件(自己实现的)、第三方中间件(npm导入的中间件,例如bodypaser等等)
  • 3、浏览器向服务器发送一个请求后,服务器直接通过request.定位属性的方式得到通过request携带过去的数据(有用户输入的数据和浏览器本身的数据信息)。这中间就一定有一个函数将这些数据分类做了处理,已经处理好了,最后让request对象调用使用,对的,这个处理数据处理函数就是我们要说的中间件。

由此可见,中间件可以总结以下几点:

  • 1、封装了一些处理一个完整事件的功能函数。
  • 2、非内置的中间件需要通过安装后,require到文件就可以运行。
  • 3、封装了一些或许复杂但肯定是通用的功能。

18、谈谈node单线程、异步IO与事件驱动的理解。

答:nodejs的运行机制:nodejs主线程主要起一个任务调度的作用。nodejs用一个主线程处理所有的请求,将I/O操作交由底下的线程池处理。在所有主线程任务执行完成后,主线程处理事件队列。所以在同步初始化代码执行完成后,nodejs会基于事件队列不停的做事件循环。事实上,nodejs运行环境 = 主线程(单线程,包括事件队列) + 线程池(工作线程池,执行其他工作-多线程)

node 的初始化:

  • 初始化 node 环境。
  • 执行输入代码。
  • 执行 process.nextTick 回调。
  • 执行 microtasks。(Promise.then)

事件循环

  • 1、进入 timers 阶段 (定时器阶段:本阶段执行已经安排的 setTimeout() 和 setInterval() 的回调函数。)
  •       检查 timer 队列是否有到期的 timer 回调,如果有,将到期的 timer 回调按照 timerId 升序执行。
  •       检查是否有 process.nextTick 任务,如果有,全部执行。
  •       检查是否有microtask,如果有,全部执行。
  •       退出该阶段。
  • 2、进入pending IO callbacks阶段。(对某些系统操作(如 TCP 错误类型)执行回调)
  •       检查是否pending的 I/O 回调。如果有,执行回调。如果没有,退出该阶段。
  •       检查是否有 process.nextTick 任务,如果有,全部执行。
  •       检查是否有microtask,如果有,全部执行。
  •       退出该阶段。
  • 3、进入 idle,prepare 阶段:
  •       仅系统内部使用。
  • 4、进入 poll 阶段(检索新的 I/O 事件;执行与 I/O 相关的回调,除了定时器和关闭的回调函数,其余都在这里)
  •       首先检查是否存在尚未完成的回调,如果存在,那么分两种情况。
  •       第一种情况:
  •               如果有可用回调(可用回调包含到期的定时器还有一些IO事件等),执行所有可用回调。
  •               检查是否有 process.nextTick 回调,如果有,全部执行。
  •               检查是否有 microtaks,如果有,全部执行。
  •               退出该阶段。
  •        第二种情况:
  •                如果没有可用回调,执行下一步;
  •                检查是否有 immediate 回调,如果有,退出 poll 阶段。如果没有,阻塞在此阶段,等待新的事件通知。
  •                如果不存在尚未完成的回调,退出poll阶段。
  • 5、进入 check 阶段。(setImmediate() 回调函数在这里执行)
  •       如果有immediate回调,则执行所有immediate回调。
  •       检查是否有 process.nextTick 回调,如果有,全部执行。
  •       检查是否有 microtaks,如果有,全部执行。
  •       退出 check 阶段
  • 6、进入 closing 阶段。(检测关闭的回调函数,例如 xx.on('close'))
  •       如果有immediate回调,则执行所有immediate回调。
  •       检查是否有 process.nextTick 回调,如果有,全部执行。
  •       检查是否有 microtaks,如果有,全部执行。
  •       退出 closing 阶段
  •       检查是否有活跃的 handles(定时器、IO等事件句柄)。
  •       如果有,继续下一轮循环。
  •       如果没有,结束事件循环,退出程序。
  •       注: 在主线程执行完和事件循环总共7个阶段,每一个阶段执行完都会调用一遍process.nextTick回调,一遍microtaks(promise);

5、谈谈nodejs中进程间通讯的方式?

答:1、通过stdin / stdout传递json。

用spawn方法拿到子进程的handle,然后用通过stdin/stdout传递json。

2、原生IPC支持。

同样要有一方能够拿到另一方的handle才行。

3、sockets。

4、message queue。

19、node内存管理情况。

答:在node.js中,内存主要分为两个部分,堆内存和栈内存。

  • 堆内存(heap):存放对象和闭包上下文,v8使用垃圾回收机制管理堆内存。
  • 栈内存(stack):存放局部变量,栈内存的分配比较简单,当程序离开某作用域后,其栈指针下移(回退),整个作用域的局部变量都会出栈被回收。

24、新建Buffer会占用V8分配的内存吗。

答:不会,Buffer属于堆外内存,不是V8分配的。

25、Buffer.alloc和Buffer.allocUnsafe的区别。

答:Buffer.allocUnsafe创建的 Buffer 实例的底层内存是未初始化的。 新创建的 Buffer 的内容是未知的,可能包含敏感数据。使用 Buffer.alloc() 可以创建以零初始化的 Buffer 实例。

26、Buffer的内存分配机制。

答:为了高效的使用申请来的内存,Node采用了slab分配机制。slab是一种动态的内存管理机制。Node以8kb为界限来来区分Buffer为大对象还是小对象,如果是小于8kb就是小Buffer,大于8kb就是大Buffer。

例如第一次分配一个1024字节的Buffer,Buffer.alloc(1024),那么这次分配就会用到一个slab,接着如果继续Buffer.alloc(1024),那么上一次用的slab的空间还没有用完,因为总共是8kb,1024+1024 = 2048个字节,没有8kb,所以就继续用这个slab给Buffer分配空间。

如果超过8kb,那么直接用C++底层地宫的SlowBuffer来给Buffer对象提供空间。

27、Buffer乱码问题。

答:rs.setEncoding('utf8')

      (我试过iconv解决,只不过电脑得提前安装一下)

 

勿删,copyright占位
分享文章到微博
分享文章到朋友圈

上一篇:花里胡哨系列之Mybatis源码终篇---感悟(九)

下一篇:ORLACE数据库管理-resource manager资源管理优化

您可能感兴趣

  • 学计算机必看:程序员部落酋长,给计算机专业学生的 6 个建议!

    如果你喜欢编程,那么你真是受到了上天的眷顾。你是非常幸运的少数人之一,能够以自己喜欢的事谋生。大多数人没有这么幸运。你认为理所当然的观念“热爱你的工作”,其实是一个很现代的概念。通常的看法是,工作是一种让人很不开心的事,你为了拿工资才不得不去上班。 你工作的目的是为了攒下钱去干那些自己真正喜欢干的事,但是前提是你得等到65岁退休之后才行,而且还有不少条件。条件一,你的积蓄必须足够多;条件二,...

  • 我用 Redis 干掉了一摞简历

    如果你是一位后端工程师,面试时八成会被问到 Redis,特别是那些大型互联网公司,不仅要求面试者能简单使用 Redis,还要深入理解其底层实现原理,具备解决常见问题的能力。可以说,熟练使用 Redis 就是后端工程师的必备技能。 但我发现,在工作或面试时,大家还是会有这样那样的疑问,比如:如何用 Redis 实现分布式锁?Redis 怎样处理过期键?缓存雪崩、穿透、热点问题怎么解决?持久化、...

  • 【Python基础】如何编写简洁美观的Python代码

    作者 | ANIRUDDHA BHANDARI 编译 | VK 来源 | Analytics Vidhya 概述 Python风格教程将使你能够编写整洁漂亮的Python代码 在这个风格教程中学习不同的Python约定和Python编程的其他细微差别 介绍 你有没有遇到过一段写得很糟糕的Python代码?我知道你们很多人都会点头的。 编写代码是数据科学家或分析师角色的一部分。另一方面,编写漂...

  • JS设计模式之发布订阅者模式

    (本篇文章是我在早高峰上班地铁上刷到了一篇公众号发布的文章,感觉讲的非常好,特分享给大家。每天坚持学习,感谢公众号大佬的分享,公众号:nodejs全栈开发) 首先我们用一个示例来演示一下什么是观察者模式,有这样一个场景,在一个院子里,有一个小偷,和若干条狗,小偷只要一行动,狗就会叫,狗叫的动作是依赖小偷的,如果小偷不行动,狗是不会叫的,也就是说狗的叫的状态依赖小偷的行动,小偷的行动状态发生变...

  • 转载:PCB设计大神的105个经验总结

    http://murata.eetrend.com/node/1001487 在电子产品设计中,PCB布局布线是最重要的一步,PCB布局布线的好坏将直接影响电路的性能。现在,虽然有很多软件可以实现PCB自动布局布线,但是随着信号频率不断提升,很多时候,工程师需要了解有关PCB布局布线的最基本的原则和技巧,这样才可以让自己的设计完美无缺,《PCB(印制电路板)布局布线100问》涵盖了PCB布局...

  • 图解一致性哈希算法,全网(小区局域网)最通俗易懂

    好久不见小伙伴们,最近都快忙晕了,后端技术学堂差点停课,不过还是抽时间写了这篇文章带大家一起学习一致性哈希算法。 很多同学应该都知道什么是哈希函数,在后端面试和开发中会遇到「一致性哈希」,那么什么是一致性哈希呢?名字听起来很厉害的样子,其实原理并不复杂,这篇文章带你彻底搞懂一致性哈希! 进入主题前,先来一场紧张刺激的模拟面试吧。 模拟面试 面试官:看你简历上写参与了一个大型项目,用到了分布式...

  • 累积手续费超比特币2倍,说明以太坊依然被低估?解决拥堵问题再说

    在DeFi风声水起和ETH价格创出年度新高的关键时刻,以太坊网络交易费用也在持续上行半年之际迎来暴涨。Glassnode数据显示,5月份以来以太坊日均Gas费用就开始持续高企,7月27日更是一度突破90Gwei,较年初上涨将近20倍。 对于在以太坊网络上运行的一众DeFi项目及普通以太坊用户而言,日渐拥堵的网络以及愈发昂贵的交易费用,已经成为以太坊生态的“不可承受之重”。 01 拥堵的以太坊...

  • 架构师成神第一步!阿里内部超高质量的k8s+Jenkins笔记

    什么是k8s? Kubernetes是一个用于容器集群的自动化部署、扩容以及运维的开源平台。 k8s孕育的初衷是培育出一个组件及工具的生态,帮助大家减轻在公有云及私有云上运行应用的负担,换言之,使得大型分布式应用的构建和运维变得更加简单(当然,越简单的表面意味着越复杂的内部细节)。 什么是Jenkins? Jenkins是一个开源的、提供友好操作界面的持续集成(CI)工具,起源于Hudson...

华为云40多款云服务产品0元试用活动

免费套餐,马上领取!
CSDN

CSDN

中国开发者社区CSDN (Chinese Software Developer Network) 创立于1999年,致力为中国开发者提供知识传播、在线学习、职业发展等全生命周期服务。