2021Web前端中高级面试题复盘

一、HTML基础

1.常见浏览器的内核

(1)IE: trident 内核

(2)Firefox:gecko 内核

(3)Safari: webkit 内核

(4)Opera: 以前是 presto 内核,Opera 现已改用 Google Chrome 的 Blink 内核

(5)Chrome:Blink(基于 webkit,Google 与 Opera Software 共同开发 )

2.HTML 开头Doctype的作用

html网页声明,位于文档中的最前面的位置,处于标签之前。此标签可告知浏览器文档使用
哪种 HTML 或 XHTML 规范。(重点:告诉浏览器按照何种规范解析页面

3.HTML5新特性

  1. 用于绘画canvas 元素。

  2. 用于媒介回放du的 video 和 audio 元素。

  3. 地理位置:Geolocation API访问地理位置,即通过window.navigator.geolocation来实现访问

  4. 本地离线存储localStorage 长期存储数据,浏览器关闭后数据不丢失;sessionStorage 的数据在浏览器关闭后自动删除。

  5. 语意化更好的内容元素,比如 article、footer、header、nav、section。

  6. 表单控件,calendar、date、time、email、url、search。

4.对 WEB 标准以及 W3C 的理解与认识?

标签闭合、标签小写、不乱嵌套、提高搜索机器人搜索几率、使用外链 css 和js 脚本、结构行为表现的分离、文件下载与页面速度更快、内容能被更多的用户所访问、内容能被更广泛的设备所访问、更少的代码和组件,容易维护、改版方便,不需要变动页面内容、提供打印版本而不需要复制内容、提高网站易用性。

5.HTML5 行内元素有哪些,块级元素有哪些, 空元素有哪些?

(1)行内元素

  • a - 锚点
  • img - 图片
  • input - 输入框
  • select - 项目选择
  • span - 常用内联容器,定义文本内区块

(2)块元素

  • div - 常用块级容易,也是 css layout 的主要标签
  • form - 交互表单
  • h1~h5 -标题
  • table - 表格
  • ul - 非排序列表

(3)空元素( 在 HTML[1] 元素中,没有内容的 HTML 元素被称为空元素 )

  • br 换行
  • hr 分隔线
  • input 文本框等
  • img 图片
  • link | meta 引入资源标签

6.什么是 WebGL,它有什么优点?

WebGL(全写 Web Graphics Library )是一种 3D 绘图标准,这种绘图技术标准允许把 JavaScript 和 OpenGL ES 2.0 结合在一起,通过增加 OpenGL ES 2.0 的一个 JavaScript 绑定,WebGL 可以为 HTML5 Canvas 提供硬件 3D 加速渲染,这样 Web 开发人员就可以借助系统显卡来在浏览器里更流畅地展示 3D 场景和模型了,还能创建复杂的导航和数据视觉化。显然,WebGL 技术标准免去了开发网页专用渲染插件的麻烦,可被用于创建具有复杂 3D 结构的网站页面,甚至可以用来设计 3D 网页游戏等等。
WebGL 完美地解决了现有的 Web 交互式三维动画的两个问题:

  • 第一,它通过 HTML 脚本本身实现 Web 交互式三维动画的制作,无需任何浏览器 插件支持 ;

  • 第二,它利用底层的图形硬件加速功能进行的图形渲染,是通过统一的、标准的、跨平台的 OpenGL 接口实现的。

通俗说 WebGL 是c基于anvas 绘图中的 3D 版本。因为原生的 WebGL 很复杂,我们经常会使用一些三方的库,如 three.js 、echarts等,这些库多数用于 HTML5 游戏开发。

7.cookies,sessionStorage 和localStorage 的区别?

1)Cookie

  1. 每个域名存储量比较小(各浏览器不同,大致 4K )
  2. 所有域名的存储量有限制(各浏览器不同,大致 4K )
  3. 有个数限制(各浏览器不同)
  4. 会随请求发送到服务器

2)LocalStorage

  1. 永久存储
  2. 单个域名存储量比较大(推荐 5MB ,各浏览器不同)
  3. 总体数量无限制

3)SessionStorage

  1. 只在 Session 内有效
  2. 存储量更大(推荐没有限制,但是实际上各浏览器也不同)

8.说说你对 HTML 语义化的理解?

(1)什么是 HTML 语义化?

<基本上都是围绕着几个主要的标签,像标题( H1~H6 )、列表( li )、强调( strong em )等等 >
根据内容的结构化(内容语义化),选择合适的标签(代码语义化)便于开发者阅读和写出更优雅的代码的同时让浏览器的爬虫和机器很好地解析。

(2)为什么要语义化?

  • 为了在没有 CSS 的情况下,页面也能呈现出很好地内容结构、代码结构 : 为了裸奔时好看;
  • 用户体验:例如 title、 alt用于解释名词或解释图片信息、 label 标签的活用;
  • 有利于SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息:爬虫依赖于标签来确定上下文和各个关键字的权重;
  • 方便其他设备解析(如屏幕阅读器、盲人阅读器、移动设备)以意义的方式来渲染网页;
  • 便于团队开发和维护,语义化更具可读性,是下一步网页的重要动向,遵循 W3C标准的团队都遵循这个标准,可以减少差异化。

