前端面试题

1. script标签的使用,defer属性

script标签有以下属性:

  1. src:可选,链接外部文件
  2. type :用script元素嵌入js代码记得要加type="text/javascript"
<script src="" type="text/javascript" charset="utf-8"></script>
  1. charset:字符编码属性,可选。默认是utf-8编码,主要表示通过src属性指定的代码的字符集,大多浏览器会忽略它的值,所以不必使用。
  2. language:脚本类型属性,不是标准组成的一部分,已废弃。大多数浏览器会忽略这个属性,已没必要使用。
  3. defer:如果script标签设置了该属性,则浏览器会异步的下载该文件并且不会影响到后续DOM的渲染;如果有多个设置了defer的script标签存在,则会按照顺序执行所有的script。defer脚本会在文档渲染完毕后,DOMContentLoaded事件调用前执行。
  4. async
    async的设置,会使得script脚本异步的加载并在允许的情况下执行
    async的执行,并不会按着script在页面中的顺序来执行,而是谁先加载完谁执行。
    注意:defer和async的区别
    • defer和async都属于异步加载, defer会比async稳定。
    • defer是延迟执行(推迟解释,当前html页面解析完成后执行)js,async是当前js文件加载完成后执行js。
    • async要和src属性配合使用。因为只对外部脚本起作用,如果你是在script标签里面书写脚本,该脚本是不会异步加载!!!
    • defer属性,表示延迟执行,具体意思是当页面解析和显示之后再执行。这个属性也是针对外部属性才起作用。
      异步脚本一定会在页面的load事件前执行完毕,但是可能会在DOMContentLoaded事件触发之前或者之后执行。

2.行内元素和块元素有哪些?区别是什么?

1. 区别
  1. 盒模型:块级元素会生成一个独立的矩形框,它会占据一整行的宽度,可以设置宽度、高度、边距和填充等属性。而行内元素则不会产生独立的框,它的宽度和高度由内容决定,无法直接设置宽度和高度
  2. 排列方式:块级元素会自上而下按顺序排列,每个块级元素独占一行。而行内元素则会在同一行上水平排列,直到一行放不下才会换行。
  3. 内容显示:块级元素可以包含其他块级元素和行内元素,并且可以设置内部元素的布局和样式。行内元素一般不能包含块级元素,只能包含文本或其他行内元素
  4. 相对位置:块级元素具有明显的边界,可以使用CSS定位属性(如position、top、left)来控制其相对位置。而行内元素通常不能设置这些属性,它们会根据文本流布局自动调整位置。
  5. 默认尺寸:块级元素的默认宽度是100%,会占满父元素可用空间。行内元素的默认宽度由内容决定,一般只占据内容所需的宽度。
  6. 行内元素、块级元素相互转换:
display: inline; // 行内元素
display: block; // 块元素
display: inline-block; // 行内块元素
2.常见的块元素和行内元素
  1. 常见块元素
    <div><p><h1>-<h6><ul><ol><li><table><form>
  2. 常见行内元素
    <span><a><strong><em><img>、、<button>

3.如果想要人名、头像、以及搜索框在同一行显示,并且对齐怎么布局?

我回答的是:将三个元素分别放在<li>标签里面,然后使用float;或者将三个元素都放在<div>标签里面,然后使用flex布局。

4.讲一下promise

从语法上说,Promise是一个构造函数;
从功能上说,Promise对象用来封装一个异步操作并可以获取其成功/失败的结果值。

5.讲一下箭头函数、以及箭头函数的this

箭头函数本身并无this,箭头函数的this由定义箭头函数时所处的作用域决定,即箭头函数的this永远指向定义箭头函数时所在的作用域的this(也可以说是上层作用域,强调的是作用域!)。箭头函数的this只和定义时的作用域this有关,和调用者无关,和调用环境无关,也永远不会改变(因此不能使用call\apply\bind改变箭头函数的this指向)。
MDN的解释:箭头函数不会创建自己的this,所以它没有自己的this,它只会从自己的作用域链的上一层继承this。

6.讲一下改变this指向的方法有哪些?

  1. Function.prototype.call(this.Arg,val1,val2, …)调用函数执行,在函数执行时将函数体中的this指向修改为thisArg所表示的对象。
  2. Function.prototype.apply(thisArg, array|arguments)调用函数执行,在函数执行时将函数体中的this指向修改为thisArg所表示的对象,array|arguments 表示调用函数的参数列表,使用数组或类数组的格式。
  3. Function.prototype.bind(thisArg) 能够返回一个新函数,该新函数的主体与原函数主体一致,但当新函数被调用执行时,函数体中的this指向的是thisArg所表示的对象。

7.讲一下原型链

原型链是JavaScript中实现继承和属性共享的机制。每个对象都有一个原型,通过原型链的关联,我们可以在对象之间共享属性和方法。当访问一个对象的属性或方法时,JavaScript会自动在原型链上查找,直到找到或者到达原型链的顶端。

8.讲一下路由懒加载的实现原理(原生JS和vue实现)

将路由相关的组件,不再直接导入了,而是改写成异步组件的写法,只有当函数被调用的时候,才去加载对应的组件内容。

9.原生Ajax怎么使用?

