Web开发

HTML

行内元素与块级元素的区别

  • 一个行内元素只占据它对应标签的边框所包含的空间。常见的行内元素有 a b span img strong sub sup button input label select textarea
  • 块级元素占据其父元素(容器)的整个宽度,因此创建了一个“块”。常见的块级元素有 div ul ol li dl dt dd h1 h2 h3 h4 h5 h6 p
  • 格式上,默认情况下,行内元素不会以新行开始,而块级元素会新起一行。
  • 内容上,默认情况下,行内元素只能包含文本和其他行内元素。而块级元素可以包含行内元素和其他块级元素。
  • 行内元素与块级元素属性的不同,主要是盒模型属性上:行内元素设置 width 无效,height 无效(可以设置 line-height),设置 margin 和 padding 的上下不会对其他元素产生影响。

请描述一下 cookie,sessionStorage 和 localStorage 的区别?

  • 浏览器端常用的存储技术是 cookie 、localStorage 和 sessionStorage。
  • cookie 其实最开始是服务器端用于记录用户状态的一种方式,由服务器设置,在客户端存储,然后每次发起同源请求时,发送给服务器端。cookie 最多能存储 4 k 数据,它的生存时间由 expires 属性指定,并且 cookie 只能被同源的页面访问共享。
  • sessionStorage 是 html5 提供的一种浏览器本地存储的方法,它借鉴了服务器端 session 的概念,代表的是一次会话中所保存的数据。它一般能够存储 5M 或者更大的数据,它在当前窗口关闭后就失效了,并sessionStorage 只能被同一个窗口的同源页面所访问共享。
  • localStorage 也是 html5 提供的一种浏览器本地存储的方法,它一般也能够存储 5M 或者更大的数据。它和 sessionStorage 不同的是,除非手动删除它,否则它不会失效,并且 localStorage 也只能被同源页面所访问共享。

如何实现浏览器内多个标签页之间的通信

  • 使用 WebSocket,通信的标签页连接同一个服务器,发送消息到服务器后,服务器推送消息给所有连接的客户端。
  • 使用 SharedWorker (只在 chrome 浏览器实现了),两个页面共享同一个线程,通过向线程发送数据和接收数据来实现标签页之间的双向通行。
  • 可以调用 localStorage、cookies 等本地存储方式,localStorge 另一个浏览上下文里被添加、修改或删除时,它都会触发一个 storage 事件,我们通过监听 storage 事件,控制它的值来进行页面信息通信;
  • 如果我们能够获得对应标签页的引用,通过 postMessage 方法也是可以实现多个标签页通信的。

的 title 和 alt 有什么区别

  • title 通常当鼠标滑动到元素上的时候显示
  • alt 是 的特有属性,是图片内容的等价描述,用于图片无法加载时显示、读屏器阅读图片。可提图片高可访问性,除了纯装饰图片外都必须设置有意义的值,搜索引擎会重点分析。

HTTP 状态码及其含义

1XX:信息状态码,2XX:成功状态码,3XX:重定向,4XX:客户端错误,5XX: 服务器错误

CSS

如何居中 div

一般对于宽高固定的元素常见的几种居中的方法有

  • 我们可以利用margin:0 auto来实现元素的水平居中。
  • 利用绝对定位,设置四个方向的值都为0,并将margin设置为auto,由于宽高固定,因此对应方向实现平分,可以实现水平和垂直方向上的居中。
  • 利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过margin负值来调整元素的中心点到页面的中心。
  • 利用绝对定位,先将元素的左上角通过top:50%和left:50%定位到页面的中心,然后再通过translate来调整元素的中心点到页面的中心。
  • 使用flex布局,通过align-items:center和justify-content:center设置容器的垂直和水平方向上为居中对齐,然后它的子元素也可以实现垂直和水平的居中。

对于宽高不定的元素,上面的后面两种方法,可以实现元素的垂直和水平的居中。

