面试宝典(持续更新)

149 阅读5分钟

1.怎么快速实现居中(上下左右居中)

给父元素dispaly flex  给子元素 margin:auto

2.padding,margin有什么区别

作用对象不同,padding作用于自身,margin作用于外部元素,设置box-sizing border-box可以看的出来

3.百分比和vw有什么区别

百分比相对于是的父元素,有继承关系
vw相对于是这个视口,无继承关系

4.行内元素和块级元素的区别

行内:不换行,不可以设置大小,大小由内容决定
块级:有继承关系

5.使用小字体

使用C3属性 
transform: scale(0.8)  
-webkit-transform: scale(0.8)

6.let var

全局污染,作用域,变量提升,重复声明

7.深浅copy

对于基本类型
string number null undefined boolean
深浅一样  不影响其他数据
比如 
let a = 2  
let b = a
b = 4
console.log(a)  // 2
console.log(b)  // 4
其实上述是赋值

对于复杂类型
object array

浅拷贝(藕断丝连)
let arr = [1,2,3,4]
let newArr = arr
newArr.push("111111111")
console.log(newArr)  // [1, 2, 3, 4, '111111111']
console.log(arr)     // [1, 2, 3, 4, '111111111']

深拷贝(一刀两断)
let arr = [1,2,3,4]

let newArr = JSON.parse(JSON.stringify(arr)) 真正的深拷贝80% 原因不能转 function
let newArr = [...arr]   解构赋值,只作用于一维才是深拷贝,多维不是深拷贝

newArr.push("111111111")
console.log(newArr)  // [1, 2, 3, 4, '111111111']
console.log(arr)     // [1, 2, 3, 4]

标准的深拷贝
// deepCopy
function deepClone(source) {
  // [].constructor => Array
  // {}.constructor => Object
  const targetObj = source.constructor === Array ? [] : {};
  // for in 可以对数组 也可以对对象
  for (let keys in source) {
    // 判断是否存在keys,有值处理
    if (source.hasOwnProperty(keys)) {
      // keys 有3种情况  基础数据 数组 对象
      // typeof 函数   是function
      if (source[keys] && typeof source[keys] === "object") {
        // typeof 数组或者对象,都是object
        targetObj[keys] = source[keys].constructor === Array ? [] : {};
        targetObj[keys] = deepClone(source[keys])
      } else {
        targetObj[keys] = source[keys];
      }
    }
  }
  return targetObj;
}

8.在网址输入URL,做了什么

https://wwww.bai.com   
https      传输协议(http和tcp之间加了一层 TSL 或者 SSL 的安全层)
wwww       服务器,万维网
bai.com    域名

1.当用户输入网址之后,浏览器会到DNS的域名系统中查找对应的IP,而网址和IP是映射关系的
2.拿到网址对应的IP,浏览器就会和服务器建立连接,俗称TCP三次握手
3.三次握手建立完成连接后,会渲染数据到页面上
4.数据渲染完成,就断开连接,俗称四次挥手

所以这次连接并不是可持续的,而是服务器给客服端建立完成并返回数据后就会断开
如果需要持续的连接,需要使用websocket进行完成


从第3步拆分,HTML,CSS怎么渲染在页面上的

image.png

image.png

9.前端的性能优化

加载性能优化
1.减少http请求(精灵图,文件的合并)
2.减小文件大小(资源压缩,图片压缩,代码压缩)
3.CDN (第三方库,大文件,大图)
4.SSR服务端渲染,预渲染
5.懒加载
6.分包

减少dom操作,避免回流,文档碎片

避免大量的dom操作,可以用定位或者tranform tranlate进行操作,避免回流问题
因为定位或者tranform tranlate的时候会脱离正常文档流,即使上下移动,正常文档流的数据也不会改变

内存占用:内存占用过大,超出浏览器的内存范围,会导致浏览器直接崩溃
例:一般是用在实时传输的websocket上,浏览器一直接受服务器的资源,当之前的资源没有及时释放并且超出浏览器
的内存范围,浏览器会直接卡死

image.png

10.图片来加载

<!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>Document</title>
</head>
<style>
    img {
        display: block;
        margin-bottom: 50xp;
        width: 400px;
        height: 400px;
    }
</style>

<body>
    <div>
        <img src="./wechatAva.jpg" data-src="./1.jpg" alt="">
        <img src="./wechatAva.jpg" data-src="./2.jpg" alt="">
        <img src="./wechatAva.jpg" data-src="./3.jpg" alt="">
        <img src="./wechatAva.jpg" data-src="./4.jpg" alt="">
        <img src="./wechatAva.jpg" data-src="./5.png" alt="">
        <img src="./wechatAva.jpg" data-src="./6.jpg" alt="">
        <img src="./wechatAva.jpg" data-src="./7.jpg" alt="">
        <img src="./wechatAva.jpg" data-src="./8.jpg" alt="">
        <img src="./wechatAva.jpg" data-src="./9.png" alt="">
    </div>

    <script>

        let num = document.getElementsByTagName('img').length
        let img = document.getElementsByTagName('img')
        let n = 0

        lazyLoad()
        window.onscroll = lazyLoad

        function lazyLoad() {
            let seeHeight = document.documentElement.clientHeight
            let scrollTop = document.documentElement.scrollTop || document.body.scrollTop

            for (let i = n; i < num; i++) {
                if (img[i].offsetTop < scrollTop + seeHeight) {
                    if (img[i].getAttribute('src') == './wechatAva.jpg') {
                        img[i].src = img[i].getAttribute('data-src')
                    }
                }
            }
        }

    </script>
