当然Nodejs也有一些缺点:
它是一个Javascript运行环境
依赖于Chrome V8引擎进行代码解释
事件驱动
非阻塞I/O
轻量、可伸缩,适于实时数据交互应用
单进程,单线程 (一个应用程序对应一个进程, 一个进程下面会有多个线程, 每个线程用于处理任务..)
后端路由, 其实就是提前规定好的一串url路径, 当前端访问不同的路径, 后端做出不同的处理
http模块 | http.Agent 类 | http.ClientRequest 类 | http.Server 类 | http.ServerResponse 类 | |
events模块 | 异步 VS 同步 | EventEmitter | |||
module模块 | commonjs模块化规范,一个module就是一个文件 | ||||
fs模块 | fs.ReadStream类 | fs.FSWatcher类 | fs.WriteStream类 | fs.Stats()类 | fs的Promise API |
process模块 | process.stdin process.stdout | process.on | process.env | process.nextTick 方法将 callback 添加到下一个时间点的队列(事件循环) | process.mainModule |
querystring模块 | querystring.parse | querystring.stringify | |||
path模块 | |||||
debuger模块 | run - 运行脚本(在调试器启动时自动运行) | restart - 重启脚本 | scripts - 列出所有已加载的脚本 |
你可以有如下几个方法:
解析:这个问题有很多种答案,取决你使用的场景,例如ES6, ES7,或者一些控制流库。
方向代理指的是以代理服务器来接收Internet上的连接请求,然后将请求转发给内部网络上的服务器, 并且将服务器返回的结果发送给客户端。
同步操作, 当代码运行到同步操作的代码时, 所在线程等待结果返回, 而异步操作, 则是不会耽误代码继续执行, 当异步操作成功,
一般使用回调函数来处理异步成功的动作(常用在ajax/定时器/计时器等)
一、HTTP模块
作用:处理网络客户端的请求
二、URL模块
作用:处理客户端请求过来的url
三、Query Strings模块
作用:处理客户端通过get/post请求传递过来的参数
四、File System模块
作用:在服务端操作文件,可能是需要将浏览器上传的图片保存到服务器,也可能是需要将服务器的资源读取之后返回给浏览器。
五、Path模块
作用:操作文件的路径,为文件操作服务
常用的几个函数: path.join(第一个路径,第二个路径) : 拼接路径
六、Global模块
作用:全局共享的,不需要导入模块即可以使用,常用的属性:
__dirname : 文件所在的文件夹路径
__filename : 文件所在的路径
require() : 导入需要的模块
module : 自定义模块时用到
exports : 自定义模块时用到
Libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个事件循环, 以异步的方式将任务的执行结果返回给V8引擎。可以简单用下面这张图来表示。
通过NPM,你可以安装和管理项目的依赖,并且能够指明依赖项的具体版本号。 对于Node应用开发而言,你可以通过package.json文件来管理项目信息,配置脚本, 以及指明项目依赖的具体版本。
npm init
npm search
npm install
npm remove
npm uninstall
npm config set
NodeJS 通常使用回调模式,如果在执行期间发生错误,会把错误作为回调的第一个参数传递到回调函数中。
客户端连接到Web服务器 2、发送HTTP请求
释放连接TCP连接
客户端浏览器解析html内容
服务器接受请求并返回HTTP响应
util是一个Node.js核心模块,提供常用函数的集合,用于弥补核心js的功能过于精简的不足。
util.inherits实现对象间原型继承的函数。js面向对象特性是基于原型的。
util.inspect将任意对象转换为字符串的方法。
util.isArray(), util.isRegExp(), util.isDate(), util.isError(), util.format(), util.debug()等
node全面支持各种网络服务器和客户端,包括tcp, http/https, tcp, udp, dns, tls/ssl等.
主要实现以下几个步骤即可: 1) openssl生成公钥私钥 2) 服务器或客户端使用https替代http 3) 服务器或客户端加载公钥私钥证书
思路是加载http模块,创建服务器,监听端口
var http = require('http'); // 加载http模块
http.createServer(function(req, res) {
res.writeHead(200, {'Content-Type': 'text/html'}); // 200代表状态成功, 文档类型是给浏览器识别用的
res.write('<meta charset="UTF-8"> <h1>我是标题啊!</h1> <font color="red">这么原生,初级的服务器</font>'); // 返回给客户端的html数据
res.end(); // 结束输出流
}).listen(3000); // 绑定3ooo, 查看效果请访问 http://localhost:3000
fs模块主要由下面几部分组成: 1) POSIX文件Wrapper,对应于操作系统的原生文件操作 2) 文件流 fs.createReadStream和fs.createWriteStream 3) 同步文件读写,fs.readFileSync和fs.writeFileSync 4) 异步文件读写, fs.readFile和fs.writeFile
总体来说有四种: 1) POSIX式低层读写 2) 流式读写 3) 同步文件读写 4) 异步文件读写
参考答案: 主要有两种方式,第一种是利用node内置的require('data.json')机制,直接得到js对象; 第二种是读入文件入内容,然后用JSON.parse(content)转换成js对象.二者的区别是require机制情况下,如果多个模块都加载了同一个json文件,那么其中一个改变了js对象,其它跟着改变,这是由node模块的缓存机制造成的,只有一个js模块对象; 第二种方式则可以随意改变加载后的js变量,而且各模块互不影响,因为他们都是独立的,是多个js对象.
二者主要用来监听文件变动.fs.watch利用操作系统原生机制来监听,可能不适用网络文件系统; fs.watchFile则是定期检查文件状态变更,适用于网络文件系统,但是相比fs.watch有些慢,因为不是实时机制.
首先封装函数, 用于读取目标路径下所有文件/文件夹的名字
开始遍历每个相对路径, 判断是文件夹, 就递归调用次函数
如果是文件, 则删除此文件
当上面循环结束以后, 则删除当前所在的文件夹即可
process, console, Buffer和exports
process.stdin, process.stdout, process.stderr, process.on, process.env, process.argv, process.arch, process.platform, process.exit
参考答案: console.log/console.info, console.error/console.warning, console.time/console.timeEnd, console.trace, console.table
setTimeout/clearTimeout, setInterval/clearInterval, setImmediate/clearImmediate, process.nextTick
event loop其实就是一个事件队列,先加入先执行,执行完一次队列,再次循环遍历看有没有新事件加入队列.执行中的叫IO events, setImmediate是在当前队列立即执行,setTimout/setInterval是把执行定时到下一个队列,process.nextTick是在当前执行完,下次遍历前执行.所以总体顺序是: IO events >> setImmediate >> setTimeout/setInterval >> process.nextTick
Buffer是用来处理二进制数据的,比如图片,mp3,数据库文件等.Buffer支持各种编码解码,二进制字符串互转.
Buffer对象是node处理二进制数据的一个接口。它是node原生提供的全局对象,可以直接使用,不需要require('Buffer')。
实例化
Buffer from(array)
Buffer alloc(size)
功能方法
Buffer isEncodeing() 判断是否支持编码
Buffer isBuffer() 判断是否为Buffer
Buffer byteLength() 返回指定编码的字节长度,默认为utf8
Buffer concat() 将一组Buffer对象合并为一个Buffer对象
实例方法
write() 向Buffer对象中写入内容
slice() 截取新的Buffer对象
toString() 把Buffer对象转成字符串
toJson() 把Buffer对象转成json形式的字符串
EventEmitter是node中一个实现观察者模式的类,主要功能是监听和发射消息,用于处理多模块交互问题.
主要分三步:定义一个子类,调用构造函数,继承EventEmitter
代码演示
var util = require('util');
var EventEmitter = require('events').EventEmitter;
function MyEmitter() {
EventEmitter.call(this);
} // 构造函数
util.inherits(MyEmitter, EventEmitter); // 继承
var em = new MyEmitter();
em.on('hello', function(data) {
console.log('收到事件hello的数据:', data);
}); // 接收事件,并打印到控制台
em.emit('hello', 'EventEmitter传递消息真方便!');
1) 模块间传递消息 2) 回调函数内外传递消息 3) 处理流数据,因为流是在EventEmitter基础上实现的. 4) 观察者模式发射触发机制相关应用
监听error事件即可.如果有多个EventEmitter,也可以用domain来统一处理错误事件.
代码演示
var domain = require('domain');
var myDomain = domain.create();
myDomain.on('error', function(err){
console.log('domain接收到的错误事件:', err);
}); // 接收事件并打印
myDomain.run(function(){
var emitter1 = new MyEmitter();
emitter1.emit('error', '错误事件来自emitter1');
emitter2 = new MyEmitter();
emitter2.emit('error', '错误事件来自emitter2');
});
newListener可以用来做事件机制的反射,特殊应用,事件管理等.当任何on事件添加到EventEmitter时,就会触发newListener事件,基于这种模式,我们可以做很多自定义处理.
代码演示
var emitter3 = new MyEmitter();
emitter3.on('newListener', function(name, listener) {
console.log("新事件的名字:", name);
console.log("新事件的代码:", listener);
setTimeout(function(){ console.log("我是自定义延时处理机制"); }, 1000);
});
emitter3.on('hello', function(){
console.log('hello node');
});
stream是基于事件EventEmitter的数据管理模式.由各种不同的抽象接口组成,主要包括可写,可读,可读写,可转换等几种类型.
非阻塞式数据处理提升效率,片断处理节省内存,管道处理方便可扩展等.
文件,网络,数据转换,音频视频等.
监听error事件,方法同EventEmitter.
参考答案: Readable为可被读流,在作为输入数据源时使用;Writable为可被写流,在作为输出源时使用;Duplex为可读写流,它作为输出源接受被写入,同时又作为输入源被后面的流读出.Transform机制和Duplex一样,都是双向流,区别时Transfrom只需要实现一个函数_transfrom(chunk, encoding, callback);而Duplex需要分别实现_read(size)函数和_write(chunk, encoding, callback)函数.
三步走:1)构造函数call Writable 2) 继承Writable 3) 实现_write(chunk, encoding, callback)函数
代码演示
var Writable = require('stream').Writable;
var util = require('util');
function MyWritable(options) {
Writable.call(this, options);
} // 构造函数
util.inherits(MyWritable, Writable); // 继承自Writable
MyWritable.prototype._write = function(chunk, encoding, callback) {
console.log("被写入的数据是:", chunk.toString()); // 此处可对写入的数据进行处理
callback();
};
process.stdin.pipe(new MyWritable()); // stdin作为输入源,MyWritable作为输出源
node是异步非阻塞的,这对高并发非常有效.可是我们还有其它一些常用需求,比如和操作系统shell命令交互,调用可执行文件,创建子进程进行阻塞式访问或高CPU计算等,child-process就是为满足这些需求而生的.child-process顾名思义,就是把node阻塞的工作交给子进程去做.
exec可以用操作系统原生的方式执行各种命令,如管道 cat ab.txt | grep hello; execFile是执行一个文件; spawn是流式和操作系统进行交互; fork是两个node程序(javascript)之间时行交互.
那就用spawn吧.
代码演示
var cp = require('child_process');
var child = cp.spawn('echo', ['你好', "钩子"]); // 执行命令
child.stdout.pipe(process.stdout); // child.stdout是输入流,process.stdout是输出流
// 这句的意思是将子进程的输出作为当前程序的输入流,然后重定向到当前程序的标准输出,即控制台
用fork嘛,上面讲过了.原理是子程序用process.on, process.send,父程序里用child.on,child.send进行交互.
代码演示
1) fork-parent.js
var cp = require('child_process');
var child = cp.fork('./fork-child.js');
child.on('message', function(msg){
console.log('老爸从儿子接受到数据:', msg);
});
child.send('我是你爸爸,送关怀来了!');
2) fork-child.js
process.on('message', function(msg){
console.log("儿子从老爸接收到的数据:", msg);
process.send("我不要关怀,我要银民币!");
});
1) 在myCommand.js文件头部加入 #!/usr/bin/env node 2) chmod命令把js文件改为可执行即可 3) 进入文件目录,命令行输入myComand就是相当于node myComand.js了
概念都是一样的,输入,输出,错误,都是流.区别是在父程序眼里,子程序的stdout是输入流,stdin是输出流.
node是单线程的,异步是通过一次次的循环事件队列来实现的.同步则是说阻塞式的IO,这在高并发环境会是一个很大的性能问题,所以同步一般只在基础框架的启动时使用,用来加载配置文件,初始化程序什么的.
1) 多层嵌套回调 2) 为每一个回调写单独的函数,函数里边再回调 3) 用第三方框架比方async, q, promise等
多种方式 1) sudo 2) apache/nginx代理 3) 用操作系统的firewall iptables进行端口重定向
参考答案: 1) runit 2) forever 3) nohup npm start &
一个CPU运行一个node实例
用--max-old-space-size 和 --max-new-space-size 来设置 v8 使用内存的上限
1) node --prof 查看哪些函数调用次数多 2) memwatch和heapdump获得内存快照进行对比,查找内存溢出
1) try-catch-finally 2) EventEmitter/Stream error事件处理 3) domain统一控制 4) jshint静态检查 5) jasmine/mocha进行单元测试
node --debug app.js 和node-inspector
Stub是用于模拟一个组件或模块的函数或程序。在测试用例中, 简单的说,你可以用Stub去模拟一个方法,从而避免调用真实的方法, 使用Stub你还可以返回虚构的结果。你可以配合断言使用Stub。
举个例子,在一个读取文件的场景中,当你不想读取一个真正的文件时:
var fs = require('fs');
var readFileStub = sinon.stub(fs, 'readFile', function (path, cb) {
return cb(null, 'filecontent');
});
expect(readFileStub).to.be.called;
readFileStub.
在单元测试中:Stub是完全模拟一个外部依赖,而Mock常用来判断测试通过还是失败。
express.Router路由组件,app.get路由定向,app.configure配置,app.set设定参数,app.use使用中间件
参考答案: /users/:name使用req.params.name来获取; req.body.username则是获得表单传入参数username; express路由支持常用通配符 ?, +, *, and ()
res.download() 弹出文件下载
res.end() 结束response
res.json() 返回json
res.jsonp() 返回jsonp
res.redirect() 重定向请求
res.render() 渲染模板
res.send() 返回多种形式数据
res.sendFile 返回文件
res.sendStatus() 返回状态
类似传统数据库,索引和分区.
set/get, hset/hget, publish/subscribe, expire
参考答案:
var redis = require("redis"),
client = redis.createClient();
client.set("foo_rand000000000000", "some fantastic value");
client.get("foo_rand000000000000", function (err, reply) {
console.log(reply.toString());
});
client.end();
二者都是代理服务器,功能类似.apache应用简单,相当广泛.nginx在分布式,静态转发方面比较有优势.
近年来,从事JavaScript的程序员越来越多,JavaScript的曝光率也越来越高,如果你想转行试试JavaScript,不妨收下这份面试题及答案,没准用得上。当然,如果针对这些问题,你有更棒的答案,欢迎移步至评论区。
面试的公司分别是:阿里、网易、滴滴、今日头条、有赞、挖财、沪江、饿了么、携程、喜马拉雅、兑吧、微医、寺库、宝宝树、海康威视、蘑菇街、酷家乐、百分点和海风教育。以下是面试题汇总
web前端常见的面试题:包括:HTML 常见题目、CSS类的题目、JavaScript类的题目、面试官爱问的问题。原来公司工作流程是怎么样的,如何与其他人协作的?如何夸部门合作的?你遇到过比较难的技术问题是?你是如何解决的?
毕业之后就在一直合肥小公司工作,没有老司机、没有技术氛围,在技术的道路上我只能独自摸索。老板也只会画饼充饥,前途一片迷茫看不到任何希望。于是乎,我果断辞职,在新年开工之际来到杭州,这里的互联网公司应该是合肥的几十倍吧。。。。
javascript的typeof返回哪些数据类型;例举3种强制类型转换和2种隐式类型转换?split() join() 的区别; 数组方法pop() push() unshift() shift();IE和标准下有哪些兼容性的写法
解析 URL Params 为对象;模板引擎实现;转化为驼峰命名;查找字符串中出现最多的字符和个数;字符串查找请使用最基本的遍历来实现判断字符串 a 是否被包含在字符串 b 中
虚拟 DOM (VDOM)是真实 DOM 在内存中的表示。UI 的表示形式保存在内存中,并与实际的 DOM 同步。这是一个发生在渲染函数被调用和元素在屏幕上显示之间的步骤,整个过程被称为调和。函数组件和类组件当然是有区别的
使用渐进式框架的代价很小,从而使现有项目(使用其他技术构建的项目)更容易采用并迁移到新框架。 Vue.js 是一个渐进式框架,因为你可以逐步将其引入现有应用,而不必从头开始重写整个程序。
AJAX 即 Asynchronous Javascript And XML(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术。AJAX 是一种用于创建快速动态网页的技术。它可以令开发者只向服务器获取数据(而不是图片,HTML文档等资源)
本文分享 12 道 vue 高频原理面试题,覆盖了 vue 核心实现原理,其实一个框架的实现原理一篇文章是不可能说完的,希望通过这 12 道问题,让读者对自己的 Vue 掌握程度有一定的认识(B 数),从而弥补自己的不足,更好的掌握 Vue
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!