display 有哪些值?说明他们的作用

  • block 块类型。默认宽度为父元素宽度,可设置宽高,换行显示。
  • none 元素不显示,并从文档流中移除。
  • inline 行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。
  • inline-block 默认宽度为内容宽度,可以设置宽高,同行显示。
  • list-item 像块类型元素一样显示,并添加样式列表标记。
  • table 此元素会作为块级表格来显示。
  • inherit 规定应该从父元素继承display属性的值。

position 有哪些值?说明他们的作用

  • absolute:生成绝对定位的元素,相对于值不为static的第一个父元素的padding box进行定位,也可以理解为离自己这一级元素最近的一级position设置为absolute或者relative的父元素的padding box的左上角为原点的。
  • fixed(老IE不支持):生成绝对定位的元素,相对于浏览器窗口进行定位。
  • relative:生成相对定位的元素,相对于其元素本身所在正常位置进行定位。
  • static:默认值。没有定位,元素出现在正常的流中(忽略top,bottom,left,right,z-index声明)。
  • inherit:规定从父元素继承position属性的值。

margin 和 padding 区别

margin是盒子的外边距,即盒子与盒子之间的距离,而padding是内边距,是盒子的边与盒子内部元素的距离。margin是用来隔开元素与元素的间距;padding是用来隔开元素与内容的间隔。

说一下常见的元素隐藏方式

  • 使用 display:none;隐藏元素,渲染树不会包含该渲染对象,因此该元素不会在页面中占据位置,也不会响应绑定的监听事件。
  • 使用 visibility:hidden;隐藏元素。元素在页面中仍占据空间,但是不会响应绑定的监听事件。
  • 使用 opacity:0;将元素的透明度设置为 0,以此来实现元素的隐藏。元素在页面中仍然占据空间,并且能够响应元素绑定的监听事件。
  • 通过使用绝对定位将元素移除可视区域内,以此来实现元素的隐藏。
  • 通过 z-index 负值,来使其他元素遮盖住该元素,以此来实现隐藏。
  • 通过 clip/clip-path 元素裁剪的方法来实现元素的隐藏,这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。
  • 通过 transform:scale(0,0)来将元素缩放为 0,以此来实现元素的隐藏。这种方法下,元素仍在页面中占据位置,但是不会响应绑定的监听事件。

css 两栏布局的实现,以左边宽度固定200px为例

  • 利用浮动,将左边元素宽度设置为 200px,并且设置向左浮动。将右边元素的 margin-left 设置为 200px,宽度设置为 auto(默认为 auto,撑满整个父元素)。*
  • 第二种是利用 flex 布局,将左边元素的放大和缩小比例设置为 0,基础大小设置为 200px。将右边的元素的放大比例设置为 1,缩小比例设置为 1,基础大小设置为 auto。*
  • 第三种是利用绝对定位布局的方式,将父级元素设置相对定位。左边元素设置为 absolute 定位,并且宽度设置为 200px。将右边元素的 margin-left 的值设置为 200px。*
  • 第四种还是利用绝对定位的方式,将父级元素设置为相对定位。左边元素宽度设置为 200px,右边元素设置为绝对定位,左边定位为 200px,其余方向定位为 0。