(3) 语义化标签

 header、footer、nav、section、article、aslde、figure(媒体元素,比如一些视频,图片啊等等)

9.link 和@import 的区别?

  • 区别 1: link 是 XHTML 标签,除了加载 CSS 外,还可以定义 RSS 等其他事 务; @import 属于 CSS范畴,只能加载 CSS 。
  • 区别 2: link 引用 CSS 时,在页面载入时同时加载; @import 需要页面网页完全载入以后加载。
  • 区别 3: link 是 XHTML 标签,无兼容问题; @import 是在 CSS2.1 提出的,低版本的浏览器不支持。
  • 区别 4: link 支持使用 Javascript 控制 DOM 去改变样式;而 @import 不支 持。

二、CSS基础

1.CSS 的盒子模型

  • 标准的盒模型:width = content
  • IE 盒模型:width = content + padding + border + border

2.几种清除浮动的方法

  • 父级 div 定义 height
  • 结尾处加空 div 标签 clear:both
  • 父级 div 定义 伪类:after 和zoom(兼容ie6、7)
 #parent:after{
     
	content:" ";
	height:0;
	visibility:hidden;
	display:block;
	clear:both;
}
  • 父级 div 定义 overflow:hidden / overflow:auto

3.box-sizing 属性和用法

标准盒子模型:width +padding + border
怪异盒子模型(IE盒子模型):width + border

4.BFC (是什么,如何产生,作用)

BFC是什么

BFC(Block Formatting Context)即“块级格式化上下文

可以把 BFC 想象成一个大箱子,箱子外边的元素将不与箱子内的元素 产生作用

如何产生 BFC

当一个 HTML 元素满足下面条件的任何一点,都可以产生 Block Formatting
Context:
a、float 的值不为 none
b、overflow 的值不为 visible
c、display 的值为 table-cell, table-caption, inline-block 中的任何一个
d、position 的值不为 relative 和 static
CSS3 触发 BFC 方式则可以简单描述为:在元素定位非 static,relative 的情况下触发,float 也是一种定位方式。

BFC 的作用与特点

作用:不和浮动元素重叠,清除外部浮动,阻止浮动元素覆盖
特点:

  • float 的值不为 none。
  • overflow 的值不为 visible。
  • display 的值为 table-cell, table-caption, inline-block 中的任何一个。
  • position 的值不为 relative 和 static。

5.页面布局的方式有哪些?

  • 多栏——bootstrap栅格系统
  • 弹性——FlexBox
  • 瀑布流
  • 响应式布局
  • *流式
  • *双飞翼

三、js基础

JS 数据类型

