1、什么是HTML语义化?

根据内容选择合适的标签,写段落就用p标签,写标题就用h1,让页面具有良好的语义和结构,从而方便人类和机器都能快速理解网页内容

2、meta viewport 是做什么用的,怎么写?

为浏览器提供页面的相关信息,比如针对搜索引擎的关键词

  1. <meta name="viewport" content="width=device-width, initial-scale=1,
  2. maximum-scale=1, minimum-scale=1">
  3. <meta name="viewport" content="width=device-width,initial-scale=1,
  4. minimum-scale=1,maximum-scale=1,user-scalable=no,viewport-fit=cover">

viewport 是 meta 标签的 name 属性中可选值中的一个,指 web 页面上用户可见的区域,web页面中的CSS像素的值等于device-width 时,对应到手机上就是占满全屏的宽度,用于移动端页面设计;
initial-scale=1.0 初始化的缩放比例;

maximum-scale=1.0 允许用户最大的缩放比例;

user-scalable=no 为no时不允许用户手动缩放

3、H5是什么?HTML5是什么?XHTML又是什么?

H5是移动网站的一个名称,手机上各种能够被浏览器打开的网页都可以被笼统的称作H5。H5的应用方式主要有:电子邀请函、电子宣传册、企业汇报幻灯片、活动广告、信息收集等。
HTML5 是下一代的 HTML。
XHTML 是以 XML 格式编写的 HTML, 指的是可扩展超文本标记语言,是更严格更纯净的 HTML 版本,XHTML 元素必须合理嵌套,必须有关闭标签,元素必须是小写
https://www.runoob.com/html/html-xhtml.html

4、两种盒模型

W3C的标准盒子模型:content-box
content-box内容盒模型:宽度=内容的宽度,如果后期添加了border或padding就会使盒子向外扩张
IE盒子模型:border-box边框盒模型
border-box边框盒模型:设置的宽度就等于=内容宽度+padding+border;添加的padding和border就在原先设置的width里,border和padding越大就会向内部content扩张,导致content变小
image.png

5、flex怎么用,常见的有哪些属性?

在父盒子上写 display:flex

  1. flex-direction:row;//改变子元素流动的方向(主轴)
  2. flex-wrap:nowrap; //改变折行
  3. justify-content:flex-start;//主轴对齐方式(默认主轴是横轴,除非你改变了flex-direction)
  4. align-items:stretch;//次轴第七方式
  5. order:1; //按着从小到大排序,-1放在第一位
  6. flex-grow:1;//元素的占比大小
  7. flex-shrink:5;//当空间不够时,控制谁变瘦,谁值大谁先变瘦的快 ,0时不变瘦,1是默认

6、BFC 是什么?