CSS 选择符有哪些

  • id选择器(#myid)
  • 类选择器(.myclassname)
  • 标签选择器(div,h1,p)
  • 后代选择器(h1 p)
  • 相邻后代选择器(子)选择器(ul>li)
  • 兄弟选择器(li~a)
  • 相邻兄弟选择器(li+a)
  • 属性选择器(a[rel=”external”])
  • 伪类选择器(a:hover,li:nth-child)
  • 伪元素选择器(::before、::after)
  • 通配符选择器(*)

JavaScript

介绍 js 的基本数据类型

  • js 一共有六种基本数据类型,分别是 Undefined、Null、Boolean、Number、String,还有在 ES6 中新增的 Symbol 和 ES10 中新增的 BigInt 类型。
  • Symbol 代表创建后独一无二且不可变的数据类型,它的出现我认为主要是为了解决可能出现的全局变量冲突的问题。
  • BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

null 和 undefined 的区别

undefined 代表的含义是未定义,null 代表的含义是空对象。一般变量声明了但还没有定义的时候会返回 undefined,null主要用于赋值给一些可能会返回对象的变量,作为初始化。

eval 是做什么的

它的功能是把对应的字符串解析成 JS 代码并运行。应该避免使用 eval,不安全,非常耗性能(2次,一次解析成 js 语句,一次执行)。

javascript 代码中的 “use strict”; 是什么意思

use strict 是一种 ECMAscript5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行。

.call() 和 .apply() 的区别

它们的作用一模一样,区别仅在于传入参数的形式的不同。

  • apply 接受两个参数,第一个参数指定了函数体内 this 对象的指向,第二个参数为一个带下标的集合,这个集合可以为数组,也可以为类数组,apply 方法把这个集合中的元素作为参数传递给被调用的函数。
  • call 传入的参数数量不固定,跟 apply 相同的是,第一个参数也是代表函数体内的 this 指向,从第二个参数开始往后,每个参数被依次传入函数。

如何判断当前脚本运行在浏览器还是 node 环境中

this === window ? ‘browser’ : ‘node’;通过判断 Global 对象是否为 window,如果不为 window,当前脚本没有运行在浏览器中。

js 中的深浅拷贝实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
// 简单粗暴,不考虑拷贝函数
var arr = ['old', 1, true, ['old1', 'old2'], {old: 1}]
var new_arr = JSON.parse( JSON.stringify(arr) );
console.log(new_arr);

// 浅拷贝的实现;
function shallowCopy(object) {
// 只拷贝对象
if (!object || typeof object !== "object") return;

// 根据 object 的类型判断是新建一个数组还是对象
let newObject = Array.isArray(object) ? [] : {};

// 遍历 object,并且判断是 object 的属性才拷贝
for (let key in object) {
if (object.hasOwnProperty(key)) {
newObject[key] = object[key];
}
}

return newObject;
}

// 深拷贝的实现;
function deepCopy(object) {
if (!object || typeof object !== "object") return object;

let newObject = Array.isArray(object) ? [] : {};

for (let key in object) {
if (object.hasOwnProperty(key)) {
newObject[key] = deepCopy(object[key]);
}
}

return newObject;
}

var,let,const三者的特点和区别

  • var 的特点
    • 存在变量提升
    • 一个变量可多次声明,后面的声明会覆盖前面的声明
    • 在函数中使用var声明变量的时候,该变量是局部的
  • let的特点
    • 不存在变量提升,let声明变量前,该变量不能使用
    • let命令所在的代码块内有效,在块级作用域内有效
    • let不允许在相同作用域中重复声明,注意是相同作用域,不同作用域有重复声明不会报错
  • const 特点
    • const声明一个只读的变量,声明后,值就不能改变
    • const必须初始化
    • const并不是变量的值不能改动,而是变量指向的内存地址所保存的数据不得改动

比较操作符 “===”、“==” 的区别

  • 使用双等号进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较。
  • 使用三等号进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false。

说说你对async/await的理解

  • async函数返回的是一个promise对象,它可以用then方法添加回调函数。
  • 当函数执行的时候一旦遇到await就会阻塞后面的代码,等待promise的resolve() 作为await的返回结果。

箭头函数与普通函数有什么区别

1.this指向的问题,箭头函数没有自己的this,继承外层上下文绑定的this

2.箭头函数不绑定 arguments,取而代之用rest参数解决

1
2
3
var foo = (...args) => {
return args[0];
}

3.箭头函数不能用作构造器,和new一起用会抛出报错

4.箭头函数没有原型属性

1
2
var foo = () => {};
console.log(foo.prototype) //undefined

ES6中有哪些新特性

  • 不一样的变量声明:const和let
  • 模板字符串
  • 箭头函数(Arrow Functions)
  • 函数的参数默认值
  • Spread / Rest 操作符
  • 二进制和八进制字面量
  • 对象和数组解构
  • 对象超类
  • for…of 和 for…in
  • ES6中的类

Vue

Vue 的各个生命阶段是什么

Vue 一共有8个生命阶段,分别是创建前、创建后、加载前、加载后、更新前、更新后、销毁前和销毁后,每个阶段对应了一个生命周期的钩子函数。

  • beforeCreate 钩子函数,在实例初始化之后,在数据监听和事件配置之前触发。因此在这个事件中我们是获取不到 data 数据的。
  • created 钩子函数,在实例创建完成后触发,此时可以访问 data、methods 等属性。但这个时候组件还没有被挂载到页面中去,所以这个时候访问不到 $el 属性。一般我们可以在这个函数中进行一些页面初始化的工作,比如通过 ajax 请求数据来对页面进行初始化。
  • beforeMount 钩子函数,在组件被挂载到页面之前触发。在 beforeMount 之前,会找到对应的 template,并编译成 render 函数。
  • mounted 钩子函数,在组件挂载到页面之后触发。此时可以通过 DOM API 获取到页面中的 DOM 元素。
  • beforeUpdate 钩子函数,在响应式数据更新时触发,发生在虚拟 DOM 重新渲染和打补丁之前,这个时候我们可以对可能会被移除的元素做一些操作,比如移除事件监听器。
  • updated 钩子函数,虚拟 DOM 重新渲染和打补丁之后调用。
  • beforeDestroy 钩子函数,在实例销毁之前调用。一般在这一步我们可以销毁定时器、解绑全局事件等。
  • destroyed 钩子函数,在实例销毁之后调用,调用后,Vue 实例中的所有东西都会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

当我们使用 keep-alive 的时候,还有两个钩子函数,分别是 activated 和 deactivated 。用 keep-alive 包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行 deactivated 钩子函数,命中缓存渲染后会执行 actived 钩子函数。

Vue 组件间的参数传递方式

(1)父子组件间通信

第一种方法是子组件通过 props 属性来接受父组件的数据,然后父组件在子组件上注册监听事件,子组件通过 emit 触发事件来向父组件发送数据。

第二种是通过 ref 属性给子组件设置一个名字。父组件通过 $refs 组件名来获得子组件,子组件通过 $parent 获得父组件,这样也可以实现通信。

第三种是使用 provider/inject,在父组件中通过 provider 提供变量,在子组件中通过 inject 来将变量注入到组件中。不论子组件有多深,只要调用了 inject 那么就可以注入 provider 中的数据。

(2)兄弟组件间通信

第一种是使用 eventBus 的方法,它的本质是通过创建一个空的 Vue 实例来作为消息传递的对象,通信的组件引入这个实例,通信的组件通过在这个实例上监听和触发事件,来实现消息的传递。

第二种是通过 $parent.$refs 来获取到兄弟组件,也可以进行通信。

(3)任意组件之间

使用 eventBus ,其实就是创建一个事件中心,相当于中转站,可以用它来传递事件和接收事件。

如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候采用上面这一些方法可能不利于项目的维护。这个时候可以使用 vuex ,vuex 的思想就是将这一些公共的数据抽离出来,将它作为一个全局的变量来管理,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。

computed 和 watch 的差异

  • computed 是计算一个新的属性,并将该属性挂载到 Vue 实例上,而 watch 是监听已经存在且已挂载到 Vue 实例上的数据,所以用 watch 同样可以监听 computed 计算属性的变化。
  • computed 本质是一个惰性求值的观察者,具有缓存性,只有当依赖变化后,第一次访问 computed 属性,才会计算新的值。而 watch 则是当数据发生变化便会调用执行函数。
  • 从使用场景上说,computed 适用一个数据被多个数据影响,而 watch 适用一个数据影响多个数据。

$route 和 $router 的区别?

$route 是“路由信息对象”,包括 path,params,hash,query,fullPath,matched,name 等路由信息参数。而 $router 是“路由实例”对象包括了路由的跳转方法,钩子函数等。

vue-router 中的导航钩子函数

(1)全局的钩子函数 beforeEach 和 afterEach

beforeEach 有三个参数,to 代表要进入的路由对象,from 代表离开的路由对象。next 是一个必须要执行的函数,如果不传参数,那就执行下一个钩子函数,如果传入 false,则终止跳转,如果传入一个路径,则导航到对应的路由,如果传入 error ,则导航终止,error 传入错误的监听函数。

(2)单个路由独享的钩子函数 beforeEnter,它是在路由配置上直接进行定义的。

(3)组件内的导航钩子主要有这三种:beforeRouteEnter、beforeRouteUpdate、beforeRouteLeave。它们是直接在路由组件内部直接进行定义的。

axios是什么?怎样使用它?怎么解决跨域的问题?

解决跨域常用的有两种方式

  • CORS解决跨域问题,这需要通过后端来解决,通过设置header头来通配。使服务器允许跨域请求接口数据,而前端正常使用axios请求方式。
  • 通过接口代理的方式,在vue项目中创建一个vue.config.js,导入一个devServe,并配置里面的选项即可。

v-if 和v-show 区别

v-if 是动态添加,当值为false 时,是完全移除该元素,即dom 树中不存在该元素。 v-show 仅是隐藏/ 显示,值为false 时,该元素依旧存在于dom 树中。 若其原有样式设置了display: none 则会导致其无法正常显示。

算法数据结构

常用排序方法

冒泡排序 选择排序 插入排序 希尔排序 归并排序 快速排序 堆排序 基数排序

说一下算法平均复杂度,以为稳定性。

实现一个函数,完成超过范围的两个大整数相加功能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function bigNumberAdd(number1, number2) {
let result = "", // 保存最后结果
carry = false; // 保留进位结果

// 将字符串转换为数组
number1 = number1.split("");
number2 = number2.split("");
// 当数组的长度都变为0,并且最终不再进位时,结束循环
while (number1.length || number2.length || carry) {
// 每次将最后的数字进行相加,使用~~的好处是,即使返回值为 undefined 也能转换为 0
carry += ~~number1.pop() + ~~number2.pop();
// 取加法结果的个位加入最终结果
result = carry % 10 + result;
// 判断是否需要进位,true 和 false 的值在加法中会被转换为 1 和 0
carry = carry > 9;
}
// 返回最终结果
return result;
}

如何实现数组去重

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function unique(array) {
if (!Array.isArray(array) || array.length <= 1) return;
var result = [];
array.forEach(function (item) {
if (result.indexOf(item) === -1) {
result.push(item);
}
})
return result;
}

function unique(array) {
if (!Array.isArray(array) || array.length <= 1) return;

return [...new Set(array)];
}

栈和队列的区别

  • 栈的插入和删除操作都是在一端进行的,而队列的操作却是在两端进行的。
  • 栈是先进后出,队列是先进先出。
  • 栈只允许在表尾一端进行插入和删除,队列只允许在表尾一端进行插入,在表头一端进行删除。

Node.js

devDependencies和dependencies有区别

devDependencies开发阶段依赖的包
dependencies:生产环境需要依赖的包

网络

POST 和 GET 的区别?

  • GET 用于获取信息,是无副作用的,是幂等的,且可缓存
  • POST 用于修改服务器上的数据,有副作用,非幂等,不可缓存
  • 传送方式:GET通过地址栏传输,POST通过报文传输
  • 传送长度:GET参数有长度限制(受限于url长度),而POST无限制

操作系统

堆与栈区别

  • 管理方式不同。
  • 空间大小不同。
  • 生长方向不同。
  • 分配方式不同。
  • 分配效率不同。
  • 存放内容不同。
  • 能否产生碎片。

其他

经常使用的 git 命令

  • git init // 新建 git 代码库
  • git add // 添加指定文件到暂存区
  • git rm // 删除工作区文件,并且将这次删除放入暂存区
  • git commit -m [message] // 提交暂存区到仓库区
  • git branch // 列出所有分支
  • git checkout -b [branch] // 新建一个分支,并切换到该分支
  • git status // 显示有变更的文件

git pull 和 git fetch 的区别

  • git fetch 只是将远程仓库的变化下载下来,并没有和本地分支合并。
  • git pull 会将远程仓库的变化下载下来,并和当前分支合并。

说一下常用的Linux命令

rm mkdir cd touch …..

您的支持将鼓励我继续创作!
0%