基本类型:Number、Boolean、String、null、undefined、symbol(ES6 新增的),BigInt(ES2020)
引用类型:Object,对象子类型(Array,Function

bigint
带符号的范围是-9223372036854775808到9223372036854775807。无符号的范围是0到18446744073709551615。
int 普通大小的整数。带符号的范围是-2147483648到2147483647。无符号的范围是0到4294967295。

就是值得范围的问题,如果需要大于int的范围,就用bigint.

事件流

事件流是网页元素接收事件的顺序,"DOM2级事件"规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段、事件冒泡阶段
首先发生的事件捕获,为截获事件提供机会。然后是实际的目标接受事件。最后一个阶段是时间冒泡阶段,可以在这个阶段对事件做出响应。
虽然捕获阶段在规范中规定不允许响应事件,但是实际上还是会执行,所以有两次机会获取到目标对象。
例如:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>事件冒泡</title>
</head>
<body>
    <div>
        <p id="parEle">我是父元素    <span id="sonEle">我是子元素</span></p>
    </div>
</body>
</html>
<script type="text/javascript">
var sonEle = document.getElementById('sonEle');
var parEle = document.getElementById('parEle');

parEle.addEventListener('click', function () {
     
    alert('父级 冒泡');
}, false);
parEle.addEventListener('click', function () {
     
    alert('父级 捕获');
}, true);

sonEle.addEventListener('click', function () {
     
    alert('子级冒泡');
}, false);
sonEle.addEventListener('click', function () {
     
    alert('子级捕获');
}, true);

</script>

当容器元素及嵌套元素,即在捕获阶段又在冒泡阶段调用事件处理程序时:事件按DOM事件流的顺序执行事件处理程序:

父级捕获——>子级冒泡——>子级捕获——>父级冒泡

1.call、apply、bind三者的用法和区别

(1)三者的使用

func.call(thisArg, arg1, arg2, ...)
func.bind(thisArg, arg1, arg2, ...)
func.apply(thisArg, [arg1, arg2, ...]) 

(2)手写call()方法

Function.prototype.myCall = function(thisArg, ...args) {
     
    thisArg.fn = this              // this指向调用call的对象,即我们要改变this指向的函数
    return thisArg.fn(...args)     // 执行函数并return其执行结果
}
 
// 尝试第一个例子
function sum(num1, num2) {
     
  return num1 + num2;
}
 
function callSum(num1, num2) {
     
  return sum.myCall(this, num1, num2);
}

console.log(callSum(10, 10)); // 20

(3)手写apply()方法

Function.prototype.myApply = function(thisArg, args) {
     
    var fn = Symbol('fn');
    thisArg[fn] = this;// this指向调用apply的对象,即我们要改变this指向的函数
    return thisArg[fn](...args);    // 执行函数并return其执行结果}
 
// 尝试第一个例子
function sum(num1, num2) {
     
  return num1 + num2;
}
 
function callSum(num1, num2) {
     
  return sum.myApply(this, [num1 + num2]);
}

console.log(callSum(10, 10)); // 20

(4)手写bind()方法:语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE6~8

fn.call(obj, 1, 2); // 改变fn中的this,并且把fn立即执行 fn.bind(obj, 1, 2); //
改变fn中的this,fn并不执行

Function.prototype.myBind = function(...rest1) {
     
    var self = this
    var context = rest1.shift() // 取得第一个参数(即执行环境),并删除
    return function(...rest2) {
     
        return self.apply(context, [...rest1, ...rest2])
    }
}
 
// 测试
window.color = 'red';
var o = {
      color: 'blue' };
 
function sayColor() {
     
  console.log(this.color)
  console.log(arguments)
}
 
var objectSayColor = sayColor.myBind(o, '1', '2');
objectSayColor('3');  // 输出 "blue" 和 "1", "2", "3" 相关的数据

区别

  • 相同点:通过 apply 和 call 改变函数的 this 指向,他们两个函数的第一个参数都是一样的表示要改变指向的那个对象;
  • 不同点:第二个参数,apply 是数组,而 call 则是参数列表(arg1,arg2…这种形式)。通过 bind 改变 this 作用域会返回一个新的函数,这个函数不会马上执行。

2.闭包

闭包是指有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式:在一个函数内部创建另一个函数

一般来讲,当函数执行完毕后,局部活动对象就会被销毁,内存中仅会保存全局作用域(全局执行环境的变量对象)。但闭包则有所不同。

一个闭包的例子:

function createFunction(width, height) {
     
  return function(object) {
     
    var area = object[width] * object[height]
    return area
  }
}
 
// 创建函数
var areaFunc = createFunction('width', 'height');
// 调用函数
var area = areaFunc({
      width: 3, height: 2 }) //5

这里的 areaFunc 方法的作用域链中,包含了闭包的活动对象(arguments,object)、createFunction()的活动对象(arguments,width,height)和全局变量对象(createFunction,area)。当createFunction()的函数返回后,其执行环境的作用域链会被销毁,但它的活动对象仍然留在内存中,这时需要我们手动销毁匿名函数,以释放内存

// 解除对匿名函数的引用(释放内存)
areaFunc = null;

注:由于闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存。所以,我们最好在必要时才使用闭包。

3.Promise

(1)promise的三种状态:pending、fuulfiled/resolved、rejected
(2)catch()

catch()方法返回一个Promise,并且处理拒绝的情况。

(3)finally()

不管promise最后的状态,在执行完then或catch指定的回调函数以后,都会执行finally方法指定的回调函数。

例如:

var promise = new Promise(function(resolve, reject) {
     
    console.log("promise")
    window.setTimeout(function(){
     
      if (false){
     
        resolve('huangbiao');
      } else {
     
        debugger
        reject('error');
      }
    },1000)
  }).then(function(){
     
    console.log('success');
  }).catch(function(){
     
    console.log('catch');
  }).finally(function(){
     
    console.log('finally');
  });

(4)resolve()

Promise.resolve()用于将现有对象转换为Promise对象,从而控制异步流程为。
而立即resolve的Promise对象是在本轮“事件循环”(Event loop)的结束时,而不是在下一轮“事件循环”的开始时。

例如:

setTimeout(function () {
     
  console.log('three');
}, 0);

Promise.resolve().then(function () {
     
  console.log('two');
});

console.log('one');

// one
// two
// three

(5)reject()

Promise.reject()方法返回一个带有拒绝原因的Promise对象。

(6)all()

Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。
Promse.all在处理多个异步处理时非常有用,比如说一个页面上需要等两个或多个ajax的数据回来以后才正常显示,在此之前只显示loading图标。

//例如:
let p1 = new Promise((resolve, reject) => {
     
  resolve('成功了')
})

let p2 = new Promise((resolve, reject) => {
     
  resolve('success')
})

let p3 = Promse.reject('失败')

Promise.all([p1, p2]).then((result) => {
     
  console.log(result)               //['成功了', 'success']
}).catch((error) => {
     
  console.log(error)
})

Promise.all([p1,p3,p2]).then((result) => {
     
  console.log(result)
}).catch((error) => {
     
  console.log(error)      // 失败了,打出 '失败'
})

(7)race()

顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2,
p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

4.函数柯里化(curry)

函数柯里化,用于创建已经设置好了一个或多个参数的函数。

例如:

function add(num1, num2) {
     
  return num1 + num2;
}
 
function curriedAdd(num2) {
     
  return add(5, num2);
}
 
console.log(add(2, 3));     // 5
console.log(curriedAdd(3)); // 8

实现如下:

function curry(fn) {
     
  var args = Array.prototype.slice.call(arguments, 1); // 删除传入的function,获取其余参数
  return function() {
     
    var innerArgs = Array.prototype.slice.call(arguments); // 取得参数
    var finalArgs = args.concat(innerArgs);
    return fn.apply(null, finalArgs); // 这里不需要考虑执行环境,所以null
  }
}
 
// 测试
function add(num1, num2) {
     
  return num1 + num2;
}
 
var curriedAdd = curry(add, 5);
console.log(curriedAdd(3)); // 8
 
// 也可以第一次就直接传递完参数
var curriedAdd2 = curry(add, 5, 3);
console.log(curriedAdd2()); // 8

5.防抖和节流的区别

防抖是延迟执行,而节流是间隔执行

比如,窗口的onresize事件,我们分别使用防抖和节流,时间设为500毫秒。

  • 使用防抖:若你一直在改变窗口大小,则你的处理方法不会执行,只有你停止改变窗口大小后的500毫秒后,才会执行你的处理方法。
  • 使用节流:若你一直在改变窗口大小,则每500毫秒就会执行一次你的处理方法。

(1)节流函数的实现

function throttle(func, wait) {
     
  let timeout = null
  return function() {
     
    const context = this
    const args = arguments
    if (!timeout) {
     
      timeout = setTimeout(() => {
     
        timeout = null
        func.apply(context, args)
      }, wait)
    }
  }
}

function handleDom() {
     
	console.log('盒子的位置:', dom.offset.x, dom.offset.y)
}
window.on('resize', function() {
     
	throttle(handleDom, 500); //这里调用节流函数获取拖动期间每隔500毫秒盒子的位置
)

应用场景:监听页面鼠标滚动

(2)函数防抖的实现

function debounce (func, wait) {
     
  let timeout = null
  return function() {
     
    const context = this
    const args = arguments
    if (timeout) clearTimeout(timeout)
    timeout = setTimeout(() => {
     
      func.apply(context, args)
    }, wait)
  }
}
function handelInput(e) {
     
	const {
     value} = e.target
	this.getSearchData(value)
}
debouce(handelInput(e), 500)

应用场景:搜索框搜索。

6.数组扁平化

(1)ES6中的flat()

const arr = [1, [1,2], [1,2,3]].flat()

(2)使用正则

const arr = [1, [1,2], [1,2,3]]
const str = `[${
      JSON.stringify(arr).replace(/(\[|\])/g, '')}]`
JSON.parse(str)

(3)使用reduce() (兼容到ie9)

var array = [1, [1, 2], [1, 2, 3]];
function flat(array) {
     
	return arry.reduce((prev, cur)=> {
     
		return prev.contact(cur instanceof Array ? flat(cur) : cur)
	}, [])
}
//调用flat函数,实现数组的扁平化
flat(array)

注意: reduce() 对于空数组是不会执行回调函数的。所以在如上返回函数之后会自动加上一个空数组

7.深拷贝,浅拷贝

深浅拷贝都是针对引用类型而言的,浅拷贝只是复制对象的引用,如果拷贝后的对象发生变化,原对象也会发生变化。只有深拷贝才是真正地对对象的拷贝。

(1)浅拷贝

浅拷贝只是复制了引用,并没有实现真正的复制。

var arr = [1,2,3];
var cloneArr = arr;
cloneArr.push(4);

console.log(arr);      // [1, 2, 3, 4]
console.log(cloneArr); // [1, 2, 3, 4]

(2)深拷贝

深拷贝是完完全全的拷贝,它们之间彼此隔离,互不影响。

实现深拷贝的方法主要有两种:

  1. 利用 JSON 对象中的 parse 和 stringify
  2. 利用递归来实现每一层都重新创建对象并赋值

(1)JSON 对象中的 parse 和 stringify

var arr = [1,2,3];
var cloneArr = JSON.parse(JSON.stringify(arr));
cloneArr.push(4);

console.log(arr);      // [1, 2, 3]
console.log(cloneArr); // [1, 2, 3, 4]

这个方法确实实现了深拷贝,也是我们最常用的一种方法,但对于一些复杂的引用类型,就存在问题

var obj = {
     
  name: 'Tom',
  sayName: function(){
     
    console.log(this.name)
  }
}
 
var cloneObj = JSON.parse(JSON.stringify(obj));
 
console.log(obj);      // {
     name: "Tom", sayName: ƒ}
console.log(cloneObj); // {
     name: "Tom"}

我们发现,它并没有将方法复制下来。原因是:undefined、function、symbol 会在转换过程中被忽略。。。

(2)递归实现

function deepClone(obj) {
     
	if (typeof obj !== 'object') return; //如果不是对象,直接跳出
	var newObj = obj instanceof Array ? [] : {
     }; // 判断复制的目标是数组还是对象
	for (var i in obj) {
     
		if (obj.hasOwnProperty(key)) {
     
			newObj[i] = typeof obj[i] == 'object' ?
			deepClone(obj[i]) : obj[i]; // 如果值是对象,就递归一下, 否则就直接赋值
		}
	}
	return newObj;
}
 
// 测试
var obj = {
     
  name: 'Tom',
  sayName: function(){
     
    console.log(this.name)
  }
}
 
var cloneObj = deepClone(obj);
obj.sex = '女';
console.log(obj);      // {
     name: "Tom", sayName: ƒ}
