下是十道大厂一面的时候常见的面试题,如果全部理解并且弄透,在一面或者电话面的时候基本上能中1~2题。小伙伴可以先不急着看答案,先自己尝试着思考一下和自己实现一下,然后再看答案。
第 1 题:http的状态码中,499是什么?如何出现499,如何排查跟解决
499对应的是 “client has closed connection”,客户端请求等待链接已经关闭,这很有可能是因为服务器端处理的时间过长,客户端等得“不耐烦”了。还有一种原因是两次提交post过快就会出现499。 解决方法:
前端将timeout最大等待时间设置大一些nginx上配置proxy_ignore_client_abort on;提问解答与更多解析:github.com/airuikun/We…
第 2 题:如何遍历一个dom树
function traversal(node) { //对node的处理 if (node && node.nodeType === 1) { console.log(node.tagName); } var i = 0, childNodes = node.childNodes, item; for (; i < childNodes.length; i++) { item = childNodes[i]; if (item.nodeType === 1) { //递归先序遍历子节点 traversal(item); } } } 复制代码
提问解答与更多解析:github.com/airuikun/We…
第 3 题:new操作符都做了什么
四大步骤:
1、创建一个空对象,并且 this 变量引用该对象,// lat target = {};
2、继承了函数的原型。// target.proto = func.prototype;
3、属性和方法被加入到 this 引用的对象中。并执行了该函数func// func.call(target);
4、新创建的对象由 this 所引用,并且最后隐式的返回 this 。// 如果func.call(target)返回的res是个对象或者function 就返回它
function new(func) { lat target = {}; target.__proto__ = func.prototype; let res = func.call(target); if (typeof(res) == "object" || typeof(res) == "function") { return res; } return target; } 复制代码
提问解答与更多解析:github.com/airuikun/We…
第 4 题:手写代码,简单实现call
Function.prototype.call2 = function(context) { var context = context || window; //因为传进来的context有可能是null context.fn = this; var args = []; for (var i = 1; i < arguments.length; i++) { args.push("arguments[" + i + "]"); //不这么做的话 字符串的引号会被自动去掉 变成了变量 导致报错 } args = args.join(","); var result = eval("context.fn(" + args + ")"); //相当于执行了context.fn(arguments[1], arguments[2]); delete context.fn; return result; //因为有可能this函数会有返回值return } 复制代码
提问解答与更多解析:github.com/airuikun/We…
第 5 题:手写代码,简单实现apply
Function.prototype.apply2 = function(context, arr) { var context = context || window; //因为传进来的context有可能是null context.fn = this; var args = []; var params = arr || []; for (var i = 0; i < params.length; i++) { args.push("params[" + i + "]"); //不这么做的话 字符串的引号会被自动去掉 变成了变量 导致报错 } args = args.join(","); var result = eval("context.fn(" + args + ")"); //相当于执行了context.fn(arguments[1], arguments[2]); delete context.fn; return result; //因为有可能this函数会有返回值return } 复制代码
提问解答与更多解析:github.com/airuikun/We…
第 6 题:手写代码,简单实现bind
Function.prototype.bind2 = function(context) { var _this = this; var argsParent = Array.prototype.slice.call(arguments, 1); return function() { var args = argsParent.concat(Array.prototype.slice.call(arguments)); //转化成数组 _this.apply(context, args); }; } 复制代码
提问解答与更多解析:github.com/airuikun/We…
第 7 题:讲解一下HTTPS的工作原理
HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议不仅仅是一套加密传输的协议,更是一件经过艺术家精心设计的艺术品,TLS/SSL中使用了非对称加密,对称加密以及HASH算法。握手过程的简单描述如下:
提问解答与更多解析:github.com/airuikun/We…
第 8 题:讲解一下https对称加密和非对称加密。
对称加密: 发送方和接收方需要持有同一把密钥,发送消息和接收消息均使用该密钥。相对于非对称加密,对称加密具有更高的加解密速度,但双方都需要事先知道密钥,密钥在传输过程中可能会被窃取,因此安全性没有非对称加密高。
非对称加密: 接收方在发送消息前需要事先生成公钥和私钥,然后将公钥发送给发送方。发送放收到公钥后,将待发送数据用公钥加密,发送给接收方。接收到收到数据后,用私钥解密。 在这个过程中,公钥负责加密,私钥负责解密,数据在传输过程中即使被截获,攻击者由于没有私钥,因此也无法破解。 非对称加密算法的加解密速度低于对称加密算法,但是安全性更高。
提问解答与更多解析:github.com/airuikun/We…
第 9 题: 简单实现项目代码按需加载,例如import { Button } from 'antd',打包的时候只打包button
原理很简单,就是将
import { Select, Pagination, Button } from 'xxx-ui'; 复制代码
通过babel转化成
import Button from `xxx-ui/src/components/ui-base/Button/Button`; import Pagination from `xxx-ui/src/components/ui-base/Pagination/Pagination`; import Select from `xxx-ui/src/components/ui-base/Select/Select`; 复制代码
自定义拓展一个babel插件,代码如下:
visitor: { ImportDeclaration (path, { opts }) { const specifiers = path.node.specifiers; const source = path.node.source; // 判断传入的配置参数是否是数组形式 if (Array.isArray(opts)) { opts.forEach(opt => { assert(opt.libraryName, 'libraryName should be provided'); }); if (!opts.find(opt => opt.libraryName === source.value)) return; } else { assert(opts.libraryName, 'libraryName should be provided'); if (opts.libraryName !== source.value) return; } const opt = Array.isArray(opts) ? opts.find(opt => opt.libraryName === source.value) : opts; opt.camel2UnderlineComponentName = typeof opt.camel2UnderlineComponentName === 'undefined' ? false : opt.camel2UnderlineComponentName; opt.camel2DashComponentName = typeof opt.camel2DashComponentName === 'undefined' ? false : opt.camel2DashComponentName; if (!types.isImportDefaultSpecifier(specifiers[0]) && !types.isImportNamespaceSpecifier(specifiers[0])) { // 遍历specifiers生成转换后的ImportDeclaration节点数组 const declarations = specifiers.map((specifier) => { // 转换组件名称 const transformedSourceName = opt.camel2UnderlineComponentName ? camel2Underline(specifier.imported.name) : opt.camel2DashComponentName ? camel2Dash(specifier.imported.name) : specifier.imported.name; // 利用自定义的customSourceFunc生成绝对路径,然后创建新的ImportDeclaration节点 return types.ImportDeclaration([types.ImportDefaultSpecifier(specifier.local)], types.StringLiteral(opt.customSourceFunc(transformedSourceName))); }); // 将当前节点替换成新建的ImportDeclaration节点组 path.replaceWithMultiple(declarations); } } } 复制代码
提问解答与更多解析:github.com/airuikun/We…
第 10 题:简单手写实现promise
// 简易版本的promise // 第一步: 列出三大块 this.then resolve/reject fn(resolve,reject) // 第二步: this.then负责注册所有的函数 resolve/reject负责执行所有的函数 // 第三步: 在resolve/reject里面要加上setTimeout 防止还没进行then注册 就直接执行resolve了 // 第四步: resolve/reject里面要返回this 这样就可以链式调用了 // 第五步: 三个状态的管理 pending fulfilled rejected // *****promise的链式调用 在then里面return一个promise 这样才能then里面加上异步函数 // 加上了catch function PromiseM(fn) { var value = null; var callbacks = []; //加入状态 为了解决在Promise异步操作成功之后调用的then注册的回调不会执行的问题 var state = 'pending'; var _this = this; //注册所有的回调函数 this.then = function (fulfilled, rejected) { //如果想链式promise 那就要在这边return一个new Promise return new PromiseM(function (resolv, rejec) { //异常处理 try { if (state == 'pending') { callbacks.push(fulfilled); //实现链式调用 return; } if (state == 'fulfilled') { var data = fulfilled(value); //为了能让两个promise连接起来 resolv(data); return; } if (state == 'rejected') { var data = rejected(value); //为了能让两个promise连接起来 resolv(data); return; } } catch (e) { _this.catch(e); } }); } //执行所有的回调函数 function resolve(valueNew) { value = valueNew; state = 'fulfilled'; execute(); } //执行所有的回调函数 function reject(valueNew) { value = valueNew; state = 'rejected'; execute(); } function execute() { //加入延时机制 防止promise里面有同步函数 导致resolve先执行 then还没注册上函数 setTimeout(function () { callbacks.forEach(function (cb) { value = cb(value); }); }, 0); } this.catch = function (e) { console.log(JSON.stringify(e)); } //经典 实现异步回调 fn(resolve, reject); }
作者:第一名的小蝌蚪
链接:https://juejin.im/post/5ca9de22e51d452b5372ed90
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。