块格式化上下文(Block Formatting Context,BFC) 是Web页面的可视CSS渲染的一部分,是块盒子的布局过程发生的区域,也是浮动元素与其他元素交互的区域。
下列方式会创建块格式化上下文

  1. - 根元素(`<html>)`
  2. - 浮动元素(元素的 [`float`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/float) 不是 `none`)
  3. - 绝对定位元素(元素的 [`position`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/position) 为 `absolute` 或 `fixed`)
  4. - 行内块元素(元素的 [`display`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/display) 为 `inline-block`)
  5. - [`overflow`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/overflow) 值不为 `visible` 的块元素
  6. - [`display`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/display) 值为 `[flow-root](https://drafts.csswg.org/css-display/#valdef-display-flow-root)` 的元素
  7. - [`contain`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/contain) 值为 `layout`、`content `或 paint 的元素
  8. - 弹性元素([`display`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/display) 为 `flex` 或 `inline-flex `元素的直接子元素)
  9. - 网格元素([`display`](https://developer.mozilla.org/zh-CN/docs/Web/CSS/display) 为 `grid` 或 `inline-grid` 元素的直接子元素)

块格式化上下文包含创建它的元素内部的所有内容.

7、清除浮动


  1. .clearfix:after{
  2. content: '';
  3. display: block; /*或者 table*/
  4. clear: both;
  5. }
  6. .clearfix{
  7. zoom: 1; /* IE 兼容*/
  8. }

ES 6 语法知道哪些,分别怎么用?

块级作用域:使用{}括起来的就是块级作用域
通过var声明的变量没有块级作用域
使用 letconst使用 块级作用域的。
使用function函数声明,同样被限制在声明他的语句块内;
箭头函数
析构赋值: 又叫 解构赋值 语法是一种 Javascript 表达式。通过解构赋值, 可以将属性/值从对象/数组中取出,赋值给其他变量。

  1. let a, b, rest;
  2. [a, b] = [10, 20];
  3. console.log(a);
  4. // expected output: 10
  5. console.log(b);
  6. // expected output: 20
  7. [a, b, ...rest] = [10, 20, 30, 40, 50];
  8. console.log(rest);
  9. // expected output: Array [30,40,50]

https://fangyinghang.com/es-6-tutorials/

同步和异步

同步: 要等任务执行完,得到结果,才执行下一个任务。是所有的操作都做完,才返回给用户结果。即写完数据库之后,再响应用户,用户体验不好。

  1. function A = function(){
  2. return '同步任务的返回值'
  3. }
  4. var result = A() // 那么 result 就是同步任务的结果
  5. B() // 然后执行下一个任务

异步:不等任务执行完,就直接执行下一个任务;书写顺序和执行顺序不一样。不用等所有操作都做完,就响应用户请求。即先响应用户请求,然后慢慢去写数据库,用户体验较好。
下面这个代码的书写顺序是 1 -> 2 -> 3;但是执行顺序是 1 -> 3 -> 2。这就是异步

  1. console.log(1)
  2. setTimeout(function(){
  3. console.log(2)
  4. },0)
  5. console.log(3)

如何判断同步异步?
如果一个函数的返回值处于 setTimeout, AJAX,addEventListener这三个东西内部,那么这个函数就是异步函数

Promise、Promise.all、Promise.race 分别怎么用?

Promise 是异步编程的一种解决方案:表示一个异步操作的最终状态以及返回的值;
从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。
promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行。

promise的用法:
一个Promise必须提供一个 then 方法以访问其当前值、终值和据因。
promise.then(onFulfilled, onRejected)回调函数只能执行一次,且返回 promise 对象
Promise的每个操作返回的都是Promise对象,可支持链式调用。
通过 then 方法执行回调函数,Promise的回调函数是放在事件循环中的微队列。

  1. function fn(){
  2. return new Promise((resolve, reject)=>{
  3. 成功时调用 resolve(数据)
  4. 失败时调用 reject(错误)
  5. })
  6. }
  7. fn().then(success, fail).then(success2, fail2)

Promise.all 用法
Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
promise1promise2都成功才会调用success1

  1. Promise.all([promise1, promise2]).then(success1, fail1)

Promise.race 用法
Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
promise1promise2只要有一个成功就会调用succ ess1
promise1promise2只要有一个失败就会调用fail1
总之,谁第一个成功或失败,就认为是race的成功或失败。

  1. Promise.race([promise1, promise2]).then(success1, fail1)

promise的缺点:不能取消,

函数节流和函数防抖

函数节流:任务在指定的间隔时间内只执行一次。

  1. // 节流(一段时间执行一次之后,就不执行第二次)
  2. function throttle(fn, delay){
  3. let canUse = true
  4. return function(){
  5. if(canUse){
  6. fn.apply(this, arguments)
  7. canUse = false
  8. setTimeout(()=>canUse = true, delay)
  9. }
  10. }
  11. }
  12. const throttled = throttle(()=>console.log('hi'))
  13. throttled()
  14. throttled()

函数防抖:只有在任务触发的间隔大于等于指定的间隔时间,任务才会被执行。(点击了之后先不做,等了一定的时间之后再做)

  1. // 防抖(一段时间会等,然后带着一起做了)
  2. function debounce(fn, delay){
  3. let timerId = null
  4. return function(){
  5. const context = this
  6. if(timerId){window.clearTimeout(timerId)}
  7. timerId = setTimeout(()=>{
  8. fn.apply(context, arguments)
  9. timerId = null
  10. },delay)
  11. }
  12. }
  13. const debounced = debounce(()=>console.log('hi'))
  14. debounced()
  15. debounced()

AJAX

AJAX 是一种在无需重新加载整个网页的情况下,能够更新部分网页的技术。

  1. var request = new XMLHttpRequest()
  2. request.open('GET', '/a/b/c?name=ff', true);
  3. request.onreadystatechange = function() {
  4. if(request.readyState === 4 && request.status === 200) {
  5. console.log(request.responseText);
  6. }};
  7. request.send();

简化版代码

  1. var request = new XMLHttpRequest()
  2. request.open('GET', '/a/b/c?name=ff', true)
  3. request.onload = ()=> console.log(request.responseText)
  4. request.send()

this

thisJavaScript关键字,在非严格模式下,它总是指向一个对象,而具体指向哪个对象是根据函数运行时所在的执行环境动态绑定的。

为什么需要 this
因为函数可以在不同的运行环境中执行,自身调用或作为方法调用,为了得到当前函数真正运行时的所在执行环境,即函数执行时真正的调用对象this机制就此诞生了。

  1. fn()
  2. this => window/global
  3. obj.fn()
  4. this => obj
  5. fn.call(xx)
  6. this => xx
  7. fn.apply(xx)
  8. this => xx
  9. fn.bind(xx)
  10. this => xx
  11. new Fn()
  12. this => 新的对象
  13. fn = ()=> {}
  14. this => 外面的 this

闭包和立即执行函数

闭包:如果一个函数用到了外部的变量,那么这个函数加这个变量,就叫做闭包
image.png
1和22
闭包的作用:闭包常常用来‘间接访问一个变量’。换句话说,隐藏一个变量。
内存泄露是指你用不到(访问不到)的变量,依然占居着内存空间,不能被再次利用起来。

立即执行函数是什么

立即执行函数:1.声明一个匿名函数
2.马上调用这个匿名函数

image.png
匿名函数后面接一对括号 (),调用这个匿名函数。
那么为什么还要用另一对括号把匿名函数包起来呢?
如果不加另一对括号,直接写成

  1. function(){alert('我是匿名函数')}()

立即执行函数的作用

只有一个作用:创建一个独立的作用域。
这个作用域里面的变量,外面访问不到(即避免「变量污染」)。

面试题

  1. let i;
  2. for(i=0; i<6; i++){
  3. setTimeout(fn()=>{
  4. console.log(i);
  5. },1000);// 为什么 打印 出来的总是 6,而不是 0、1、2、3、4、5
  6. }

为什么 打印的总是 6 呢,因为 i 是贯穿整个作用域的,setTimeout函数是当1000毫秒执行完后就执行,但此时i已经等于6了

那么怎么解决这个问题呢
解法1:把let i=0写道for循环里,这样会对每一次循环创建一个新的作用域,i会保留此时的值
解法2:用立即执行函数给每个i创造一个独立作用域即可

  1. //解法1
  2. for(let i=0; i<6; i++){
  3. setTimeout(fn()=>{
  4. console.log(i);
  5. },1000);
  6. }
  7. //解法2
  8. for(let i=0; i<6; i++){
  9. !function(){
  10. setTimeout(()=> console.log(i),1000);
  11. }(i)
  12. }

什么是跨域,什么是 JSONP,什么是 CORS

跨域

浏览器从一个域名的网页去请求另一个域名的资源时,域名、端口、协议有一个不同,都是跨域;
即指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制

同源策略

同源定义: 如果两个url的协议,域名,端口号完全一致,那么这两个url就是同源的
源: 在任意一个浏览器打印 window.origin 或location.origin可以得到当前源
源=协议+域名+端口号

同源策略定义: 浏览器规定,如果JS运行在源A里,那么就只能获取源A的数据不能获取源B的数据,即不允许跨域。目的就是为了保护用户隐私

CORS

CORS: 跨源资源共享
就是解决不同源之间数据的访问
在被访问源的响应头里提前声明,指明此数据谁可以访问: [http://dong.com:9990](http://dong.com:9990)可以访问了

  1. response.setHeader("Access-Control-Allow-Origin", "http://dong.com:9990");

面试 - 图4

但是IE 6,7,8,9 不支持CORS,可以使用JSONP

JSONP

JSONP:在跨域的时候浏览器不支持cors,必须使用另外一种方式跨域,于是我们就请求一个js文件,这个js文件会执行一个回调,回调里面就有我们的数据,回调函数名字可以是一个随机数,把这个名字以callback参数传给后台,后台会把这个参数返回过来并执行;
优点: 兼容ie,可以跨域
缺点: 由于是script标签,它拿不到状态码和响应头,只知道成功和失败,只能发get请求,不支持post

  1. 1.jsonp跨域方法是新建一个js文件里面写上一个占位符{{data}}
  2. 2.在后端路由里将json数据文件转化成字符串
  3. 3.再将js文件转化成字符串
  4. 4.然后用json字符串 替换掉{{data}}

面试 - 图5

这样就可以跨域访问了,但是还是有一个问题,这个js所有人都可以访问,不安全
解决方法:是由referer检验,在路由哪判断一下是否允许访问

如何实现深拷贝?

  • 浅拷贝:是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象
  • 深拷贝:是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

image.png
浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象还是共享同一块内存。但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象。
使用递归实现深拷贝

  1. function deepClone1(obj) {
  2. //判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
  3. var objClone = Array.isArray(obj) ? [] : {};
  4. //进行深拷贝的不能为空,并且是对象或者是
  5. if (obj && typeof obj === "object") {
  6. for (key in obj) {
  7. console.log(key,'key')
  8. if (obj.hasOwnProperty(key)) {
  9. if (obj[key] && typeof obj[key] === "object") {
  10. objClone[key] = deepClone1(obj[key]);
  11. } else {
  12. objClone[key] = obj[key];
  13. }
  14. }
  15. }
  16. }else{
  17. console.log(key,'ke11y')
  18. }
  19. return objClone;
  20. }
  21. var ma={ma1:2}
  22. // var ma=[2,3,3]
  23. deepClone1(ma)

async/await 怎么用,如何捕获异常?

https://es6.ruanyifeng.com/?search=async&x=0&y=0#docs/async

不用 class 如何实现继承?用class 又如何实现?

不用class

  1. function Animal(color){
  2. this.color = color
  3. }
  4. Animal.prototype.move = function(){} // 动物可以动
  5. function Dog(color, name){
  6. Animal.call(this, color) // 或者 Animal.apply(this, arguments)
  7. this.name = name
  8. }
  9. // 下面三行实现 Dog.prototype.__proto__ = Animal.prototype
  10. function temp(){}
  11. temp.prototype = Animal.prototype
  12. Dog.prototype = new temp()
  13. Dog.prototype.constuctor = Dog // 这行看不懂就算了,面试官也不问
  14. Dog.prototype.say = function(){ console.log('汪')}
  15. var dog = new Dog('黄色','阿黄')

用 class 就简单了

  1. class Animal{
  2. constructor(color){
  3. this.color = color
  4. }
  5. move(){}
  6. }
  7. class Dog extends Animal{
  8. constructor(color, name){
  9. super(color)
  10. this.name = name
  11. }
  12. say(){}
  13. }

如何用正则实现 trim()?

  1. String.prototype.trim = function(){
  2. return this.replace(/^\s+|\s+$/g, '')
  3. }
  4. //或者
  5. function trim(string){
  6. return string.replace(/^\s+|\s+$/g, '')
  7. }