</body>

</html>

解释:
img的src和data-src的区别
src          是一个简写,如果img属性上没有data-src, src属性就会做为data-src
data-src     是真正图片源的地址,一般配合src进行使用,src作为loading,而data-src作为真实的图片源地址

11.this指向

console.log(this);  //window

function a (){
  console.log(this);  //调用者
}

let a = {
    b: 10,
    k: {
        b: 29,
        fn: function () {
            console.log(this);
        }
    }

}

a.k.fn()   // 指向k,指向上级调用者

12.闭包

什么是闭包
定义:一个函数中调用另一个函数

为什么要有闭包
答:数据私隐性,避免全局污染,保存变量(长住内存)

应用
防抖,节流,封装dom

13.new关键字

let obj1 = Object.create(null)
let obj2 = {}

区别在于是否存在原型以及原型链

let obj = new Object()
1.创建空对象
let person = new Person()   // 基类

2.更改原型链
person.__proto__ = Person.prototype

3.修改this指向
let res = Person.call(person)

4.判断返回值类型
if( typeof res == 'object' ){
    person = res
}else{
    person = obj
}

14.事件委托

1.解决动态创建点击事件的问题,用父元素进行代理委托

<!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>Document</title>
</head>

<body>
    <ul id="ul">
        <li>0</li>
        <li>1</li>
        <li>2</li>
        <li>3</li>
    </ul>

    <button id="btn">add li</button>
    <script>
        // 事件委托
        let ul = document.getElementById("ul");
        ul.onclick = function (event) {
            event = event || window.event
            let target = event.target
            if (target.nodeName == "LI") {
                console.log(target.innerHTML);
            }
        }

        let btn = document.getElementById("btn");
        btn.onclick = function (event) {
            let li = document.createElement("li")
            li.innerHTML = ul.children.length
            ul.appendChild(li)
        }
    </script>
</body>
</html>

15.vue中的V-model实现

简易实现v-model的功能,但是不知道通知,没有watcher

<!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>Document</title>
</head>

<body>

    <input type="text" id="username">
    <br>
    值显示:<span id="Uname"></span>

    <script>
        const uInput = document.getElementById('username')
        const Uname = document.getElementById('Uname')

        uInput.addEventListener('input',e=>{
            Uname.innerHTML  =  e.target.value
        },false)

    </script>
</body>
</html>
通过 Object.defineProperty 去触发 set,相当于有通知 watcher

<!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>Document</title>
</head>

<body>

    <input type="text" id="username">
    <br>
    值显示:<span id="Uname"></span>

    <script>

        let obj = {}

        Object.defineProperty(obj,'username',{
            get(){
                console.log("1");
            },
            set(value){
                document.getElementById('Uname').innerHTML = value;
            }
        })

        const uInput = document.getElementById('username')

        uInput.addEventListener('keyup',e=>{
            obj.username = e.target.value
        },false)

    </script>

</body>
</html>

16.render()函数和template的异同点

相同点:render() 函数和 template模板 都是属于 类编译器 并不是真实的编译器
不同点:template编译的是模板,使用的模板语法,并不是真实显示在dom里面的,而render()函数是template的下一步,通过解
析template的语法,把template的内容显示在真正的dom上(rander函数会根据template创建真实的dom节点)

但是Vue3中不建议直接书写render()函数,因为会跳过编译器优化。

17.vue的渲染过程

简化:template => render() h => 原生JS的createElement() => 创建真实元素(一般是标签) => 生成虚拟dom => 真实dom

image.png

18.vue中的jsx

<script>
export default {
    // 接收父组件传来的值
    props:{
        type:{
            type: String,
            default:'normal'
        },
        text:{
            type: String,
            default:''
        }
    },
    // 使用render函数进行jsx的模板
    // h   createElement
    render(h) {
        return h('button', {
            // 对 button 进行添加类名 
            // 相当于 :class=" type === 'success' ? 'successType' : 'normal'"
            class:{
                btn:true,
                'successType' : this.type === 'success',
                'errorType' : this.type === 'error',
                'normalType' : !this.type,
            },
            // dom属性
            // document.getElementById('').innerText
            domProps: {
                innerText:  this.text
            },
            // 绑定事件
            // 相当于 v-on
            on: {
                  click:(e)=>{
                    console.log(e);
                }
            }
        })
    },
};
</script>