console.log(cloneObj); // {
     name: "Tom", sayName: ƒ}

JavaScript中的有的方法也能实现拷贝,比如:concat()和slice(),ES6中的Object.assgin()和…展开运算符。

  1. concat 只是对数组的第一层进行深拷贝
  2. slice 只是对数组的第一层进行深拷贝
  3. … 实现的是对象第一层的深拷贝。后面的只是拷贝的引用值。
  4. 总结:
    (1)赋值运算符 = 实现的是浅拷贝,只拷贝对象的引用值;
    (2)JavaScript 中数组和对象自带的拷贝方法都是“首层浅拷贝”;
    (3)JSON.stringify 实现的是深拷贝,但是对目标对象有要求
    (4)若想真正意义上的深拷贝,请递归

8.剩余/扩展运算符(常用)

剩余运算符和扩展运算符的区别就是:

  • 剩余运算符会收集这些集合,放到右边的数组中
  • 扩展运算符是将右边的数组拆分成元素的集合,它们是相反的

9.事件循环(eventloop)

(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。

(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。

(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。

(4)主线程不断重复上面的第三步。

四、前端基础知识

1.http 和 https的区别

(1) 申请方式不一致:https协议需要ca证书,且费用较高,http申请不需要证书和费用;
(2) 传输协议不一致:http是超文本传输协议,信息是明文传输,而http是具有安全性的SSL加密传输协议;
(3) 端口不一致:一般而言,http 协议的端口为 80,https的端口为 443;
(4) 安全性不一致:http 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 http 协议安全

2.tcp 三次握手

客户端和服务端都需要直到各自可收发,因此需要三次握手。
简化三次握手:

从图片可以得到三次握手可以简化为:
C 发起请求连接 S 确认,也发起连接 C 确认(C:客户端,S:服务器端)
每次握手的过程:
第一次握手:S 确认自己可以接受 C 发送的报文段;
第二次握手:C 确认 S 收到了自己发送的报文段,并且确认自己可以接
受 S 发送的报文段;
第三次握手:S 确认 C 收到了自己发送的报文段;

3.TCP 和 UDP 的区别

(1)TCP 是面向连接的,UDP 是无连接的即发送数据前不需要先建立链接。
(2)TCP 提供可靠的服务。也就是说,通过 TCP 连接传送的数据,无差错,不
丢失,不重复,且按序到达;UDP 尽最大努力交付,即不保证可靠交付。 并且因
为 tcp 可靠,面向连接,不会丢失数据因此适合大数据量的交换。
(3)TCP 是面向字节流,UDP 面向报文,并且网络出现拥塞不会使得发送速率降
低(因此会出现丢包,对实时的应用比如 IP 电话和视频会议等)。
(4)TCP 只能是 1 对 1 的,UDP 支持 1 对 1,1 对多。
(5)TCP 的首部较大为 20 字节,而 UDP 只有 8 字节。
TCP 是面向连接的可靠性传输,而 UDP 是不可靠的。

4.WebSocket

WebSocket 是 HTML5 中的协议,支持持久连续,http 协议不支持持久性连接。Http1.0 和 HTTP1.1 都不支持持久性的链接,HTTP1.1 中的 keep-alive,将多个http 请求合并为 1 个;

5.BOM

什么是 Bom? Bom 是浏览器对象。有哪些常用的 Bom 属性呢?

(1)location 对象

  • location.href – 返回或设置当前文档的 URL
  • location.search – 返回 URL 中的查询字符串部分。

例如 http://www.dreamdu.com/dreamdu.php?id=5&name=dreamdu
【返回包括(?)后面的内容?id=5&name=dreamdu 】

  • location.hash–返回URL#后面的内容,如果没有#,返回空

  • location.host – 返回 URL 中的域名部分,

    例如 www.dreamdu.com

  • location.hostname – 返回 URL 中的主域名部分,

例如 dreamdu.com

  • location.pathname – 返回 URL 的域名后的部分。

例如 http://www.dreamdu.com/xhtml/ 【返回/xhtml/】

  • location.port – 返回 URL 中的端口部分。

例如 http://www.dreamdu.com:8080/xhtml/ 【返回 8080】

  • location.protocol – 返回 URL 中的协议部分。

例如 http://www.dreamdu.com:8080/xhtml/ 【返回(//)前面的内容 http:】

  • location.assign – 设置当前文档的 URL
  • location.replace() – 设置当前文档的 URL,并且在 history 对象的地址列表 中移除这个 URL – location.replace(url);
  • location.reload() – 重载当前页面

(2)history 对象

  • history.go() – 前进或后退指定的页面数 history.go(num);
  • history.back() – 后退一页
  • history.forward() – 前进一页

(3)Navigator 对象

navigator.userAgent – 返回用户代理头的字符串表示(就是包括浏览器版本
信息等的字符串)
navigator.cookieEnabled – 返回浏览器是否支持(启用)cookie

6.说一下 http2.0

http2.0 是基于 1999 年发布的 http1.0 之后的首次更新。
http2.0相对于http1.0的优势有:

  • 提升访问速度(可以对于,请求资源所需时间更少,访问速度更快,相比 http1.0)
  • 允许多路复用:多路复用允许同时通过单一的 HTTP/2连接发送多重请求响应信 息。
  • 增加了连接数量:在 http1.1 中,浏览器客户端在同一时间,针对同一域名下的请求有一定数量限制(连接数量),超过限制会被阻塞。
  • 二进制分帧:HTTP2.0 会将所有的传输信息分割为更小的信息或者帧,并对他们进行二进制编码。
  • *首部压缩
  • *服务器端推送

7.请求状态码

  • 200(成功): 服务器已成功处理了请求
  • 304(重定向): 自从上次请求后,请求的网页未被修改过。服务器返回此响应时,不会返回网页内容。
  • 400(错误请求): 服务器不理解请求的语法
  • 403(禁止请求) 服务器理解请求客户端的请求,但是拒绝执行此请求
  • 404(未找到): 服务器找不到请求的网页。
  • 401(权限不够):当前请求需要用户验证
  • 500(服务器内部错误):服务器遇到错误,无法完成请求。

8.Cookie、sessionStorage、localStorage 的区别

  • Cookie:数据始终在同源的 http 请求中携带,可以在浏览器和服务器端来回传递,存储容量小,只有大约 4K 左右;

cookie作用:(1)保存用户登录状态;(2)跟踪用户行为

  • sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;
  • localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;

9.iframe 是什么?有什么缺点?

定义:iframe 元素会创建包含另一个文档的内联框架
提示:可以将提示文字放在之间,来提示某些不支持 iframe的浏览器
缺点:
a. 会阻塞主页面的 onload 事件
b. 搜索引擎无法解读这种页面,不利于 SEO
c. iframe 和主页面共享连接池,而浏览器对相同区域有限制所以会影响性能。

10.Doctype 作用?严格模式与混杂模式如何区分?它们有何意义?

Doctype 声明于文档最前面,告诉浏览器以何种方式来渲染页面,这里有两种模式,严格模式和混杂模式。

  • 严格模式的排版和 JS 运作模式是 以该浏览器支持的最高标准运行。
  • 混杂模式向后兼容,模拟老式浏览器,防止浏览器无法兼容页面。

11.Cookie 如何防范 XSS 攻击

XSS(跨站脚本攻击)是指攻击者在返回的 HTML 中嵌入 javascript 脚本,为了减轻这些攻击,需要在 HTTP 头部配上,set-cookie:httponly-这个属性可以防止 XSS,它会禁止 javascript 脚本来访问 cookie。secure - 这个属性告诉浏览器仅在请求为 https 的时候发送 cookie。
结果应该是这样的:Set-Cookie=.....

12.Cookie 和 session 的区别

(1)数据存放位置不同:

cookie数据存放在客户的浏览器上,session数据放在服务器上。

(2)安全程度不同:

cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。

(3)性能使用程度不同:

session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。

(4)数据存储大小不同:

单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie,而session则存储与服务端,浏览器对其没有限制。

13.说一下你对RESTFUL的理解?

Representational State Transfer的缩写。即"资源表现层状态转化"。
即就是用 URL 定位资源,用 HTTP 描述操作的一种URL设计风格。

举例来说,某个URI是/posts/show/1,其中show是动词,这个URI就设计错了,正确的写法应该是/posts/1,然后用GET方法表示show。

14.讲讲 viewport 和移动端布局

参考答案:
前端开发中,静态网页通常需要适应不同分辨率的设备,常用的自适应解决方案包括媒体查询、百分比、rem 和 vw/vh 等。
下面从 px 单位出发,分析 px 在移动端布局中的不足,接着介绍几种不同的自适应解决方案。

  • px 和视口
  • 媒体查询
  • 百分比自适应场景下的 rem 解决方案

基于750设计稿1rem=100px的布局方案:
html { font-size: calc(100vm / 750 * 100) }

  • 通过 vw/vh 来实现自适应

15.http 常用请求头

可以将 http 请求头为通用首部,请求首部,响应首部,实体首部,通用首部表示一些通用信息

  • date:表示报文创建时间,请求首部就是请求报文中独有的;
  • cookie:和缓存相关的;
  • if-Modified-Since:响应首部就是响应报文中独有的;
  • set-cookie:和重定向相关的 location, 实体首部用来描述实体部分 ;
  • allow:用来描述可执行的请求方法 ;
  • content-type:描述主题类型;
  • content-Encoding:描述主体的编码方式。

Accept 可接受的响应内容类型(Content-Types) Accept-Charset 可接受的字符集
Accept-Encoding 可接受的响应内容的编码方式
Accept-Language 可接受的响应内容语言列表
Accept-Datetime 可接受的按照时间来表示的响应内容版本
Authorization 用于表示 HTTP
协议中需要认证资源的认证信息
Cache-Control 用来指定当前的请求/回复中的,是否使用缓存机制 Connection 客户端(浏览器)想要优先使用的连接
Cookie 由之前服务器通过 Set-Cookie(见下文)设置的一个 HTTP 协议Cookie
Content-Type 请求体的 MIME 类型(用于 POST 和 PUT请求中)
Date 发送该消息的日期和时间(以 RFC7231中定义的"HTTP 日期"格式发送)
Host 表示服务器的域名以及服务器所监听的端口号。如果所请求的端口是对应的服务的标准端口(80),则端口号可以省略
Origin 发起一个针对跨域资源共享的请求(该请求要求服务器在响应中加入一个
Access-Control-Allow-Origin 的消息头,表示访问控制所允许的来源)
User-Agent 浏览器的身份标识字符串
Warning 一个一般性的警告,表示在实体内容体中可能存在错误

16.强,协商缓存

缓存分为两种:强缓存和协商缓存,根据响应的 header 内容来决定。

  • 强缓存相关字段有 expires,cache-control。如果 cache-control 与expires同时存在的话,cache-control 的优先级高于 expires。
  • 协商缓存相关字段有Last-Modified/If-Modified-Since,Etag/If-None-Match

17.GET 和 POST 的区别

  1. get 参数通过 url 传递,post 放在 request body 中。
  2. get 请求在 url 中传递的参数是有长度限制的,而post 没有。
  3. get 比 post 更不安全,因为参数直接暴露在 url 中,所以不能用来传递敏感信息。
  4. get 请求只能进行url 编码,而 post 支持多种编码方式
  5. get 请求会浏览器主动 cache,而 post 则不支持。
  6. get请求参数会被完整保留在浏览历史记录里,而 post 中的参数不会被保留。
  7. GET 和 POST 本质上就是 TCP链接,并无差别。但是由于 HTTP 的规定和浏览器/ 服务器的限制,导致他们在应用过程中体现出一些不同。 GET 产生一个 TCP数据包;POST 产生两个 TCP 数据包

18.如何画一个三角形

三角形原理:边框的均分原理

div {
     
	width:0px;
	height:0px;
	border-top:10px solid red;
	border-right:10px solid transparent;
	border-bottom:10px solid transparent;
	border-left:10px solid transparent;
}

19.在地址栏里输入一个 URL,到这个页面呈现出来,中间会发生什么?

总体来说分为以下几个过程:

1. DNS解析

2. TCP连接

3. 发送HTTP请求

4. 服务器处理请求并返回HTTP报文

5. 浏览器解析渲染页面

6. 连接结束

        输入 url 后,首先需要找到这个 url 域名的服务器 ip,为了寻找这个 ip,浏览器首先会寻找缓存,查看缓存中是否有记录,缓存的查找记录为:浏览器缓存->系统缓存->路由器缓存,缓存中没有则查找系统的 hosts 文件中是否有记录,如果没有则查询 DNS 服务器,得到服务器的 ip 地址后,浏览器根据这个 ip 以及相应的端口号,构造一个 http 请求,这个请求报文会包括这次请求的信息,主要是请求方法,请求说明和请求附带的数据,并将这个 http 请求封装在一个 tcp包中,这个 tcp 包会依次经过传输层,网络层,数据链路层,物理层到达服务器,服务器解析这个请求来作出响应,返回相应的 html 给浏览器,因为 html 是一个树形结构,浏览器根据这个 html 来构建 DOM 树,在 dom 树的构建过程中如果遇到 JS 脚本和外部 JS 连接,则会停止构建 DOM 树来执行和下载相应的代码,这会造成阻塞,这就是为什么推荐 JS 代码应该放在 html 代码的后面,之后根据外部样式,内部样式,内联样式构建一个 CSS 对象模型树 CSSOM 树,构建完成后和DOM 树合并为渲染树,这里主要做的是排除非视觉节点,比如 script,meta 标签和排除 display 为 none 的节点,之后进行布局,布局主要是确定各个元素的位置和尺寸,之后是渲染页面,因为 html 文件中会含有图片,视频,音频等资源,在解析DOM 的过程中,遇到这些都会进行并行下载,浏览器对每个域的并行下载数量有一定的限制,一般是 4-6 个,当然在这些所有的请求中我们还需要关注的就是缓存,缓存一般通过 Cache-Control、Last-Modify、Expires 等首部字段控制。Cache-Control 和 Expires 的区别在于 Cache-Control 使用相对时间,Expires 使用的是基于服务器 端的绝对时间,因为存在时差问题,一般采用Cache-Control,在请求这些有设置了缓存的数据时,会先 查看是否过期,如果没有过期则直接使用本地缓存,过期则请求并在服务器校验文件是否修改,如果上一次 响应设置了ETag值会在这次请求的时候作为If-None-Match的值交给服务器校验,如果一致,继续校验 Last-Modified,没有设置 ETag 则直接验证Last-Modified,再决定是否返回 304。

20.csrf 和 xss 的网络攻击及防范

CSRF:跨站请求伪造

可以理解为攻击者盗用了用户的身份,以用户的名义发送了恶意请求,比如用户登录了一个网站后,立刻在另一个tab页面访问量攻击者用来制造攻击的网站,这个网站要求访问刚刚登陆的网站,并发送了一个恶意请求,这时候 CSRF 就产生了,比如这个制造攻击的网站使用一张图片,但是这种图片的链接却是可以修改数据库的,这时候攻击者就可以以用户的名义操作这个数据库;

防御方式:使用验证码,检查 https 头部的 refer,使用 token

XSS:跨站脚本攻击

是说攻击者通过注入恶意的脚本,在用户浏览网页的时候进行攻击,比如获取 cookie,或者其他用户身份信息,可以分为存储型和反射型,存储型是攻击者输入一些数据并且存储到了数据库中,其他浏览者看到的时候进行攻击,反射型的话不存储在数据库中,往往表现为将攻击代码放在 url地址的请求参数中;

防御方式:为 cookie 设置 httpOnly 属性,对用户的输入进行检查,进行特殊字符过滤;

21.HTML5 和 CSS3 新增的特性?

html5:

1)标签增删

(1) 8 个语义元素 header section footer aside nav main article figure
(2) 内容元素 mark 高亮 progress 进度
(3) 新的表单控件 calander date time email url search
(4) 新的 input 类型 color date datetime datetime-local email
(5) 移除过时标签 big font frame frameset

2)canvas 绘图,支持内联 SVG。支持 MathML

3)多媒体 audio video source embed track

