字节效率工程 一面
面完之后觉得自己是真的菜,很多东西确实都知道,但是说不明白,有点自闭
更新 4.27约了二面,来复盘一下
算法题:
基础:js和别的语言有什么区别
1、合并有序数组,leetcode原题
2、看代码说输出顺序,就平常的题 async function async1() {async function async1() { console.log('async1 start');//2 await async2();// console.log('async1 end');//6 } async function async2() { console.log('async2');//3 } console.log('illegalscript start');//1 setTimeout(function() { console.log('setTimeout');//8 }, 0); async1(); new Promise(function(resolve) { console.log('promise1');//4 resolve(); }).then(function() { console.log('promise2');//7 }); console.log('illegalscript end');//5
3、菜🐔的代码看看就好,面试的时候没有写出来,想用递归没写出来,面试官说递归总要返回什么,我想不出来,换了个思路,但是数组部分也没写出来,后来补上的,面试官提醒我也没有写出来。。。。是真的有点菜没有想到那个点,写出来还给面试官发消息说写出来了,他说不用纠结,总之就是编程能力还是要重视的 const obj = { selector: { to: { toutiao: 'FE coder' } }, target: [1, 2, { name: 'byted' }] }; /* 运行代码 */ // get(obj, 'selector.to.toutiao', 'target[0]', 'target[2].name') /* 输出结果: ['FE coder', 1, 'byted'] */ function get(obj, ...args) { for (let i = 0; i < args.length; i++) { args[i] = args[i].replace(/\[/g, '.').replace(/\]/, '') } args = args.map(item => { return item.split('.') }) let res = [] for (let i = 0; i < args.length; i++) { res.push(help(args[i], obj)) } console.log(res, args) } function help(arr, obj) { for (let i = 0; i < arr.length; i++) { obj = obj[arr[i]] } return obj } // help(["selector","to","toutiao"],0,obj)
基础:js和别的语言有什么区别
1、变量提升,js是运行前编译,编译完立刻执行,(不是提前编译,编译结果也不能移植),编译阶段找到所有的声明,提前放在相关联的作用域,然后顺序执行语句,js采取词法作用域,this是动态作用域--作用域链,你不知道的js里面比较详细 function foo(){ console.log(a)//1 } function bar() { var a = 2 foo() } var a = 1 bar() 2、var重复声明,多次声明会被忽略 3、动态类型, 4、es5没有块级作用域 能想到的差不多就这样吧
var声明变量,一直声明是个什么情况
变量提升之后是放在哪里的
let const 和var的区别
1、var重复声明和变量提升,所以可以在未声明之前使用 2、let限定作用域(暂时性死区) {} 函数内部,禁止重复声明 3、常量声明,如果常量是引用类型,是可以改变其属性, 那怎么让引用类型的常量不可更改:Object.freeze()//相当于configurable为false,writable设置成false,但是对深层对象都没有用
闭包
//感觉这样看很清晰 function foo() { var a = 2 function bar() { //这里就已经产生了闭包,在bar中可以记住并访问foo的作用域 只是不能直接观察,所以return出去保存就可以看到 console.log(a) } // bar() return bar } var baz = foo() baz()//在定义自己的词法作用域以外的地方执行, 闭包是一个引用,对不属于自己作用域的一个保存, 对foo作用域的保持,就是闭包的引用,这个引用不在作用域定义的位置使用, 闭包就是一个把函数内部和外部连接起来的桥梁, 应用:回调函数,数据共享,缓存数据、柯里化(延迟执行),单例模式? 缺点:变量无法释放,造成内存泄漏 说到柯里化,顺便动手写一下,把接收多个参数的函数转换成多个接收一个参数的函数 function curry(func) { // 返回一个函数,接收新的参数 return function curried(...args) { console.log(args, func.length) //参数满足条件直接调用 if (args.length >= func.length) { return func.apply(this, args); } else { // 参数不满足条件 继续收集新的参数 return function (...newArgs) { console.log(newArgs) return curried.apply(this, args.concat(newArgs)); } } }; }
我说我后来学的时候有看书,js高级程序设计什么的,说说有什么难点,印象深刻的
promise 说说是干啥的
cookie 和local/sessionstroage有啥区别,
cookie是为http无状态服务的,由于http是无状态的,Cookie可以用来跟踪用户,由于每次请求浏览器都会自动携带Cookie,这样服务端就知道哪些请求是来自同一个用户了。 cookie是保存在客户端的一小段数据文本,以key-value的形式,整个值是字符串 cookie有很多属性可以进行操作: domain:表示cookie的域,限定cookie能被访问地址,后端显示设置主域名之后,子域就可以访问到cookie path:指定可以共享cookie的子目录,默认根目录 cookie的作用域与协议和端口无关 Expires/Max-Age:cookie的有效时间,默认Session,Expires指具体的过期时间,Max-Age指多少秒之后过期,Max-Age的优先级更高 HttpOnly:表示Cookie能否被js获取 Secure:只有***L 和 HTTPS 协议的时候才会被发送 SameSite:用于限制第三方 Cookie 的发送 cookie的安全隐患:csrf:利用浏览器自动带上cookie的特性 https://juejin.cn/post/6869573026980036616 xss: 通过可执行代码获取cookie https://juejin.cn/post/6867184627393265677 有源码的讲解 storage是本地储存,发送请求不会自动带上 cookie的大小一般4kb,storage一般5m cookie的期限可以设置,sessionstorage是会话期有效,localsotorage是永久保存,手动删除 共同点:都不可以跨域 看到一个题,storage容量有限怎么解决:内嵌同源页面使用?套娃? 说到cookie要说下session:一般配对使用,一个用户创建一个session,服务器把sessionid发给客户端存在cookie里,session存在服务端,每次收到cookie获取session查找服务端的session找到就放行,可以保存状态
cookie里面存的啥,有什么安全隐患,怎么解决,我说了https,这个是咋解决的,非对称加密是为了什么,为了交换对称加密的密钥,这里说的挺差的
https:TSL/SSL + HTTP,对传输的数据进行加密,对服务端进行身份验证 算了 感觉自己写的不好,推荐两个链接,连着看 阮一峰的https,https://blog.csdn.net/update7/article/details/111187245 基本上能搞明白
如果用token的话完整一套下来的流程是怎样的,又是怎么验证的
说到token,我一直都有一个疑问,服务端收到token是怎么验证有效性的,一篇文章:一篇文章告诉你JWT的实现原理 上面cookie和session需要各种保存在客户端和服务端来做状态管理,token就只保存在客户端,服务端只是验证收到的这个token是否有效,以解析token的时间换取session的储存空间 步骤:首先:JWT的组成 header-----加密算法,类型-----进行base64 payload-----标准声明(签发者-面向用户-接收方-过期时间等等)、公共声明(任意信息,因为可以被解密,不要放敏感信息)、私有声明(JWT提供者添加,可以被解密,不能存放敏感信息。)----通过base64 Signature----加密算法(header+'.'+payload+secret) 验证(我疑惑的点):解析JWT以后可以知道用户信息,比如能拿到uuid就能通过了? JWT防止篡改:Signature,再通过Signature的生成一次,对比就能知道,服务器的secret不能泄漏 为了防止csrf就不要放在cookie中, 还有个问题,如果token被截取到了又怎么办(有特殊场景可以把用户的user-agent(干扰码,每个客户端不一样,就不能解析别的token)和ip放进token进行验证?或者https?想不到别的了) Token - 服务端身份验证的流行方案:这篇有讲上面的问题
浏览器发起请求登陆
服务端验证身份,根据算法,将用户标识符打包生成 token, 并且返回给浏览器
浏览器发起请求获取用户资料,把刚刚拿到的 token 一起发送给服务器
服务器发现数据中有 token,验明正身
服务器返回该用户的用户资料
看简历用过vue,那你说说vue从实例化开始到看到页面一整个流程,这个理解错意思了----说了一堆初始化的工作
分阶段说比较好 1.初始化阶段:new Vue()到created之间的阶段 1.1 配置:始化配置项,合并配置,如果有全局配置合并得到根组件的配置上 1.2 initLifecycle:*组件关系属性的初始化,比如$parent root chidren这种* 1.3 initEvents:自定义事件 1.4 initRender:初始化插槽,获取this.$slots, this._c就是createElement方法,也就是h方法 1.5 callHook:beforecreate函数 1.6 initInjections:初始化inject选项,做响应式处理 1.7 initState:响应式原理的核心,处理 props methods computed,data watch 1.8 initProvide:处理provide 1.9 callHook:create函数 2.模版编译阶段:在created钩子函数与beforMount钩子函数之间 2.1 获取模版,将html编译成ast tree,将asttree解析成render函数,挂载到vm.$options.render 2.2 mountComponent: 2.2.1 判断vm.$options.render 2.2.2 beforeMount函数 2.2.3 updateComponent:调用了 vm_update(vm._render(),...), 2.2.4 new Watcher(),此时会传入updateComponent函数,并随后执行此函数,执行后会发生一些函数执行, Vue._render:执行由vue-loader生成的render函数或者自己写的render函数,最终返回一个由createComponent(非createPatchFunction内部的)产生的vnode. createComponent(非createPatchFunction内部):创建组件虚拟节点,此函数返回一个vnode,表示vue组件的vnode. vm._update:接收上面的vnode参数,这里面会触发VM.__patch__函数,这个函数里面最终返回的结果就是我们在html页面写的空的div,但是里面有了真实的内容,此时页面可以看到内容了, 2.2.5 触发mount钩子函数,这个mount钩子每个组件实例会在自己的insert hook中调用 3.挂载阶段:beforeMount钩子函数到mounted钩子函数之间 4.卸载阶段:调用vm.$destroy方法后,Vue.js的生命周期会进入卸载阶段。 这里面好多小点,比如computed的缓存原理,和watch的区别,响应式原理,provide/inject原理 computed的缓存原理:1、初始化computed的时候,遍历拿到里面的key,是函数直接赋值,不是函数获取getter, 2、把每个key都实例化一个watcher,传入一个对象{vm,getter,null,懒执行配置} 3、执行的时候,默认watcher.dirty = true,得到函数执行结果,赋值给watch.value,将watcher.dirty置为false,一次渲染中,只执行一次computed,后续访问不会执行,直到下一次更新下会执行,watcher.update之后才会把ditry置为true,不然每次执行都直接返回value 4、将key代理到vue实例上,支持this.computedKey访问
说了之后就问computed是怎么做到缓存的,双响绑定原理,感觉应该说完整一点,只说了核心部分就没头没尾的
一些细节就是我回答了什么他就顺着问
别的又记不得了,还停留在太菜了情绪中太菜了太菜了
反问我就问面试官对我们这种学的不久的人的建议,他说代码能力还是很重要的,还有基础,就不用急于去弄什么源码框架的,对于所有人来说都是,像刚刚你递归用的不好就不应该在面试过程中使用,这样就不太好