├── .gitignore ├── interview190108.md ├── interview190323.c ├── test190316_01.c ├── test190316_02.c ├── test190316_03.c └── test190316_04.c /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | .project 3 | .settings/org.eclipse.core.resources.prefs 4 | *.exe 5 | -------------------------------------------------------------------------------- /interview190108.md: -------------------------------------------------------------------------------- 1 | # ByteDance 2 | 2019年1月字节跳动广告系统后端开发工程师面试问题回忆 3 | 4 | * 形式:现场面试 单面 5 | * 时间:2019年1月8日下午2点半 6 | * 地点:北京市海淀区丹棱街1号互联网金融中心17层 7 | 8 | 面试官是一位很年轻的男的,做前端的,问的大部分都是Node.js相关的问题 9 | 10 | ## 1.回调函数、promise、generator/yield、async/await有哪些异同? 11 | 回调函数是js中的概念,一类特殊的函数,可以作为参数传给主函数,在主函数执行完之后调用该函数。前端的ajax请求就用到了回调函数。 12 | 13 | ``` 14 | //定义主函数,回调函数作为参数 15 | function A(callback) { 16 | callback(); 17 | console.log('我是主函数'); 18 | } 19 | 20 | //定义回调函数 21 | function B(){ 22 | setTimeout("console.log('我是回调函数')", 3000);//模仿耗时操作 23 | } 24 | 25 | //调用主函数,将函数B传进去 26 | A(B); 27 | 28 | //输出结果 29 | 我是主函数 30 | 我是回调函数 31 | ``` 32 | Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供的接口,使得控制异步操作更加容易。 33 | ``` 34 | var promise = new Promise(function(resolve, reject) { 35 | if (/* 异步操作成功 */){ 36 | resolve(value); 37 | } else { 38 | reject(error); 39 | } 40 | }); 41 | 42 | promise.then(function(value) { 43 | // success 44 | }, function(value) { 45 | // failure 46 | }); 47 | ``` 48 | Generator 函数是 ES6 提供的一种异步编程解决方案。一个Generator函数与普通function的区别就是函数名前面多了一个星号 * 但是执行时有很大不同,与yield命令配合,可以实现暂停执行的功能,意味着可以把异步操作写在yield表达式里面,等到调用next方法时再往后执行。这实际上等同于不需要写回调函数了。 49 | ``` 50 | function* loadUI() { 51 | showLoadingScreen(); 52 | yield loadUIDataAsynchronously(); 53 | hideLoadingScreen(); 54 | } 55 | var loader = loadUI(); 56 | // 加载UI 57 | loader.next() 58 | 59 | // 卸载UI 60 | loader.next() 61 | ``` 62 | ES2017 标准引入了 async 函数,使得异步操作变得更加方便。async 函数是什么?一句话,它就是 Generator 函数的语法糖,同时进行了一定的改进。 63 | ``` 64 | async function getStockPriceByName(name) { 65 | const symbol = await getStockSymbol(name); 66 | const stockPrice = await getStockPrice(symbol); 67 | return stockPrice; 68 | } 69 | ``` 70 | 总的来说async/await的实现最简洁,最符合语义,几乎没有语义不相关的代码。 71 | 72 | ## 2.Node.js单线程、非阻塞具体是怎么实现的? 73 | 事件驱动。有点像单个窗口,客户排队点餐,点完餐直接去座位上等着就行,而下一个客户可以接着点餐,而不用等前一个客户取完餐再点。而多线程相当于是开了多个窗口。I/O阻塞相当于是下一个客户必须等前一个客户取完餐之后才可以开始点餐。 74 | 75 | ## 3.你知道的HTTP状态码有哪些?分别表示什么含义? 76 | 常见的HTTP状态码: 77 | * 200 请求成功 78 | * 401 要求用户的身份认证 79 | * 404 请求的资源不存在 80 | * 500 内部服务器错误 81 | * 301 资源被永久转移到其它URL 82 | * 100 继续,客户端应继续其请求 83 | 84 | 分类: 85 | * 1xx 信息 86 | * 2xx 成功 87 | * 3xx 重定向 88 | * 4xx 客户端错误 89 | * 5xx 服务器错误 90 | 91 | ## 4.你对浏览器缓存了解多少? 92 | 简单来说,浏览器缓存就是把一个已经请求过的Web资源(如html页面,图片,js,数据等)拷贝一份副本储存在浏览器中。缓存会根据进来的请求保存输出内容的副本。当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。 93 | 94 | ## 5.tcp协议是如何建立和释放连接的? 95 | 三次握手建立连接。 96 | * 第一次握手:A给B打电话说,你可以听到我说话吗?(seq=x) 97 | * 第二次握手:B收到了A的信息,然后对A说: 我可以听得到你说话啊,你能听得到我说话吗?(ACK=x+1,seq=y) 98 | * 第三次握手:A收到了B的信息,然后说可以的,我要给你发信息啦!(ack=y+1) 99 | 100 | 四次挥手释放连接。 101 | * A:喂,我不说了。(FIN) 102 | * B:我知道了。等下,上一句还没说完。Balabala…..(ACK) 103 | * B:好了,说完了,我也不说了。(FIN) 104 | * A:我知道了。(ACK) 105 | 106 | A等待2MSL,保证B收到了消息,否则重说一次我知道了。 107 | 108 | ## 6.OSI模型和TCP/IP模型分别有哪几层,HTTP协议属于哪一层? 109 | OSI模型分为7层: 110 | * 物理层 111 | * 数据链路层 112 | * 网络层 113 | * 传输层 114 | * 会话层 115 | * 表示层 116 | * 应用层 117 | 118 | 实际应用中基本都是5层,没有表示层和会话层的,应该说它们和应用层合并了。我们需要关注的主要是应用层(HTTP协议)和传输层(TCP协议)。 119 | 120 | TCP/IP把分为4层: 121 | * 网络接口层 122 | * 网络层 IP 123 | * 运输层 TCP UDP 124 | * 应用层 HTTP、FTP 125 | 126 | ## 7.什么是RPC?它在7层模型中属于哪一层?与HTTP有什么区别? 127 | 是一种通过网络从远程计算机程序上请求服务,而不需要了解底层网络技术的协议。在OSI网络通信模型中,RPC跨越了传输层和应用层。RPC使得开发包括网络分布式多程序在内的应用程序更加容易。 128 | 129 | ## 8.进程间通讯的方式有哪些? 130 | * 管道(PIPE) 131 | * 消息排队 132 | * 旗语 133 | * 共用内存 134 | * 套接字(Socket) 135 | 136 | ## 9.子网掩码是如何工作的? 137 | 每一个IP地址分为网络标识和主机标识。IP地址与子网掩码做与运算得到网络标识。 138 | 139 | ## 10.koa怎么获取POST请求中的参数?写出具体代码。如果用Node.js原生方法怎么实现?服务端怎么区分body的不同格式? 140 | Node.js原生方法: 141 | ``` 142 | var http = require('http'); 143 | var querystring = require('querystring'); 144 | 145 | http.createServer(function(req, res){ 146 | // 定义了一个post变量,用于暂存请求体的信息 147 | var post = ''; 148 | 149 | // 通过req的data事件监听函数,每当接受到请求体的数据,就累加到post变量中 150 | req.on('data', function(chunk){ 151 | post += chunk; 152 | }); 153 | 154 | // 在end事件触发后,通过querystring.parse将post解析为真正的POST请求格式,然后向客户端返回。 155 | req.on('end', function(){ 156 | post = querystring.parse(post); 157 | res.end(util.inspect(post)); 158 | }); 159 | }).listen(3000); 160 | ``` 161 | 162 | koa方法: 163 | ``` 164 | const Koa = require('koa') 165 | const app = new Koa() 166 | 167 | // get请求 168 | app.use( async (ctx) => { 169 | ctx.body = { 170 | url: ctx.url, 171 | ctx_query: ctx.query, 172 | ctx_querystring: ctx.querystring 173 | } 174 | }) 175 | 176 | // post请求 177 | const bodyParser = require('koa-bodyparser') 178 | app.use(bodyParser()) 179 | app.use( async (ctx) => { 180 | ctx.body = ctx.request.body 181 | }) 182 | ``` 183 | 服务端通常是根据请求头(headers)中的 Content-Type 字段来获知请求中的消息主体是用何种方式编码(application/x-www-form-urlencoded,multipart/form-data,application/json,text/xml),再对body进行解析。 184 | -------------------------------------------------------------------------------- /interview190323.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwlpyl/ByteDance/58c89addc449a08ef8c66d012d298e7d4e55c05f/interview190323.c -------------------------------------------------------------------------------- /test190316_01.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwlpyl/ByteDance/58c89addc449a08ef8c66d012d298e7d4e55c05f/test190316_01.c -------------------------------------------------------------------------------- /test190316_02.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwlpyl/ByteDance/58c89addc449a08ef8c66d012d298e7d4e55c05f/test190316_02.c -------------------------------------------------------------------------------- /test190316_03.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwlpyl/ByteDance/58c89addc449a08ef8c66d012d298e7d4e55c05f/test190316_03.c -------------------------------------------------------------------------------- /test190316_04.c: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lwlpyl/ByteDance/58c89addc449a08ef8c66d012d298e7d4e55c05f/test190316_04.c --------------------------------------------------------------------------------