- 特性
- 单线程
- 异步 io
- 非阻塞 & 阻塞
是否去处理其他的任务
- 异步 & 非异步
是否要等待结果回来
- 事件驱动
- 主进程,执行栈,事件队列(事件循环:取一个放到执行栈中执行,异步的线程池中的线程处理,回调放到队列尾部),异步处理的线程池
- 跨平台
- libuv 库
类型判断 ladash
- typeof 基本数据类型
- isSymbol 独一无二
- isfunction
- instanceof 判断对象是某个实例
- constructor 它指向构造该对象的构造函数
- Object.prototype.toString.call(obj)
- console.log(Object.prototype.toString.call([])) //[object Array]
- objectToString(re) === '[object RegExp]'
- objectToString(d) === '[object Date]'
- 其他
- undefined === void 0
- NullOrUndefined == null
- isObject: typeof arg === 'object' && arg !== null;
- (objectToString(e) === '[object Error]' || e instanceof Error);
- Buffer.isBuffer
- isPrimitive 是否是基本类型
- arg === null || typeof arg === 'boolean' || typeof arg === 'number' || typeof arg === 'string' || typeof arg === 'symbol' || // ES6 symbol typeof arg === 'undefined';
- 不论var声明的变量处于当前作用域的第几行,都会提升到作用域的头部。
- 使用let命令声明变量之前,该变量都是不可用的
- let不允许在相同作用域内,重复声明同一个变量。
- 什么类型是传递引用, 什么类型是值传递? 如何将值类型的变量以引用的方式传递?
- 如何编写一个 json 对象的拷贝函数
- == 的 === 的区别的了解
- 引用类型是在没有引用之后, 通过 v8 的 GC 自动回收, 值类型如果是处于闭包的情况下,要等闭包没有引用才会被 GC 回收, 非闭包的情况下等待 v8的新生代 (new space) 切换的时候回收.
- v8 的 GC 有多了解
- 基础的内存释放
ES6 新特性 《ECMAScript 6 入门》
- 箭头函数 与 function 的区别
引用
const
Set
Map
symbol
- ... 的使用上, 如何实现一个数组的去重 (使用 Set 可以加分)
- AMD, CMD, CommonJS 三者的区别
- (浏览器异步)AMD 提前执行 requireJs
- (浏览器异步)CMD 按需加载执行 seaJs
// CMD define(function(require, exports, module) { var a = require('./a') a.doSomething() // 此处略去 100 行 var b = require('./b') // 依赖可以就近书写 b.doSomething() // ... }) // AMD 默认推荐的是 define(['./a', './b'], function(a, b) { // 依赖必须一开始就写好 a.doSomething() // 此处略去 100 行 b.doSomething() ... })
- (服务器同步)CommonJs
- node 中 require 的实现原理
- 解析路径原理:先缓存,再按文件,补齐扩展名(js, node, jsonx), 再目录(package.json, 补齐扩展名),再index补齐扩展名,再往上一级直到根目录,
- 执行原理,js用fs模块同步读取编译;node用c++扩展, dlopen()加载最后编译生成的文件;json用JSON.parse;其他扩展都按js方式来
- require 会有一个 cache, 有这个 cache 在, 即使你更新了 .js 文件, 在代码中再次require 还是会拿到之前的编译好缓存在 v8 内存 (code space) 中的的旧代码. 但是如果只是单纯的清除掉 require 中的 cache, 再次 require确实能拿到新的代码, 但是这时候很容易碰到各地维持旧的引用依旧跑的旧的代码的问题.如果还要继续推行这种热更新代码的话, 可能要推翻当前的架构,从头开始从新设计一下目前的框架.
- 其他方式:让更新的部分动态化,存库,缓存等服务
- vm模块创建新的上下文沙盒 (sandbox) 可以避免上下文被污染
- 为什么 Node.js 不给每一个.js文件以独立的上下文来避免作用域被污染?
- 性能
- 锁版本
- npm shrinkwrap:递归锁定依赖 注意: 如果 node_modules 下存在某个模块(如直接通过 npm install xxx 安装的)而 package.json 中没有,运行 npm shrinkwrap 则会报错。另外,npm shrinkwrap 只会生成 dependencies 的依赖,不会生成 devDependencies 的。
- 原理:状态机,事件队列
- 如何处理 Callback Hell
- Q, async, EventProxy
- promise
- co generate
- async await
- Promise 的实现
- js运行机制 & node 运行机制
setTimeout(function() { console.log(1) }, 0); new Promise(function executor(resolve) { console.log(2); for( var i=0; i<10000; i++ ) { i == 9999 && resolve(); } console.log(3); }).then(function() { console.log(4); }); console.log(5); // 2 3 5 4 1
- Node.js 中 Eventemitter 的 emit 是同步的.(确保顺序,避免竞争,逻辑错误...)
- TCP 的复杂状态机
- once
- 如何实现一个异步的 reduce(接收一个函数作为累加器)
- 事件循环, Timers 以及 nextTick 的关系
- nextTick, setTimeout 以及 setImmediate
- process.nextTick 在执行站尾部,效率最高,消费资源小,但会阻塞CPU的后续调用;
- setTimeout 在事件队列尾部,精确度不高,可能有延迟执行的情况发生,且因为动用了红黑树,所以消耗资源大;
- setImmediate 在事件队列尾部,消耗的资源小,也不会造成阻塞,但效率也是最低的。
- setTimeout(fn, 1) 与 setImmediate 谁先谁后执行都有可能,主要看到下次tick是否已经过了1ms,到了则先执行,否则后执行
```text
┌───────────────────────┐
┌─>│ timers │<————— 执行 setTimeout()、setInterval() 的回调
│ └──────────┬────────────┘
| |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调
│ ┌──────────┴────────────┐
│ │ I/O callbacks │<————— 执行几乎所有的回调,除了 close callbacks 以及 timers 调度的回调和 setImmediate() 调度的回调
│ └──────────┬────────────┘
| |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调
│ ┌──────────┴────────────┐
│ │ idle, prepare │<————— 内部调用,可忽略
│ └──────────┬────────────┘
| |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调
| | ┌───────────────┐
│ ┌──────────┴────────────┐ │ incoming: │ - (retrieve new I/O events; node will block here when appropriate)
│ │ poll │<─────┤ connections, │
│ └──────────┬────────────┘ │ data, etc. │
│ | └───────────────┘
| |
| |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调
| ┌──────────┴────────────┐
│ │ check │<————— setImmediate() 的回调将会在这个阶段执行
│ └──────────┬────────────┘
| |<-- 执行所有 Next Tick Queue 以及 MicroTask Queue 的回调
│ ┌──────────┴────────────┐
└──┤ close callbacks │<————— socket.on('close', ...)
└───────────────────────┘
```
- 在 IPC 通道建立之前, 父进程与子进程是怎么通信的? 如果没有通信, 那 IPC 是怎么建立的?
- 会问什么情况下需要 IPC, 以及使用 IPC 处理过什么业务场景等.
守护进程 实现守护进程
- 1-属性不可再分 2-全部依赖唯一主键 3-消除依赖 4-消除多值依赖
- 减少数据冗余(这是最主要的好处,其他好处都是由此而附带的)
- 满足高等级的范式的先决条件是满足低等级范式
- 查询时要连接多个表,增加了查询的复杂度, 降低了数据库查询性能
- 存储不值钱,具体看场景,二三范式也够
- 你需要全文索引吗?
- 你经常使用什么样的查询模式?
- 你的数据有多大?
- 索引是用空间换时间的一种优化策略
- (产生脏数据)数据一致性:锁,事务
- 引擎
- 维护工具更棒
- 索引优化
- 组合索引,查询顺序
- 大数据索引更新
- like 导致的索引失效
- 磁盘空间 维护索引耗时
- 数据一致性问题
- Monogdb 连接问题(超时/断开等)有可能是什么问题导致的?
- json 格式与 js 更友好
- 数据是存储在硬盘上的,只不过需要经常读取的数据会被加载到内存中,将数据存储在物理内存中,从而达到高速读写
- redis 单核 100k 以下更快,memcahce 多核,大数据量更快,但性能很难是瓶颈
- 持久性,redis 定期写入磁盘,memcache 重启后数据会丢失
- 内存使用率上,简单key-value memcache 会更高,其他 redis 更好
- redis 支持主从,集群,更高可用
- 强制缓存
- expired
- cache-control
- Pragma
- 对比缓存
- last-modifred (if modified since)
- etag (If-None-Match) (优先级高于Last-Modified / If-Modified-Since)
- 物理层 宽带
- 链路层 交换机
- 网络层 ip
- 传输层 tcp
- 会话层
- 表示层
- 应用层
- CSP 策略
- CSRF token
- 同源检查: Origin Header & Referer Header
- wife
- Standard JavaScript errors 标准 JavaScript 错误 由错误代码触发
- System errors 系统错误 由操作系统触发
- User-specified errors 用户自定义错误 通过 throw 抛出
- Assertion errors 断言错误 由 assert 模块触发
- 怎么处理未预料的出错? 用 try/catch , domains 还是其它什么?
- 为什么要在 cb 的第一参数传 error? 为什么有的 cb 第一个参数不是 error, 例如 http.createServer?
- 对比 PHP
- 性能
- 社区
- 文档
- 成熟度
- 生态
创建一个具有指定原型且可选择性地包含指定属性的对象。(将对象继承到原型上)
var newObj = Object.create(null, {
size: {
value: "large",
enumerable: true
},
shape: {
value: "round",
enumerable: true
}
});
document.write(newObj.size + "<br/>");
document.write(newObj.shape + "<br/>");
document.write(Object.getPrototypeOf(newObj));
// Output:
// large
// round
// null
Return whitelisted properties of an object.
var obj = {
name: 'tobi',
last: 'holowaychuk',
email: '[email protected]',
_id: '12345'
};
var user = only(obj, 'name last email');
// output
{
name: 'tobi',
last: 'holowaychuk',
email: '[email protected]'
}
HTTP status utility for node.
Check if a body is JSON
- use(fn) 用一个 middleware(Array) 队列 维护
- fn(req, res, next) next() 匹配路由,中间件等 循环调用 middleware 队列
koa 是 express 原班人马实现的,比 express 更轻量,只是在 http 模块 create Server 上封装了一层。中间件的处理基于 koa-compose,使得有了洋葱式的流程控制,中间件会传入一个叫
ctx
的上下文,这个上下文包含的 http 回调 handle 里的 请求[req] 和 相应[res], 以及框架自身扩展的一些属性方法,本身不依赖任何中间件,靠生态的中间件自由开发。
- 多进程管理特性
- 渐进式开发
- load 挂载 controller,model 等到 app 实例上
- egg 运行原理
运行原理主要是 egg-cluster,多进程模型:master, agent, worker。master 负责管理agent,worker进程,包括启动,重启,退出,消息通信等。master 首先child_process模式 fork agent进程,初始化好了通知master进程,再fork worker进程,完了再cfork worker进程,初始化好了就开启服务
- egg-core
egg 很重要的特性就是基于一定的目录约定,将不同代码放在不同目录管理,像controller,service等,对企业级的应用更友好。而egg-core作为egg框架的核心,里面的loader则是将controller,model 等挂载到 app,context上下文,core上实现的了具体的各个加载单元的加载逻辑。