目录
·垂直居中
· 左侧固定、右侧自适应
· 如何判断一个值是数组
· bigint 最大安全整数
· 如何判断某个字符串以 abc 开头
·进程和线程的区别
·tcp 与 udp
·跨域问题的几种解决方案
·option 预请求
·跨域的同时携带 cookie
·用 css 画一个扇形
·多行超出显示省略号
·实现多个页面之间通信
·cookie 和 localstorge 的区别
·cookie、sessionStorage、localStorage 区别
·call apply bind 的区别
·实现一个 bind(编程)
·最大连续子数组 (编程)
·老虎吃羊的问题
·vue 中的 nextTick
·宏任务和微任务
·正则中的 i 具体做了什么事
·JavaScript的三种类型检测typeof,instanceof,toString比较
·script 标签中 async 和 defer 的区别
·position 有哪几种?分别说一下对应的效果和用法
·css 选择器优先级(由高到低)
·js原型链
· JavaScript创建对象的方式
·使用JS实现一个new方法
·MVVM 结构
·MVVM 和 MVC 的区别
· Vue 的生命周期
· Vue生命周期什么阶段才能调用DOM?什么阶段能发起请求?
·Vue 的组件通信(三种)
·讲一下 TCP 的三次握手和四次挥手 (HTTP 传输过程)
· promise 有哪几种状态
·promise是什么与使用方法
·手写promise
· 手写 Promise.All()
· 编程题(最长公共前缀)
·垂直居中
<div class="parent"><div class="children"></div></div>
1. flex布局
.parent{display: flex;align-items: center;justify-content: center;}
2. 子元素是单行文本
设置父元素的text-align
和line-height = height
.parent{height: 100px;line-height: 100px;text-align: center;}
3. absolute
+transform
.parent {position: relative;}.children{position: absolute;left: -50%;top: -50%;transform: translate(-50%, -50%);}
4. grid
布局(将容器划分为行和列,产生单元格,然后指定项目所在的单元格,可以看作是二维布局)
.parent{display: grid;}.children {justify-self: center; align-self: center;}
5. 绝对定位和margin:auto
.children{position: absolute;left: 0;top: 0;right: 0;bottom: 0;margin: auto;}.parent{position: relative;}
· 左侧固定、右侧自适应
flex-basis: 100px; flex-shrink: 0; / flex-grow: 1;grid-template-columns: 100 px 1fr;· 如何判断一个值是数组
Array.isArraytoStringinstanceof(有局限性)· bigint 最大安全整数
-2^63 到 2^63-1,存储大小为 8 个字节
· 如何判断某个字符串以 abc 开头
正则表达式String xxx= "abcxxxxxx",if(xxx.startsWith(abc))
2. .slice:切片操作
3. indexOf / startsWith
·进程和线程的区别
定义不一样,进程是执行中的一段程序,而一个进程中执行中的每个任务即为一个线程一个线程只可以属于一个进程,但一个进程能包含多个线程线程无地址空间,它包括在进程的地址空间里线程的开销或代价比进程的小·tcp 与 udp
tcp 是一种面向有连接的传输层协议,能够对自己提供的连接实施控制。适用于要求可靠传输的应用,例如文件传输。面向字节流,传输慢
udp是一种面向无连接的传输层协议,不会对自己提供的连接实施控制。适用于实时应用,例如:IP电话、视频会议、直播等。以报文的方式传输,效率高
HTTP 请求的幂等概念的理解以及常见请求的幂等性常见请求的幂等性(HTTP幂等方法,是指无论调用这个url多少次,都不会有不同的结果的HTTP方法,也就是不管你调用1次还是调用100次,结果都是一样的)
HTTP请求方法
HTTP请求方法的幂等性(如果一个方法重复执行多次,产生的效果是一样的,那么这个方法就是幂等的)
·跨域问题的几种解决方案
cors技术(服务器在返回响应报文的时候,在响应头中设置一个允许的header)//服务器设置CORS,允许浏览器跨域res.setHeader('Access-Control-Allow-Origin', '*')
2-express使用中间件cors(自动给每一个res设置默认请求头)
2. 原生jsonp(通过动态创建script标签,通过script标签的src,向一个不同源的接口发送一个get请求)
3. jQuery中的jsonp
dataType:'jsonp'
4. 谷歌浏览器设置跨域
5. 区别
CORS服务器返回响应头,前端无需任何处理简单快捷,支持所有请求方式JSONP浏览器:自定义响应回调函数,使用script标签的src请求利用浏览器的src属性没有跨域这一限制特点服务器:接收callback参数,返回函数调用处理复杂,并且只支持get请求原因:get请求参数直接在url后面拼接,而post请求参数是放在请求体中
·option 预请求
options 请求就是预检请求,可用于检测服务器允许的 http 方法。当发起跨域请求时,由于安全原因,触发一定条件时浏览器会在正式请求之前自动先发起 OPTIONS 请求,即 CORS 预检请求,服务器若接受该跨域请求,浏览器才继续发起正式请求
简单请求:请求方式为GET、HEAD、POST时的请求复杂请求:PUT、DELETE、CONNECT、OPTIONS、TRACE、PATCH
·跨域的同时携带 cookie
前端请求时在request
对象中配置"withCredentials": true
;服务端在response
的header
中配置"Access-Control-Allow-Origin","http://xxx:${port}"
;服务端在response
的header
中配置"Access-Control-Allow-Credentials", "true"
·用 css 画一个扇形
<!DOCTYPE html><html lang="en"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>扇形</title><style>#box {border: 200px solid transparent;border-top-color: thistle;width: 0;border-radius: 200px;}</style></head><body><div id="box"></div></body></html>
·多行超出显示省略号
overflow: hidden;text-overflow: ellipsis;white-space: nowrap;·实现多个页面之间通信
localstorage(推荐)// pageA.html<body><h1>pageA</h1></body><script>window.addEventListener("storage", (e) => {console.info("localStorage发生变化:", e)})</script>
// pageB.html<body><h1>pageB</h1><button id="btnB">添加数据到localStorage</button></body><script>let btnB = document.getElementById("btnB");let num = 0;btnB.addEventListener("click", () => {localStorage.setItem("num", num++)})</script>
2. websocket协议
3. SharedWorker
4. 使用cookie + setInterval
·cookie 和 localstorge 的区别
1. 容量
cookie容量在4K左右,且有条数限制。localStorage的容量有5M。
2. 是否向服务器发送数据
cookie会向服务器发送数据,localStorage不会往服务器发送数据。
3. 过期时间
cookie的有过期时间,在没有设置过期时间,关闭浏览器就消失,默认过期时间是一次会话。localStorage没有过期时间。
4. 路径限制
cookie有路径的限制。localStorage没有路径的限制。
5. 存储类型
cookie存储的是字符串,字符串,字符串。localStorage存储的是对象,对象,对象。
·cookie、sessionStorage、localStorage 区别
cookie、sessionStorage、localStorage都是浏览器本地存储
共同点:都是存储在浏览器本地的
区别:
cookie是由服务器端写入的、而SessionStorage、LocalStorage都是由前端写入的cookie的生命周期是由服务端在写入的时候就设置好的,LocalStorage是写入就一直存在的,除非手动清除,SessionStorage是页面关时就会自动清除。cookie的存储空间比较小大概4KB,SessionStorage、LocalStorage存储空间比较大,大概5MCookie、SessionStorage、LocalStorage存数据共享都遵循同源原则,SessionStorage还限制必须是同一个页面在前端给后端发发送请求时会自动携带Cookie中的数据,但是SessionStorage、LocalStorage不会
由于以上区别,它们的应用场景也不同
Cookie一般用于存储登录验证信息SessionID或者tokenLocalStorage常用于存储不易变动的数据,减轻服务器的压力SessionStorage可以用来检测用户是否时刷新进入页面,如音乐播放器恢复播放进度条的功能
·call apply bind 的区别
1. 相同点:
都是改变this指向的第一个参数都是this要指向的对象都可以利用后续参数传参
2. 区别:
call和bind的参数是依次传参,一一对应的但apply只有两个参数,第二个参数为数组call和apply都是对函数进行直接调用,而bind方法返回的仍是一个函数
·实现一个 bind(编程)
(function () {Function.prototype.bind = function () {let args = arguments;return () => {return this.apply(args[0], [...args].slice(1));};};})();
·最大连续子数组 (编程)
问题描述,给定一个数组A[0,1,...,n-1],求出A的连续数组,使得该子数组的和最大。
例如:数组A[1,-2,3,10,-4,7,2],则最大的子数组为[3,10,-4,7,2]
解法:动态规划
int maxSubArray_dongtaiguihua(int A[], int n) {int result = A[0];int sum = A[0];for (int i = 0; i < n; i++) {if (sum > 0)sum += A[i];else sum = A[i];if (sum > result)result = sum;}return result;}
·老虎吃羊的问题
问题
100只老虎和一只羊共同生活在一个只有草的魔法岛上。老虎可以吃草,但它们更喜欢吃羊。
假设:
A、每次一只老虎只能吃一只羊,并且吃完后老虎会变成羊;
B、所有的老虎都很精明,并且都想活下去。
问:
羊会被吃掉吗?
解答
对于数量较大的脑筋急转弯,可以先降低数量,简化问题。
这里100是个大数目,所以让我们再次把问题简化。如果只有一只老虎(m=1),它肯定会吃掉羊,因为它不用担心变成羊后会被吃掉。
如果有2只老虎呢?因为两只老虎都很精明,都清楚如果自己吃掉羊后变成羊,就会被另一只老虎吃掉,所以结果是,谁也不去吃羊。
如果有3只老虎呢?如果其中一只老虎吃掉一只羊后变身,剩下的两只老虎不会再继续吃羊,所以第一只老虎把羊吃掉。
如果有四只老虎,每只老虎都知道如果它吃了羊,它就会变成羊。还剩下3只老虎,它还是会被吃掉的。所以为了保证最大的生存可能性,没有老虎会吃羊肉。
同样的逻辑,我们自然可以证明,如果老虎的数量是偶数,羊就不会被吃掉。如果数字是奇数,羊就会被吃掉。对于100只老虎的情况,羊不会被吃掉。
·vue 中的 nextTick
nextTick:
将回调推迟到下一个 DOM 更新周期之后执行。在更改了一些数据以等待 DOM 更新后立即使用它。
nextTick会将其中的回调函数放入微任务队列中
·宏任务和微任务
1. 什么是宏任务和微任务
宏任务(macrotask)异步Ajax请求setTimeout 、setInterval文件操作其他宏任务微任务(microtask)Promise.then、Promise.catch和Promise.finallyprocess.nextTick其他微任务
2. 宏任务和微任务的执行顺序
每一个宏任务执行完之后,都会检查是否存在待执行的微任务,
如果有,则执行完所有的微任务之后,再执行下一个宏任务。
宏任务和微任务交替执行。
3. 经典面试题
console.log('1');setTimeout(function() {console.log('2');new Promise(function(resolve) {console.log('3');resolve()}).then(function() {console.log('4');})})new Promise(function(resolve) {console.log('5');resolve()}).then(function() {console.log('6');})setTimeout(function() {console.log('7');new Promise(function(resolve) {console.log('8');resolve()}).then(function() {console.log('9');})})
正确输出顺序: 1 5 6 2 3 4 7 8 9
分析
第一行中,同步任务A块中,这个定时器的回调函数属于异步任务里面的宏任务,一整个放入宏任务队列等待B块中,五属于同步任务,六属于微任务C块中,和A块一样,一整个放入宏任务队列所以,先执行同步任务 1 5再执行微任务 6,现在只剩下宏任务队列的两个任务了会先执行A块,执行 2 3 4再执行 C块,执行 7 8 9
·正则中的 i 具体做了什么事
正则表达匹配中是有区分大小写的,i 作用是忽略大小写,匹配。
·JavaScript的三种类型检测typeof,instanceof,toString比较
1. typeof:返回一个表达式的数据类型的字符串,返回结果只能为javascript中的基本数据类型,包括:number、boolean、string、object、undefined、function等6种数据类型。
2. instanceof:采用了另一种方式来判断对象类型:原型链。如 a instanceof b只要能在a对象的原型链上找到b,则认为a是b类型的一个对象。
3. toString:使用Object.prototype.toString.call(value) 方法去调用对象,得到对象的构造函数名。可以解决instanceof的跨框架问题
·script 标签中 async 和 defer 的区别
1. 共同点:
script放在<head>和放在<body>底部时没区别。script脚本会异步加载,在加载过程中不会阻塞HTML代码的解析和渲染;
2. 区别:
defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。defer是“渲染完再执行”,async是“下载完就执行”。另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的;
注意:如果同时指定了两个属性,则会遵从async属性而忽略defer属性
·position 有哪几种?分别说一下对应的效果和用法
relative:相对定位,经常配合absolute来实现垂直居中;absolute:绝对定位(脱离文档流的布局),起始位置为html文档,如果父元素为relative则相对于父元素;fixed:固定定位(类似于absolute),相对于浏览器窗口不随着滚动条而改变位置, 通常用于功能:回到顶部按钮;static:静态定位,元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。·css 选择器优先级(由高到低)
! important内联样式(行内样式:style=" 属性:属性值; ")id选择器(#myid)类选择器(.myclassname)标签选择器(div,h1,p)子选择器(ul < li)后代选择器(li a)伪类选择器(a:hover,li:nth-child)·js原型链
由于原型prototype本身是对象,因此他也有隐式原型,指向的规则不变,从某个对象出发,依次寻找隐式原型的指向,将形成一个链条,该链条叫做原型链。它也有一个’_ _ proto_ _'属性
fn._ _ proto _ _=== Foo.prototype;Foo.prototype._ _ proto _ _=== Object.prototype;
· JavaScript创建对象的方式
1. 利用字面量创建对象
var obj = {name: '猫猫没有猫耳朵',sayHi: function () {console.log('hi~');}}
2. 利用new Object创建对象
<script>var obj = new Object();//O要大写obj.name = '猫猫没有猫耳朵';obj.sayHi = function () {console.log('hi~');}obj.sayHi();</script>
3. 利用构造函数创建对象
<script>function 构造函数名() {this.属性 = 值;this.方法 = function () {}}new 构造函数名();</script>
·使用JS实现一个new方法
function _new(constructer, ...arg) {// 创建一个空的对象let resultObj = {};// 链接该对象到原型,这样新对象就能访问到原型上面的方法resultObj.__proto__ = constructer.prototype;// 然后实现步骤3,将新创建的对象作为this的上下文let result = constructer.call(resultObj, ...arg);// 实现步骤4:如果该函数没有返回对象(即result不是一个对象),则返回this(即resultObj)return typeOf result === 'object' ? result : resultobj}
new方法的效果
function Persion(name, age) {this.name = name;this.age = age;}let Persion1 = _new(Persion, 'lucy', '18');console.log(Persion1.name); // 'lucy'console.log(Persion1 instanceof Persion); // true
·MVVM 结构
MVVM是Model-View-ViewModel的简写。即模型-视图-视图模型。【模型】指的是后端传递的数据。【视图】指的是所看到的页面。【视图模型】mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM
·MVVM 和 MVC 的区别
MVVM与MVC的最大区别就是:它实现了View和Model的自动同步,也就是当Model的数据改变时,我们不用再自己手动操作Dom元素,来改变View的显示,而是改变数据后该数据对应View层显示会自动改变。MVVM并不是用VM完全取代了C,ViewModel存在目的在于抽离Controller中展示的业务逻辑,而不是替代Controller,其它视图操作业务等还是应该放在Controller中实现。
mvvm各部分的通信是双向的,而mvc各部分通信是单向的mvvm是真正将页面与数据逻辑分离放到js里去实现,而mvc里面未分离
· Vue 的生命周期
vue生命周期是指vue实例对象从创建之初到销毁的过程,vue所有功能的实现都是围绕其生命周期进行的,在生命周期的不同阶段调用对应的钩子函数实现组件数据管理和DOM渲染两大重要功能
· Vue生命周期什么阶段才能调用DOM?什么阶段能发起请求?
1. 调用DOM:
在钩子函数 mounted 被调用前,Vue 已经将编译好的模板挂载到页面上,所以在 mounted 中可以访问操作 DOM。
2. 发请求:
可以在钩子函数 created、beforeMount、mounted 中进行调用,因为在这三个钩子函数中,data 已经创建,可以将服务端端返回的数据进行赋值。
但是推荐在 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
能更快获取到服务端数据,减少页面loading 时间;ssr不支持 beforeMount 、mounted 钩子函数,所以放在 created 中有助于一致性;
·Vue 的组件通信(三种)
父子通信父向子传递数据是通过 props,子向父是通过 events($ emit)通过父链 / 子链也可以通信($ parent / $ children);ref 也可以访问组件实例;provide / inject API;$attrs/ $listeners兄弟通信BusVuex跨级通信Bus;Vuex;provide / inject API$attrs/ $listeners·讲一下 TCP 的三次握手和四次挥手 (HTTP 传输过程)
三次握手客户端主机C说:“我可以给你发送数据吗?”服务器S说:“可以的,不过我可能也会给你发送数据。”C:“好,那我开始互相发送数据吧。”四次挥手客户端主机C说:“我没有数据了,断开连接吧。 ”服务器S说:“好,但是我还有数据(不断给C发送数据,此时C已经不能给S发送数据了,但是必须要就收S发来的数据)。”(当S给C发完数据后)S说:“我发完了,断开连接吧。”C说:“好,断开连接吧。”· promise 有哪几种状态
初始态pending成功态resolved(fulfilled)失败态rejected三种状态小结
状态是可转化
最初创建promise对象是,默认状态是pending,如果在函数体内部调用了第一个参数对应的函数,则状态变成了resolved;如果调用了第二个参数对应的函数,则状态变成了rejected
pending ----- resolve() --> resolved;pending ----- reject() --> rejected;
状态转换是不可逆的
一旦从pending --> resolved(或者rejected),就不可能再回到pending,也不能由resolved变成rejected
·promise是什么与使用方法
Promise的作用:Promise是异步微任务,解决了异步多层嵌套回调的问题,让代码可读性更高,更容易维护Promise使用
Promise的特点对象的状态不受外界影响(Promise对象代表一个异步操作,有三种状态)一旦状态改变,就不会再变,任何时候都可以得到这个结果resolve 方法的参数是then中回调函数的参数,reject 方法中的参数是catch中的参数then 方法和 catch方法 只要不报错,返回的都是一个fullfilled状态的promisePromise的其他方法Promise.resolve() :返回的Promise对象状态为fulfilled,并且将该value传递给对应的then方法。 Promise.reject():返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法。Promise.all():返回一个新的promise对象,该promise对象在参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。Promise.any():接收一个Promise对象的集合,当其中的一个 promise 成功,就返回那个成功的promise的值。Promise.race():当参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。
·手写promise
const p1 = new Promise((resolve, reject) => {console.log('create a promise');resolve('成功了');})console.log("after new promise");const p2 = p1.then(data => {console.log(data)throw new Error('失败了')})const p3 = p2.then(data => {console.log('success', data)}, err => {console.log('faild', err)})
· 手写 Promise.All()
const PromiseAll = (iterator) => {const promises = Array.from(iterator); // 对传入的数据进行浅拷贝,确保有遍历器const len = promises.length; // 长度let index = 0; // 每次执行成功+1,当等于长度时,说明所有数据都返回,则可以resolvelet data = []; // 用来存放返回的数据数组return new Promise((resolve, reject) => {for (let i in promises) {promises[i].then((res) => {data[i] = res;if (++index === len) {resolve(data);}}).catch((err) => {reject(err);});}});};const promise1 = Promise.resolve('promise1');const promise2 = new Promise(function (resolve, reject) {setTimeout(resolve, 2000, 'promise2');});const promise3 = new Promise(function (resolve, reject) {setTimeout(resolve, 1000, 'promise3');});PromiseAll([promise1, promise2, promise3]).then(function(values) {console.log(values);});
· 编程题(最长公共前缀)
题目内容
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入:strs = [“flower”,“flow”,“flight”]
输出:“fl”
示例 2:
输入:strs = [“dog”,“racecar”,“car”]
输出:“”
import java.util.Arrays;class Solution {public String longestCommonPrefix(String[] strs) {int l = strs.length;StringBuffer sb =new StringBuffer(200);Arrays.sort(strs);int ml= Math.min(strs[0].length(),strs[l-1].length());if(ml==0){return "";}else{for(int i= 0;i<ml;i++){if(strs[0].charAt(i)==strs[l-1].charAt(i)){sb.append(strs[0].charAt(i));}else{return sb.toString();}}}return sb.toString();}}
如果觉得《前端面试题及答案(字节跳动)(一)》对你有帮助,请点赞、收藏,并留下你的观点哦!