基础

Posted by Chouvel on November 19, 2024

防抖: slice. 手写一个深拷贝:

HTMl-CSS

HTML的标签有哪些,行内,块有哪些,区别。

h5新特性的作者| h5新特性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
1、标题:h1~h6

2、段落:p

3、HTML 文本格式化标签:b,strong,i,em,s,del,u,sup,sub,hr,行内

4、HTML 中的特殊符号:`<`,`>`,` `,`©`,`™`,`®`

5、区:div(块) 和 span(行内)

6、列表:ol + li,ul + li,dl + dt + dd

7、图片:img,行内

8、超链接:a,行内

9、HTML 表格:table,caption,th,tr,td

10、HTML 表单:form,input,label,select + option,button

11、框架 iframe

12. 语义化标签:增加了一套新的语义化元素
13. audio和ideo标签

windows下面有那些属性或者方法

  1. dom(document,文档对象模型)
  2. bom(browser object model)浏览器对象模型
    • window.open,window.close()
    • location
    • history;length,back,forward,go
    • screen
    • navigator(浏览器的信息,各种方法)
    • frames
    • settimeout,setinterval
    • addEventListener,removeEvenListener

css的布局知道哪些,flexbox。

flexbox:给元素设置display:flex,则可以将盒子转变成flexbox。可以通过flex-direction改变指向,flex-warp:warp确定是否换行,flex属性有三个参数,分别是flex-grow,flex-shrink,flex-base。还可以通过order属性来控制每个flexitem的显示。

在子元素上可以使用flex来设置浮动的 display:flex。

css的选择器有哪些