4)本地离线存储,把需要离线存储在本地的文件列在一个 manifest 配置文件

5)web 存储:localStorage、SessionStorage

css3:

边框: border-radius,box-shadow 等;
背景: background-size,background-origin 等;
动画: transform、animation 等。

22.了解重绘和重排(回流)吗,知道怎么去减少重绘和重排吗,让文档脱离文档流有哪些方法?

DOM 的变化影响到了预算内宿的几何属性比如宽高,浏览器重新计算元素的几何属性,其他元素的几何属性也会受到影响,浏览器需要重新构造渲染书,这个过程称之为重排,浏览器将受到影响的部分重新绘制在屏幕上 的过程称为重绘。
引起重排重绘的原因有:

(1) 添加或者删除可见的 DOM 元素,
(2) 元素尺寸位置的改变
(3) 浏览器页面初始化,
(4) 浏览器窗口大小发生改变,重排一定导致重绘,重绘不一定导致重排.

减少重绘重排的方法有:

(1) 不在布局信息改变时做 DOM 查询,
(2) 使用 csstext,className 一次性改变属性
(3) 使用 fragment
(4) 对于多次重排的元素,比如说动画。使用绝对定位脱离文档流,使其不影响其他元素

23.怎么隐藏一个元素

1)opacity:0