btn.onclick = function() {
    // 1. 创建对象
    const xhr = new XMLHttpRequest();
    // 2. 初始化,设置请求方法和URL
    xhr.open('GET', 'http://127.0.0.1:8000/server?a=100&b=200&c=300'); // 后面直接设置参数 a b c
    // 3. 发送
    xhr.send();
    // 4. 事件绑定,处理服务端返回的结果
    // readyState 是 xhr 对象中的属性,表示状态 0 1 2 3 4
    xhr.onreadystatechange = function() {
                // (判断)服务端返回了所有的结果
                if (xhr.readyState === 4) {
                    // 判断响应状态码 200 404 403 401 500
                    // 2xx 都表示成功
                    if (xhr.status >= 200 && xhr.status < 300) {
                        // 处理结果 行 头 空行 体
                        // (1) 响应行
                        // console.log(xhr.status); // 状态码
                        // console.log(xhr.statusText); // 状态字符串
                        // console.log(xhr.getAllResponseHeaders()); // 所有响应头
                        // console.log(xhr.response); // 响应体
                        // (2) 设置 div 里面的文本
                        div.innerHTML = xhr.response;
                    }
                }
            }
}

10.一个盒子怎么实现页面居中?

  1. 定位+margin
  2. 定位+transform
  3. flex布局
  4. grid布局
  5. table布局

11.vue项目中在本地执行npm run serve后,都发生了什么?

12.口述一个简单的算法题:要走n级台阶,一次可以走1阶、也可以走2阶,问走完n阶总共有几种方法

/**
 1级 1
 2级 2  1+1,2
 3级 3  1+1+1,1+2,2+1
 4级 5  1+1+1+1,2+2,2+1+1,1+2+1,1+1+2
 5级 8  1+1+1+1+1,1+2+2,2+2+1,2+1+2,1+1+2+1,1+2+1+1,2+1+1+1,1+1+1+2
 f(n) = f(n-1) + f(n-2)
*/
function fn(n) {
  if (n == 1 || n === 2) {
    return n;
  }
  return fn(n - 1) + fn(n - 2);
}
let count = 3;
while (count > 0) {
  let n = prompt('请输入一个整数(>0):');
  n = parseInt(n);
  alert(`共有${fn(n)}种方法`);
  count--;
}

13.怎么比较两个变量的值是否相等?

比较基本数据类型:

  1. ==:只判断值是否相等
  2. ===:判断值和类型是否相等

14.说一说三次握手,为什么是三次握手?两次行不行?

1. 什么是三次握手
  • 第一次握手(SYN):客户端向服务器发送SYN包,请求建立连接。该包中包含一个随机生成的初始序列号ISN(Initial Sequence Number)。
  • 第二次握手(SYN+ACK):服务器收到SYN包后,向客户端发送SYN+ACK包,表示同意建立连接。该包中也包含一个随机生成的序列号ISN,同时将确认序列号ACK设置为客户端的ISN+1。
  • 第三次握手(ACK):客户端收到服务器的SYN+ACK包后,向服务器发送ACK包,表示客户端也同意建立连接。该包的序列号设置为服务器的ISN+1,确认序列号设置为服务器的ISN+1。
  • 在三次握手完成后,TCP连接建立成功,双方可以开始进行数据传输。这个过程可以确保连接的可靠性和完整性,防止数据包的丢失或重复传输。
2.为什么是三次握手?两次行不行?
  1. 防止已过期的连接请求报文突然又传送到服务器,因而产生错误。
    在双方两次握手即可建立连接的情况下,假设客户端发送 A 报文段请求建立连接,由于网络原因造成 A 暂时无法到达服务器,服务器接收不到请求报文段就不会返回确认报文段,客户端在长时间得不到应答的情况下重新发送请求报文段 B,这次 B 顺利到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,客户端在收到 确认报文后也进入 ESTABLISHED 状态,双方建立连接并传输数据,之后正常断开连接。此时姗姗来迟的 A 报文段才到达服务器,服务器随即返回确认报文并进入 ESTABLISHED 状态,但是已经进入 CLOSED 状态的客户端无法再接受确认报文段,更无法进入 ESTABLISHED 状态,这将导致服务器长时间单方面等待,造成资源浪费。
  2. 三次握手才能让双方均确认自己和对方的发送和接收能力都正常
  • 第一次握手:客户端只是发送处请求报文段,什么都无法确认,而服务器可以确认自己的接收能力和对方的发送能力正常;
  • 第二次握手:客户端可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常;
  • 第三次握手:服务器可以确认自己发送能力和接收能力正常,对方发送能力和接收能力正常;
    可见三次握手才能让双方都确认自己和对方的发送和接收能力全部正常,这样就可以愉快地进行通信了。
  1. 告知对方自己的初始序号值,并确认收到对方的初始序号值
    TCP 实现了可靠的数据传输,原因之一就是 TCP 报文段中维护了序号字段和确认序号字段,也就是图中的 seq 和 ack,通过这两个字段双方都可以知道在自己发出的数据中,哪些是已经被对方确认接收的。这两个字段的值会在初始序号值得基础递增,如果是两次握手,只有发起方的初始序号可以得到确认,而另一方的初始序号则得不到确认。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值