id,类,标签 我会使用scss这个css框架进行开发,这类sass的语言写法支持css 的嵌套,编译得到的选择器,是

  1. 后代选择器(#box div),选择id为box元素内部所有的div元素
  2. 子选择器(.one>one_1),选择父元素为.one的所有.one_1的元素。这个只选择一层,不会深入

Css预编译语言有这几个重要的特性:、

  1. 变量
  2. 混入(mixin) Sass声明 mixins时需要使用 @mixinn,后面紧跟 mixin的名,也可以设置参数,参数名为变量 $声明的形式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
@mixin large-text {
  font: {
    family: Arial;
    size: 20px;
    weight: bold;
  }
  color: #ff0000;
}

.page-title {
  @include large-text;
  padding: 4px;
  margin-top: 10px;

高级技巧。

WeakSet和WeakMap都是弱引用 弱引用是不能确保其引用的对象不会被垃圾回收器回收的引用,而强引用是确保其引用的对象不会被垃圾回收器回收的引用。

  1. 其他

对数组的遍历大家最常用的就是for循环,ES5的话也可以使用forEach,ES5具有遍历数组功能的还有map、filter、some、every、reduce、reduceRight等,只不过他们的返回结果不一样。但是使用foreach遍历数组的话,使用break不能中断循环,使用return也不能返回到外层函数。

项目优化

  1. 封装了那些组件,实现了那些功能

Vue

vue的典型特征是

  1. 数据驱动
  2. 组件化
  3. 指令
  • 没有指令之前,我们操作dom是先使用document来获取dom,再进行后续操作。
  • 有了指令以后,就可以直接在标签上写对应的方法了v-on(@),以及绑定对应的响应式数据v-bind(:)
  • 条件渲染指令 v-if
  • 列表渲染指令 v-for,在 v-for 的时候,建议设置 key值,并且保证每个 key值是独一无二的,这便于 diff算法进行优化

c1:vue3和vue2 的区别。

  1. vue3:更快,更小。更好的typescript支持,使用proxy代替vue2的Object.defineProperty。
  2. 引入了组合式api,仍然支持选项式api。
  3. v-for的优先级高于v-if。

c2:watch和computed的区别:

watch

watch 是观察者,它允许你指定一个选项来监听Vue实例上的数据或计算属性。当被监听的数据发生变化时,可以执行一些操作。watch 的特性如下:

  • 非缓存性:每次被监听的数据变化时,都会执行对应的函数。
  • 异步性:在Vue 3中,watch 的默认行为是异步的,这意味着监听的数据变化不会立即触发回调函数,而是在下一个微任务中执行。

computed

computed 是计算属性,它们是依赖于Vue实例的数据的。当依赖的数据发生变化时,计算属性会自动重新计算。computed 的特性如下:

  • 缓存性:只有当依赖的响应式数据发生变化时,计算属性才会重新计算。这意味着如果计算属性的依赖没有变化,访问计算属性将立即返回之前的计算结果,而不必再次执行计算。
  • 响应式:计算属性是基于它们的依赖进行缓存的。如果依赖项之一发生变化,计算属性将重新计算。
  • 依赖收集:对于 computed 属性,Vue会遍历它们并为每个属性创建一个依赖收集器(Dep)实例。依赖收集器负责管理该属性的依赖关系。

vue的响应式原理

vue在为data设置响应式,通过Onject.definePropoty(vue2.x)或者Proxy(vue3.x)。之后,为computer中依赖的数据添加监听。

vue的NextTick这个api

nexttick这个api是用来实现在

计算机网络

http和https的区别,tcp和udp的区别。

TCP 是面向连接的协议,建立连接3次握手、断开连接四次挥手,UDP是面向无连接,数据传输前后不连接连接,发送端只负责将数据发送到网络,接收端从消息队列读取。

UDPTCP两者的都位于传输层

性质层面

tcp是可靠的,udp不可靠。

tcp是面向连接的,需要三次握手。

tcp是全双工的,udp则可以一对一,一对多,多对一,对对多等等。

tcp的报文头是20个字节,而udp只有8个字节,传输开销小。

应用层面

TCP 应用场景适用于对效率要求低,对准确性要求高。

udp可以在直播,视频里面使用。

讲一下tcp三次握手

上述每一次握手的作用如下:

  • 第一次握手:客户端发送网络包,服务端收到了 这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
  • 第二次握手:服务端发包,客户端收到了 这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常
  • 第三次握手:客户端发包,服务端收到了。 这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常

通过三次握手,就能确定双方的接收和发送能力是正常的。之后就可以正常通信了

为什么不是两次握手?

如果是两次握手,发送端可以确定自己发送的信息能对方能收到,也能确定对方发的包自己能收到,但接收端只能确定对方发的包自己能收到 无法确定自己发的包对方能收到

并且两次握手的话, 客户端有可能因为网络阻塞等原因会发送多个请求报文,延时到达的请求又会与服务器建立连接,浪费掉许多服务器的资源

get和post的区别

  1. get和post最主要的区别是get的请求体为空。post通常使用来客户端发送数据给服务端(我的浅薄理解)。
  2. get是幂等的,post是非幂等的。

JavaScript

实现数组去重

  1. 利用set的特性,不重复来实现。
1
2
3
const arr = [1, 2, 3, 1, 2, 3, 1, 1] 
const newArr = [...new Set(arr)]
console.log(newArr);
  1. 使用indexOf返回的下标来去重。
1
2
3
4
5
const arr = [1,2,3,3,3,3,4]
const newArr = []
newArr.filter((item,index) => {
    return arr.indexOf(item) === index
})
  1. 不使用数据结构以及js特有的api实现去重。
1
2
3
4
5
6
7
8
9
10
let i; let j; let len = arr.length
for (i = 0; i < len; i++) {
   for (j = i + 1; j < len; j++) {
      if (arr[i] === arr[j]) {
        arr.splice(j, 1)
        len--
        j--
      }
   }
}

for. of 和for . in 的区别

for in 应用于数组循环返回的是数组的下标 、属性原型上的方法和属性,而for in应用于对象循环返回的是对象的属性名和原型中的方法和属性。

for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值。 所以for in更适合遍历对象,不要使用for in遍历数组。

数组的方法

增删改差等操作

  1. push,unshift,splice(粘合),concat
  2. pop,shift,splice,slice
  3. splice
  4. indexOf,inclulds,find ;排序
  5. reverse,sort ;转换
  6. join ,迭代的等。
  7. forEach,map,sort,filter,every,some

隐式转化/显示转换

显示转换,即我们很清楚可以看到这里发生了类型的转变,常见的方法有:

  • Number()
  • parseInt()
  • String()
  • Boolean()

在隐式转换中,我们可能最大的疑惑是 :何时发生隐式转换?

我们这里可以归纳为两种情况发生隐式转换的场景:

  • 比较运算(==!=><)、ifwhile需要布尔值地方
  • 算术运算(+-*/%

除了上面的场景,还要求运算符两边的操作数不是同一类型

自动转换为布尔值

在需要布尔值的地方,就会将非布尔值的参数自动转为布尔值,系统内部会调用 Boolean函数

可以得出个小结:

  • undefined
  • null
  • false
  • +0
  • -0
  • NaN
  • ""

除了上面几种会被转化成 false,其他都会被转化成 true

原型链

面试官又追问, var a = new A(),a 和 A 的关系,A 和 Function 的关系

a 是 A 的一个实例对象,a 的 __proto__ 指向 A 的 prototype,A 的 __proto__ 指向 Function 的 prototype

作用域

作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合

换句话说,作用域决定了代码区块中变量和其他资源的可见性 我们一般将作用域分成:

  • 全局作用域
  • 函数作用域
  • 块级作用域

我们写好代码时它的作用域就确定了,JavaScript 遵循的就是词法作用域,也叫静态作用域。

实现水平居中的方式

  1. 利用flexbox的方法,父元素创建flexbox;
  2. 子元素的height = lineheight。

实现对给定对象数组,找到其中id为1的所有元素。

1
2
3
4
5
6
arr = [{id:1,code:23},{id:2,code:989}]
function(arr){
    if(arr instanceofof Array === false) return;
  
  
}

判断数据类型

  1. typeof 判断基本数据类型
  2. instanceof 判断复杂数据类型;这种方法是利用左边对象的propotype
  3. Object.propotype.toString.call()判断所有。

事件和事件流,冒泡,捕获

事件流有多种形式,例如冒泡。 事件流分为3个阶段:

  1. 事件捕获
  2. 事件触发
  3. 事件冒泡 事件代理(事件委托)可以通过对父元素设置监听,批量对子元素进行监听。 优点:使用事件委托存在两大优点:
  • 减少整个页面所需的内存,提升整体性能
  • 动态绑定,减少重复工作 适合对click进行事件监听

Ajax

实现 Ajax异步交互需要服务器逻辑进行配合,需要完成以下步骤:

  • 创建 Ajax的核心对象 XMLHttpRequest对象
  • 通过 XMLHttpRequest 对象的 open() 方法与服务端建立连接
  • 构建请求所需的数据内容,并通过 XMLHttpRequest 对象的 send() 方法发送给服务器端
  • 设置实例对象的一个方法,这个方法有一个特性:每次进入一个新的传输阶段的时候,都会执行这个方法;知道最后传入的code变成4后,表示收到了服务服务端的回答,可以对status进行判断,在[200,300]之间表示正常,400则打印错误内容。

dom操作

document.createElement('li')

element.appendChild(element)

document.queryselect(css选择器)。

document.querySelectAll(css选择器)

js的事件循环

** 事件循环是实现js异步编程的核心方法,通过监听任务队列以及执行任务队列中的任务来实现的。 **

事件循环中的执行顺序

JavaScript 事件循环的执行顺序可以概括为:

  1. 执行所有同步代码。
  2. 执行完同步代码后,检查微任务队列,如果有微任务,按顺序执行所有微任务。
  3. 检查宏任务队列,取出队首的宏任务执行。
  4. 宏任务执行完毕后,再次检查微任务队列,如果有微任务,再次执行所有微任务。
  5. 重复步骤3和4,直到宏任务队列为空。

js的原型

在JavaScript中,每个对象都有一个内部属性([[Prototype]]) 类似于其他编程语言,例如c#,java中的继承。它们实现继承通过类,我们通过原型链。 浏览器里面通过__proto__来修改原型,在实例身上。 对象的属性和方法查找会沿着原型链向上进行。

js原型是js中实现继承和属性共享的一个js对象。

面试官又追问, var a = new A(),a 和 A 的关系,A 和 Function 的关系

a 是 A 的一个实例对象,a 的 __proto__ 指向 A 的 prototype,A 的 __proto__ 指向 Function 的 prototype

逐字稿:

"JavaScript是一种基于原型的语言,这意味着每个对象在创建时都会关联到一个原型对象。这个原型对象可以包含属性和方法,而所有引用了这个原型的对象都会共享这些属性和方法。这种机制允许我们创建可复用和可扩展的代码。

在JavaScript中,每个对象都有一个内部属性 [[Prototype]],它指向其原型。当我们尝试访问一个对象的属性或方法时,如果该属性或方法在对象本身上不存在,JavaScript引擎就会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的末端。

开发者可以通过 __proto__属性或者 Object.getPrototypeOf()方法来访问一个对象的原型。同样,我们可以使用 Object.setPrototypeOf()方法来修改一个对象的原型。

例如,当你创建一个数组并调用 .push方法时,这个方法实际上定义在数组的原型上。这就是原型链的威力,它允许我们在整个对象类型中共享方法。"

js的闭包

注意:这里需要结合静态作用域来描述 js它采用的是静态作用域:函数能访问哪些东西,在你定义的时候就确定好了 创建一个函数的时候,这个一个函数能够记住它创建时的词法作用域,即使该函数在其原始作用域之外被执行。

使用场景:

  1. 数据封装和隐私: 闭包可以用来创建私有变量,这些变量不能从外部函数直接访问。
  2. vue的响应式原理利用到了闭包

几个大的概念:静态作用域(词法作用域)js采用动态作用域

每一个函数创建之初,都会创建一个闭包。

柯里化函数

柯里化的目的在于避免频繁调用具有相同参数函数的同时,又能够轻松的重用

1
2
3
4
5
6
7
8
9
10
11
12
13
// 我们可以使用闭包柯里化这个计算面积的函数
function getArea(width) {
    return height => {
        return width * height
    }
}

const getTenWidthArea = getArea(10)
// 之后碰到宽度为10的长方形就可以这样计算面积
const area1 = getTenWidthArea(20)

// 而且如果遇到宽度偶尔变化也可以轻松复用
const getTwentyWidthArea = getArea(20)

从代码中可以发现,箭头函数同样存在闭包。

逐字稿:

"闭包是一个函数和其周围的状态(词法环境)的组合。在JavaScript中,函数总是能够访问它们在哪里被创建的作用域,即使它们在那个作用域之外被调用。这就是所谓的词法作用域,它是在函数定义时决定的。

闭包的主要特点是它们可以捕获外部函数的变量,即使外部函数已经执行完毕。这意味着闭包可以存储和操作那些在函数外部定义的变量,这为数据封装和创建私有变量提供了一种机制。

例如,当我们在函数内部定义另一个函数,并在外部函数执行完毕后返回这个内部函数时,就创建了一个闭包。这个内部函数可以访问外部函数的变量,即使外部函数已经不在其作用域内。

闭包在许多现代JavaScript应用程序中都有广泛的应用,包括数据封装、模块模式实现、和一些库和框架的核心机制,比如Vue.js的响应式系统。"

js中的this

JavaScript 中的 this

在JavaScript中,this关键字指的是当前上下文环境中的一个对象。this的值在函数被调用时确定,它取决于函数是如何被调用的,而不是在哪里定义的。

  1. 全局上下文:在全局函数中,this通常指向全局对象(在浏览器中是 window对象)。
  2. 方法调用:当函数作为对象的方法调用时,this指向调用该方法的对象。
  3. 构造函数:在构造函数中,this指向新创建的对象。
  4. 事件处理:在事件处理函数中,this指向触发事件的对象。
  5. 箭头函数:箭头函数不绑定自己的 this,它会捕获其所在上下文的 this值。

在JavaScript中,this关键字指的是当前上下文环境中的一个对象。this的值在函数被调用时确定,它取决于函数是如何被调用的,而不是在哪里定义的。

  1. 构造函数: 在构造函数中,this 指向新创建的对象实例。

    1
    2
    3
    4
    5
    
    function Person(name) {
      this.name = name;
    }
    const person = new Person('Kimi');
    console.log(person.name); // 输出 "Kimi"
    
  2. 箭头函数: 箭头函数不绑定自己的 this,它会捕获其所在上下文的 this 值,即它引用的是封闭作用域中的 this

    1
    2
    3
    4
    5
    6
    7
    
    const obj = {
      name: 'Kimi',
      greet: () => {
        console.log(`Hello, my name is ${this.name}!`);
      }
    };
    obj.greet(); // 输出 "Hello, my name is undefined!",因为箭头函数中的 this 指向全局对象
    

事件委托和事件冒泡。

浏览器的时间默认是在事件冒泡的时候执行。 可以在addEventLislen方法的第三个参数传入false来实现在事件捕获的时候执行。 https://vue3js.cn/interview/JavaScript/event_agent.html#%E4%BA%8C%E3%80%81%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF

浏览器

浏览器渲染原理。

  1. 解析HTML,生成DOM树,解析CSS,生成CSSOM树
  2. 将DOM树和CSSOM树结合,生成渲染树(Render Tree)
  3. Layout(回流):根据生成的渲染树,进行回流(Layout),得到节点的几何信息(位置,大小)
  4. Painting(重绘):根据渲染树以及回流得到的几何信息,得到节点的绝对像素
  5. Display:将像素发送给GPU,展示在页面上。
  6. 如图:

promise使用以及一些异步任务的处理

上一次面试的问题:

js的三大(this,原型链,闭包),任务队列

1,HTML的标签有哪些,行内,快。 2,css的元素选择器知道哪些,布局:flexbox。 css选择器有哪些; 显示和隐藏一个元素的方法。,回流和重绘 https://vue3js.cn/interview/css/layout_painting.html#%E4%BA%8C%E3%80%81%E5%A6%82%E4%BD%95%E8%A7%A6%E5%8F%91

3,http和https的区别,tcp和udp的区别。 问原生。 4,

4-一些概念

回流和重绘 分片加载,瀑布加载,虚拟列表。