该元素隐藏起来了,但不会改变页面布局,并且,如果该元素已经绑定一些事件,如 click 事件,那么点击该区域,也能触发点击事件的

2)visibility:hidden

该元素隐藏起来了,但不会改变页面布局,但是不会触发该元素已经绑定的事件

3)display:none

把元素隐藏起来,并且会改变页面布局,可以理解成在页面中把该元素删除掉。

24.flex布局

容器有以下属性:

  • flex-direction: 属性决定主轴的方向;
  • flex-wrap: 属性定义,如果一条轴线排不下,如何换行;
  • *flex-flow:属性是 flex-direction 属性和 flex-wrap 属性的简写形式,默认值 为 row nowrap;
  • justify-content: 属性定义了项目在主轴上的对齐方式。
  • align-items: 属性定义项目在交叉轴上如何对齐。
  • align-content: 属性定义了多根轴线的对齐方式。如果项目只有一根轴线,该属性不起作用。

项目(子元素)也有一些属性:order,flex-grow,flex-shrink,flex-basis,flex,align-self。

  • order 属性定义项目的排列顺序。数值越小,排列越靠前,默认为 0。

  • flex-grow 属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放 大。

  • flex-shrink 属性定义了项目的缩小比例,默认为 1,即如果空间不足,该项目 将缩小。

  • flex-basis 属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。
    2021Web前端中高级面试题复盘_第1张图片

  • flex 属性是 flex-grow、flex-shrink 和 flex-basis 的简写,默认值为 0 1 auto。后两个属性可选。

  • align-self 属性允许单个项目有与其他项目不一样的对齐方式,可覆盖 align-items 属性。默认值为 auto,表示继承父元素的 align-items 属性,如果 没有父元素,则等同于 stretch。

