前端面试题记录
HTML面试题记录
HTML5新特性
- 语义化标签:比如 article、footer、header、nav、section;
- 表单控件:calendar、date、time、email、url、search;
- 媒体元素video和audio元素
- 本地存储:localStorage sessionStorage
- 新的技术,websocket
前端页面由哪三个部分组成
- html:页面结构,布局
- css:样式
- js:行为交互
HTML和XHTML的区别
XHTML:重写了HTML规范,比HTML更严格
XHTML中所有的标记都必须有一个相应的结束标签;
XHTML所有标签的元素和属性的名字都必须使用小写;
所有的XML标记都必须合理嵌套;
所有的属性都必须用引号“”括起来;
把所有<和&特殊符号用编码表示;
给所有属性附一个值;
不要在注释内容中使用“–”;
图片必须使用说明文字。
canvas和svg的区别
canvas | svg |
---|---|
通过js绘制2D图形,按像素进行渲染,当位置发生改变会重新进行绘制 | 使用XML绘制的2D图形,可以为元素添加js处理器 |
依赖分辨率 | 不依赖分辨率 |
不支持事件处理器 | 支持事件处理器 |
弱的文本渲染能力 | 最适合带有大型渲染区域的应用程序(如谷歌地图) |
能以.png或.jpg格式保存结果图像 | 复杂度高会减慢渲染速度 |
最适合图像密集型游戏,其中的许多对象会被频繁重绘 | 不适合游戏应用 |
div+css布局和table布局有什么优点
表现和结构分离
页面加载速度更快,结构化清晰,页面显示简洁
修改样式方便,只要改css文件
易于优化,搜索引擎更友好
语义化的了解
正确的标签做正确的事
内容结构化,结构更清晰
便于搜索引擎解析
便于阅读理解维护
src和href的区别
src
: 引用资源,替换当前元素,用在img,script,iframe上
href
: 在当前元素和引用资源建立联系,用在link和a等元素上
img标签的title和alt是什么
title
:解释信息,鼠标移上去显示的信息
alt
:替换信息、图片不能显示时的信息
块级元素、行内元素、行内块元素
块级元素
特点:可设置宽高边距,占满整行,会自动换行
示例:div、 p、 h1 、h6、ol、ul、dl、table、address、blockquote、form
行内元素:
特点:无法设置宽高边距,不会占满整行,不会自动换行
示例:a、strong、b、em、i、del、s、ins、u、span
行内块元素:
- 特点:可设置宽高,占满整行,但不会自动换行
seo的TDK是什么
title description keywords
JS面试题记录
JS==以及===区别 在什么情况下使用
==
和===
都是用于比较两个值是否相等的JS运算符,它们之间的主要区别在于它们的比较方式和类型转换。
==
比较两个值是否相等时,会进行类型转换。如果两个值的数据类型不同,JS会尝试将它们转换为相同的类型,然后再进行比较。这种类型转换可能会产生一些意想不到的结果,例如:
console.log(1 == '1'); // true
console.log(true == 1); // true
console.log(null == undefined); // true
===
比较两个值是否相等时,不会进行类型转换。只有当两个值的类型相同且值相等时,才会返回true,否则返回false。这种比较方式更为严格和安全,因为它可以避免类型转换带来的问题。
在一般情况下,建议使用===
运算符进行比较。只有在确实需要进行类型转换时,才使用==
运算符。例如,在比较两个值是否为null或undefined时,使用==比较更为方便:
if (value == null) {
// 这里会同时匹配 null 和 undefined
}
需要注意的是,使用==
比较时,要注意避免类型转换带来的意想不到的结果。如果不确定类型转换的结果,可以使用===
进行比较,或者先显式地将值转换为相应的类型,再进行比较。例如:
console.log(Number('1') == 1); // true
console.log(Number('foo') == NaN); // false,NaN 不等于任何值,包括它本身
console.log(String(1) === '1'); // true
typeof 与 instanceof 区别
typeof
和instanceof
操作符都是用来判断数据类型的 但使用场景却各不相同。
typeof
typeof运算符返回一个字符串,表示操作数的类型
typeof operand
typeof(operand)
operand表示要返回类型的对象或基本类型的表达式
typeof 666 // 'number'
typeof '666' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
typeof null // 'object'
typeof [] // 'object'
typeof {} // 'object'
typeof可以精准的判断基本数据类型(null)除外
instanceof
instanceof
运算符用于检测构造函数的prototype
属性是否出现在某个实例对象的原型链上
使用方法如下
object instanceof constructor
object 是指某个实例对象
constructor是指某个构造函数
// 定义构造函数
function C(){}
function D(){}
var o = new C();
o instanceof C; // true,因为 Object.getPrototypeOf(o) === C.prototype
o instanceof D; // false,因为 D.prototype 不在 o 的原型链上
o instanceof Object; // true,因为 Object.prototype.isPrototypeOf(o) 返回 true
C.prototype instanceof Object // true,同上
C.prototype = {};
var o2 = new C();
o2 instanceof C; // true
o instanceof C; // false,C.prototype 指向了一个空对象,这个空对象不在 o 的原型链上。
D.prototype = new C(); // 继承
var o3 = new D();
o3 instanceof D; // true
o3 instanceof C; // true 因为 C.prototype 现在在 o3 的原型链上
区别
typeof与instanceof 都是判断数据类型的方法,区别如下:
- typeof会返回一个运算数的基本类型,instanceof 返回的是布尔值
- instanceof 可以准确判断引用数据类型,但是不能正确判断原始数据类型
- typeof虽然可以判断原始数据类型(null 除外),但是无法判断引用数据类型(function 除外)
eval是做什么的?
非严格模式,可以将json字符串转换为对象的形式。也可将字符串参数转化为脚本代码执行,但只适合在非严格模式下。它的功能是将对应的字符串解析成js并执行,应该避免使用js,因为非常消耗性能(2次,一次解析成js,一次执行),简单来说将字符串参数解析成js代码并执行,并返回执行结果。但应避免使用,不安全,也耗性能。
Vue面试题记录
什么是计算属性
计算属性是用来声明式的描述一个值依赖了其他的值,当它依赖的这个值发生改变时,就更新DOM
当在模板中把数据绑定到一个计算属性上时,vue会在它依赖的任何值导致该计算属性改变时更新DOM
每个计算属性都包括一个getter和setter,读取时触发getter,修改时触发setter
生命周期
vue生命周期是什么
Vue 实例从创建到销毁的过程为生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、卸载等一系列过程,称之为 Vue 的生命周期。
vue生命周期总共有几个阶段
创建前/后, 载入前/后,更新前/后,销毁前/销毁后
简述每个周期具体适合哪些场景
beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法
created:data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作
beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的
mounted:执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行
beforeUpdate: 当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
updated:页面显示的数据和data中的数据已经保持同步了,都是最新的
beforeDestory:Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁
destroyed: 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。
第一次页面加载会触发哪几个钩子?
beforeCreate, created, beforeMount, mounted
组件传值的几种类型
- 父组件给子组件传值
- 子组件给父组件传值
- 非父子组件传值(任意组件之间传值)
父组件给子组件传值
- 父组件中通过 import - components - < /> 三部曲 注册子组件
- 子组件在 props 对象中创建一个属性 prop
- 父组件在注册的子组件标签中添加 prop 属性,即 prop=“value”
- 父组件可以通过 v-bind:prop(:prop)实现数据双向绑定
以下是具体实例
<!-- 父组件 -->
<template>
<div>
<child-component @myEvent="handleEvent"></child-component>
<p>从子组件接收到的值:{{ receivedValue }}</p>
</div>
</template>
<script>
import ChildComponent from '@/components/ChildComponent.vue'
export default {
components: {
ChildComponent
},
data() {
return {
receivedValue: ''
}
},
methods: {
handleEvent(value) {
this.receivedValue = value
}
}
}
</script>
<!-- 子组件 -->
<template>
<div>
<button @click="emitValue">传值给父组件</button>
</div>
</template>
<script>
export default {
methods: {
emitValue() {
this.$emit('myEvent', '这是子组件传递给父组件的值')
}
}
}
</script>
子组件给父组件传值
- 子组件中需要以某种方式的方法来触发一个自定义事件(例如点击事件)
- 子组件使用 this.$emit 方法,第一个参数为父组件定义的方法名称 event,第二个参数为传递的值
- 在父组件中注册子组件并在子组件标签上绑定对自定义事件的监听(event=“Event”),Event(data) 可以接收传过来的参数
以下是具体实例
<!-- 子组件 -->
<template>
<div>
<button @click="emitValue">传值给父组件</button>
</div>
</template>
<script>
export default {
methods: {
emitValue() {
this.$emit('myEvent', '这是子组件传递给父组件的值')
}
}
}
</script>
子组件定义了一个按钮,当按钮被点击时,sendData方法会被调用,它通过this.$emit方法触发了一个自定义事件child-event,并传递了一个字符串值作为参数。
<!-- 父组件 -->
<template>
<div>
<child-component @myEvent="handleEvent"></child-component>
<p>从子组件接收到的值:{{ receivedValue }}</p>
</div>
</template>
<script>
import ChildComponent from '@/components/ChildComponent.vue'
export default {
components: {
ChildComponent
},
data() {
return {
receivedValue: ''
}
},
methods: {
handleEvent(value) {
this.receivedValue = value
}
}
}
</script>
父组件通过import引入了子组件,然后在模板中使用<child-component>
标签将子组件添加到父组件中。在子组件上,我们监听了myEvent事件,并在触发事件时调用了handleEvent方法。handleEvent方法将接收到的值设置为receivedValue,然后在模板中显示出来。
兄弟组件之间的传参
EventBus 是中央事件总线,不管是父子组件,兄弟组件,跨层级组件等都可以使用它完成通信操作
兄click设置点击事件,用$emit设置通道传参给中转站,弟通过 $on接收来自中转站的参数
任意组件之间的通信
任意关系的组件之间的传参可以通过 vue-router 来完成
vue路由传参的三种方式
params传参(显示参数)
params传参(显示参数)又可分为声明式
和编程式
两种方式
声明式router-link
该方式是通过router-link
组件的to
属性实现,该方法的参数可以是一个字符串路径,或者一个描述地址的对象。使用该方式传值的时候,需要子路由提前配置好参数,例如:
// router/index.js
{
path: '/child/:id',
component: Child
}
// src/compants/father.vue
<router-link :to="/child/123">进入Child路由</router-link>
编程式 this.$router.push
使用该方式传值的时候,同样需要子路由提前配置好参数,如下实例:
// router/index.js
{
path: '/child/:id',
component: Child
}
//父路由编程式传参(通过Onclick点击事件触发)
this.$router.push({
path:'/child/${id}',
})
子路由中可以通过下面代码来获取传递的参数值
this.$route.params.id
编程式 this.$router.push
使用该方式传值的时候,同样需要子路由提前配置好参数,不过不能再使用 :/id 来传递参数了,因为父路由中,已经使用 params 来携带参数了,例如:
// router/index.js
{
path: '/child,
name: 'Child',
component: Child
}
//父路由编程式传参(通过Onclick点击事件触发)
this.$router.push({
name:'Child',
params:{
id:123
}
})
子路由中可以通过下面代码来获取传递的参数值
this.$route.params.id
query传参
query 传参(显示参数)也可分为 声明式 和 编程式 两种方式
声明式 router-link
该方式也是通过 router-link
组件的to
属性实现,不过使用该方式传值的时候,需要子路由提前配置好路由别名(name 属性),例如:
// router/index.js
{
path: '/child,
name: 'Child',
component: Child
}
//父路由组件
<router-link :to="{name:'Child',query:{id:123}}">进入Child路由</router-link>
编程式 this.$router.push
使用该方式传值的时候,同样需要子路由提前配置好路由别名(name 属性),例如:
// router/index.js
{
path: '/child,
name: 'Child',
component: Child
}
//父路由编程式传参(一般通过事件触发)
this.$router.push({
name:'Child',
query:{
id:123
}
})
子路由中可以通过下面代码来获取传递的参数值
this.$route.query.id