前端基础总结
复习笔记
html
什么是重绘?什么是回流?
-
重绘: 当渲染树中的一些元素需要更新属性,而这些属性只是影响元素的外观、风格,而 不会影响布局的操作,比如 background color,我们将这样的操作称为重绘。
-
回流:当渲染树中的一部分(或全部)因为元素的规模尺寸、布局、隐藏等改变而需要重 新构建的操作,会影响到布局的操作,这样的操作我们称为回流。
H5有哪些新特性
- 绘画 canvas;
- 用于媒介回放的 video 和 audio 元素
- 本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失; sessionStorage 的数据在浏览器关闭后自动删除
- 语意化更好的内容元素,比如 article、footer、header、nav、section; 表单控件,calendar、date、time、email、url、search;
- 新的技术 webworker, websocket;
- 新的文档属性 document.visibilityState
css
说一下常见的盒子模型,如何切换两种盒子模型?
- 标准(W3C)盒子模型:属性 width,height 只包含内容 content,不包含 border 和 padding
- IE盒子模型:属性 width,height 包含 content、border 和 padding,指的是 content +padding+border。
box-sizing:content-box;
box-sizing:border-box;
如何解决margin塌陷/margin重叠?
- 有时当我们设置子元素的margin-top,但是却发现子元素没有出现上外边距的效果,反而是父元素出现了上外边距的效果。第一个子元素设置margin-top父元素会跟着移动,这就是
margin
塌陷,解决方法:- 为父元素设置padding。---要设置padding,设置margin不行
- 为父元素设置border。---设置border为0px不行,border要有值
- 为父元素设置 overflow: hidden
- 父级或子元素使用浮动或者绝对定位absolute
什么是BFC?BFC是如何触发的?
-
容器里面的元素不会在布局上影响到外面的元素
-
只要元素满足下面任一条件即可触发BFC特性
- body 根元素
- 浮动元素:float 除 none 以外的值
- 绝对定位元素:position (absolute、fixed)
- display 为 inline-block、table-cells、flex
- overflow 除了 visible 以外的值 (hidden、auto、scroll)【最常用】
如何实现垂直水平居中
- flex布局
.box{
display: flex;
align-items: center;
justify-content: center;
}
- 定位
.box{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
}
JavaScript
数据类型都有哪几种,有什么区别?
-
数据类型分为
原始数据类型
和对象数据类型
。- 原始数据类型:null、Boolean、Number、String、undefined、Symbol、BigInt
- 对象数据类型:Object
-
区别:原始数据类型存储在栈区,占用空间较小,存储的是值;对象类型同时存储在栈区和堆区,且大小不固定。
如何判断数据类型
typeOf
:可以判断基本数据类型,除了null
以外,因为null
认为是空对象的引用。instanceof
:可以判断对象类型,内部机制是通过原型链来进行判断的。constructor
:利用原型上的prototype.constructor指向实例的构造函数来进行判断。如果中途改变类型,则判断不准确。Object.prototype.toString.call
:使用Object对象的原型方法toString,返回值是[object 类型]字符串。
说一下js类型转换规则
-
转换为布尔值:除了
undefined
、null
、false
、NaN
、''
、0
、-0
,剩下的都为true
-
转化为数字:
- null,返回0
- undefined,返回NaN
- 布尔值, true 转换为1, false 转换为0
- 字符串:
- 如果字符串包含数值字符,包括数值字符前面带加、减号的情况,则转换为一个十进制数值
- 如果字符串包含有效的浮点值格式如 "1.1" ,则会转 换为相应的浮点值(同样,忽略前面的零)
- 如果字符串包含有效的十六进制格式如 "0xf" ,则会 转换为与该十六进制值对应的十进制整数值。
- 如果是空字符串(不包含字符),则返回0。
- 如果字符串包含除上述情况之外的其他字符,则返回NaN。
- 如果是对象,调用
valueof()
方法,并按照字符串的规则转换返回的值。如果转换结果是NaN,则调用toString()
方法,再按照转换字符串的规则转换。
-
转换为字符串,直接转化
如何正确判断this?箭头函数的this是什么?如何改变this指向
- 在浏览器中,全局环境下,
this
指向window
对象。 - 在函数中,
this
指向最后调用它的那个对象。 - 箭头函数的
this
始终指向其包裹箭头函数的第一个函数。 - 有
new
操作符,指向new
出来的那个对象。 call
、apply
、bind
指向绑定的新对象上。
== 和 === 有什么区别?
==
如果类型不同,会进行隐式转化;再进行比较。===
直接判断类型和值是否相等。
什么是闭包?
- 函数A内部有函数B,函数B访问函数A的变量,函数B就是一个闭包。闭包就是为了我们能够间接访问内部变量,避免被垃圾机制回收。
function a(){
let a=0;
function b(){
a++;
console.log(a)
}
return b
}
let n=a();
n(); //1
n(); //2
什么是浅拷贝?如何实现浅拷贝?什么是深拷贝?如何实现深拷贝?
- 浅拷贝:拷贝所有的值到新对象中,如果属性值是对象,则拷贝对象的地址。
//通过Object.assign
let a={
name:'tom',
age:18
};
let b=Object.assign({},a)
console.log(b);
//通过展开运算符
let c={
name:'lonjin',
age:18
};
let d={...c}
console.log(d)
- 深拷贝:拷贝所有的值到新对象中,如果属性值是对象,则拷贝对象的地址。
// JSON.parse(JSON.stringify(object))实现
/* 缺点:会忽略 undefined
会忽略 symbol
不能序列化函数
不能解决循环引用的对象 */
let a={
name:'tom',
fnc:{
age:18
}
}
let b=JSON.parse(JSON.stringify(a))
a.fnc.age=19
console.log(b.fnc)
如何理解原型?如何理解原型链?
-
举个例子:当我们写一个构造函数时候,构造函数身上会有一个
prototype
属性,这就是该构造函数的原型对象;它可以存一些该构造函数公告的属性和方法,同时该属性身上有constructor
属性,它指向创建它的构造函数。 -
当我们访问一个对象的某个属性时候,如果在对象内部没有找到,就会通过**proto**沿着向上查找,这就是原型链。
var、let 及 const 区别
var
声明的变量会变量提升let、const
声明的变量不会进行变量提升,且有块级作用域const
声明时必须赋值
如何实现继承
ES5
组合继承法:
function Parent(){
this.name='tom';
};
Parent.prototype.say=function(){
console.log(this.name)
};
function Child(){
Parent.call(this)
this.age=18;
};
Child.prototype=Object.create(Parent.prototype);
Child.prototype.constructor=Child;
ES6
使用class
:
class Parent{
constructor(name,age){
this.name=name;
this.age=age;
}
}
class Child extends Parent{
constructor(name,age,say){
super(name,age);
this.say=say;
}
}
let c=new Child('bob',17,'say hi')
Proxy 可以实现什么功能?
- Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
vue3
中就是通过Proxy
取代Object.defineProperty
来实现数据响应式。
forEach、map、filter、find、reduce、every、some都适用于哪种场景?
-
forEach
:进行遍历操作,可在当前遍历对象身上直接操作,不会产生新数组。 -
map
:用于遍历操作,且需要返回值,如果没有返回值,则为undefined
,map
会返回一个新数组。 -
filter
:进行一些筛选过滤,return
符合条件的值产生新数组。 -
find
:根据指定的条件找到数组中符合条件的值。 -
reduce
:提取数组对象中某个值|数组求和
Promise 的特点是什么,分别有什么优缺点?什么是 Promise 链?Promise 构造函数执行和 then 函数执行有什么区别?
-
Promise
本译就是承诺的意思,这个承诺会在未来有一个确切的答复,并且该承诺有三种状态:- 进行中:
pending
- 完成了:
resolved
- 失败了:
rejected
- 进行中:
-
承诺状态一旦改变就不可更改,且在构造
Promise
时候,构造函数内部代码是立即执行的。
new Promise((resolve, reject) => {
console.log('Promise')
})
console.log('finifsh') //Promise -> finifsh
Promise
可以进行链式调用,每次then()
都是一个新Promise
。如果在Promise
中使用了return
,也会被转化为Promise.resolve()
。
async 及 await 的特点,它们的优点和缺点分别是什么?await 原理是什么?
- 在普通函数前面加上
async
,该函数返回就成了一个Promise
,如果要使用其返回值,我们就可以使用then()
:
async function fn(){
console.log('fn');
return 'i im fn'
};
fn().then((val)=>{
console.log(val)
})
//fn ---> i im fn
await
只能在async
函数内使用
谈一谈js的执行机制
- js是一种单线程、异步、非阻塞、解释型脚本语言,它最大的特点就是单线程。在js执行时候,从上往下,先吧同步任务放到执行栈中执行,当遇到异步任务时候,会把异步任务放到异步队列,当执行栈为空的时候,会从异步队列中取出一条压入执行栈,这样一直循环,这就是
Event Loop
。异步任务又分为宏任务和微任务,微任务优先于宏任务。
new操作符都干了什么?
- 在内存中创建一个新对象
- 这个新对象内部的[[prototype]]特性被赋值为构造函数的prototype属性
- 构造函数内部的this被赋值为这个新对象(即this指向新对象)
- 如果构造函数返回非空 对象,则返回该对象;否则,返回刚创建的新对象
function _new(fn,...args){
const newObj = Object.create(fn.prototype);
const value = fn.apply(newObj,args);
return value instanceof Object ? value : newObj;
}
为什么 0.1 + 0.2 != 0.3?如何解决这个问题?
- 因为精度问题导致的,解决方法如下:
parseFloat((0.1 + 0.2).toFixed(10)) === 0.3 // true
说一说浏览器垃圾回收机制
- 浏览器垃圾回收机制有好几种方案,之前大部分浏览器采用标记清理,还有一部分使用引用计数。V8新生代算法把内内存空间分为两部分:
From
和to
空间,这两个空间必定有一个是空的,当一个空间满了以后,就会检查当前空间存活的对象放到另外一个空间。
什么是防抖?什么是节流?
- 防抖:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
function debounce(fn,wait){
let timer=null;
return function(){
clearTimeout(timer);
timer=setTimeout(function(){
fn.apply(this)
},wait)
}
}
document.getElementById('btn').onclick=debounce(function(){console.log('触发'+Date.now());},1000)
- 节流:规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
function throttle(fn,wait){
// 记录上一次函数执行的时间
var lastTime=0;
return function(){
// 现在时间
var nowTime=new Date();
if(nowTime-lastTime>wait){
fn.call(this);
lastTime=nowTime;
}
}
};
document.onscroll=throttle(function(){console.log('触发'+Date.now());},1000)
Vue
谈一谈
Vue
的生命周期,在哪个周期可以获取DOM
?平时获取数据可以在哪个生命周期执行?
-
简单来说,
Vue
的生命周期可以归为3类,创建阶段、运行阶段、销毁阶段。 -
创建阶段
-
beforeCreate:实例刚在内存中创建出来,还没有初始化 data和 methods,只包含一些自带额生命周期函数。
-
created:实例已经在内存中创建完成,此时data和methods已经创建完成。
-
beforeMount:此时已经编译模版,但没有渲染到页面中。
-
mounted:渲染模版,创建阶段到此结束。这时候可以操作dom。
-
-
运行阶段
-
beforeUpdate:界面中的数据还是旧的,但是data数据已经更新,页面中和data还没有同步。修改data数据就会触发这个函数。
-
updated:页面重新渲染完毕,页面中的数据和data保持一致。修改data数据就会触发这个函数。
-
-
销毁阶段
-
beforeDestroy:执行该方法的时候,Vue的生命周期已经进入销毁阶段,但是实例上的各种数据还出于可用状态。
-
destroyed:组件已经全部销毁,Vue实例已经被销毁,Vue中的任何数据都不可用
-
-
keep-alive
-
activited:keep-alive 专属,组件被激活时调用
-
deactivated:keep-alive 专属,组件被销毁时调用
-
组件如何进行通信?
-
父子组件
-
props/$emit
:父组件通过props
来给子组件传递数据,子组件可以通过$emit
发送事件给父组件。但这种父子直接传递数据是单向数据流 -
$$parent/$children
:通过$parent
或$children
就可以访问组件的实例 -
ref/refs
:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例,可以通过实例直接调用组件的方法或访问数据
-
-
兄弟组件
this.$parent.$children
:在$children
中可以通过组件name
查询到需要的组件实例。
-
任意组件
Vuex
Event Bus
:eventBus
又称为事件总线,在vue中可以使用它来作为沟通桥梁的概念, 就像是所有组件共用相同的事件中心,可以向该中心注册发送事件或接收事件, 所以组件都可以通知其他组件。eventBus
也有不方便之处, 当项目较大,就容易造成难以维护的灾难。
vue2双向绑定的原理是什么?vue3和vue2双向绑定有什么区别?
- vue2是采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。Object.defineProperty()只能对属性进行数据劫持,不能对整个对象进行劫持,同理无法对数组进行劫持。vue3中则采用Proxy,它可以监听到数组内的数据变化。
为什么 Vue 组件中 data 必须是一个函数?
- 如果 data 是一个对象,当复用组件时,因为 data 都会指向同一个引用类型地址,其中一个组件的 data 一旦发生修改,则其他重用的组件中的 data 也会被一并修改。
如果 data 是一个返回对象的函数,因为每次重用组件时返回的都是一个新对象,引用地址不同,便不会出现如上问题。
Vue 中 computed 和 watch 有什么区别?
-
计算属性
computed
:
(1)支持缓存,只有依赖数据发生变化时,才会重新进行计算函数;
(2)计算属性内不支持异步操作;
(3)计算属性的函数中都有一个 get(默认具有,获取计算属性)和 set(手动添加,设置计算属性)方法;
(4)计算属性是自动监听依赖值的变化,从而动态返回内容。 -
侦听属性
watch
:
(1) 不支持缓存,只要数据发生变化,就会执行侦听函数;
(2) 侦听属性内支持异步操作;
(3) 侦听属性的值可以是一个对象,接收 handler 回调,deep,immediate 三个属性;
(3) 监听是一个过程,在监听的值变化时,可以触发一个回调,并做一些其他事情。
vuex 都有哪些部分组成?
- state:用来存储数据
- Getter:用来获取
state
中的值 - Mutation:唯一可以改变
state
中的值,且必须是同步函数 - Action:用于提交
mutation
,而不是直接变更状态,可以包含任意异步操作 - Module:许将单一的
Store
拆分为多个store
且同时保存在单一的状态树中。
浏览器相关
输入URL到页面渲染中都发生了什么?
1.URL 解析
2.DNS 查询
3.TCP 连接
4.处理请求
5.接受响应
6.渲染页面