25.说一下类的创建和继承

(1)类的创建(es5):
new 一个 function,在这个 function 的 prototype 里面增加属性和方法。
下面来创建一个 Animal 类:

// 定义一个动物类
function Animal (name) {
     
// 属性
this.name = name || 'Animal';
// 实例方法
this.sleep = function() {
     
	console.log(this.name + '正在睡觉!');
	}
}
// 原型方法
Animal.prototype.eat = function(food) {
     
console.log(this.name + '正在吃:' + food);
};

这样就生成了一个 Animal 类,实力化生成对象后,有方法和属性。

(2)类的继承——原型链继承

function Cat(){
      }
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';
// Test Code
var cat = new Cat();
console.log(cat.name);
console.log(cat.eat('fish'));
console.log(cat.sleep());
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true

介绍:在这里我们可以看到 new 了一个空对象,这个空对象指向 Animal 并且Cat.prototype 指向了这个空对象,这种就是基于原型链的继承。
特点:基于原型链,既是父类的实例,也是子类的实例
缺点:无法实现多继承

26.如何解决异步回调地狱

promise、generator、async/await

27.说一下事件委托

事件委托指的是,不在事件的发生地(直接 dom)上设置监听函数,而是在其父元素上设置监听函数,通过事件冒泡,父元素可以监听到子元素上事件的触发,通过判断事件发生元素 DOM 的类型,来做出不同的响应。

28.js 的 new 操作符做了哪些事情

new 操作符新建了一个空对象,这个对象原型指向构造函数的 prototype,执行构造函数后返回这个对象。

29.异步加载 js 的方法

defer:只支持 IE 如果您的脚本不会改变文档的内容,可将 defer 属性加入到

你可能感兴趣的:(前端,面试,html,css,javascript)