面试题集

HTML部分

1. 你是如何理解 HTML 语义化的?

语义化是指根据内容的结构化(内容语义化),选择合适的标签(代码语义化),便于开发者阅读和写出更优雅的代码的同时,让浏览器的爬虫和机器很好的解析。
标题用h1-h5。文章用artical。段落用p。时间用time标签。 header标签,footer标签,main标签, nav,artical标签。

html分的历史阶段:

  1. 后台开发写前端页面
    使用table标签。会出现table套table的窘境
  2. 美工阶段
    div+css布局。不够语义化。
  3. 前端阶段
    语义化标签
2. meta viewport 是做什么用的,怎么写?

移动设备上的viewport就是设备的屏幕上能用来显示我们的网页的那一块区域。比如浏览器的可展示区域

<meta name="viewport" content="width=device-width,initial-scale=1">

width设置layout viewport的宽度,为一个正整数,或字符串"width-device"
initial-scale设置页面的最大缩放值,为一个数字,可以带小数
minimum-scale允许用户的最小缩放值,为一个数字,可以带小数
maximum-scale允许用户的最大缩放值,为一个数字,可以带小数
height设置layout viewport的高度,这个属性并不重要,很少使用
user-scalable 是否允许用户进行缩放,值为"no"或"yes"

CSS

两种盒模型
  • box-sizing: conent-box; 将盒子设置为标准模型(盒子默认为标准模型)
  • box-sizing: border-box; 将盒子设置为 IE 模型(也叫做怪异盒子)
content-box {  width: 100px;  height: 100px;  border: 50px solid;  padding: 50px;}

标准模型中,它在页面中实际占有的宽高为300px
IE 模型中,它的页面实际占有宽度还是100px。由于 border + padding 已经等于 100px 了,所以这里 content 已经被压缩到只剩 0 了

什么是边距重叠
两种现象
  1. 同一层相邻元素
<style>
.box-1 {  
  width: 100px;  
  height: 100px; 
  margin-bottom: 50px; /* 会出现重叠。不会出现100px的合边距。 只有50px;*/  
  background-color: aqua;
}
.box-2 {  
  width: 100px;  
  height: 100px;  
  margin-top: 50px;  /* 会出现重叠。不会出现100px的合边距。 只有50px;*/ 
  background-color: blueviolet;
 }
</style>
<div class="box-1"></div>
<div class="box-2"></div>
  1. 父元素和子元素之间没有内容
<div class="futher">
  <div class="child"></div>
</div>
<style>
  * {  margin: 0;  padding: 0;}
  .futher {  
    background: deeppink;
   }
  .child {
    margin-top: 50px;  /*父元素也会跟着有个50px的margin-top*/
    height: 100px;  
    background: deepskyblue;
  }
</style>
实现垂直居中

如果 .parent 的 height 不写,你只需要 padding: 10px 0; 就能将 .child 垂直居中;

如果父元素height写了高度

<div id="box">
    <div id="child"></div>
</div>
#box {
    width: 300px;
    height: 300px;
    background: #ddd;
    position: relative;
}
#child {
    width: 150px;
    height: 100px;
    background: orange;
    position: absolute;
    top: 50%;
    margin: -50px 0 0 0; 
}
#box {
    width: 300px;
    height: 300px;
    background: #ddd;
    position: relative;
}
#child {
    background: orange;
    position: absolute;
    top: 50%;
    transform: translate(0, -50%);
}
#box {
    width: 300px;
    height: 300px;
    background: #ddd;
    display: flex;
    align-items: center;
}
#box {
    width: 300px;
    height: 300px;
    background: #ddd;
    position: relative;
}
#child{
  background: orange;
  position: absolute;
  width: 150px;
  height: 100px;
  margin: auto;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}
水平垂直居中
  1. 水平居中

margin: 0 auto;

<div class="wrap">
    <div class="example2">
    </div>
</div>
.wrap {
    position: relative;
    background-color: orange;
    width: 300px;
    height: 300px;
}
.example2 {
    background-color: red;
    width: 100px;
    height: 100px;
    position: absolute;
    left: 50%;
    top: 50%;
    margin: -50px 0 0 -50px;
}

flex布局

<div class="warp">
  <div class="example3">
    居中显示
  </div>
</div>
.warp {
  position: relative;
  background-color: orange;
  width: 200px;
  height: 200px;
}
.example3 {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: red;
  width: 100px;
  height: 100px;
  margin: auto;
}
.warp {
  position: relative;
  background-color: orange;
  width: 200px;
  height: 200px;
}
.example3 {
  position: relative;
  top:50%;
  transform:translateY(-50%);
  background-color: red;
  width: 100px;
  height: 100px;
  margin: 0 auto;
}
BFC

块格式化上下文

1.给父元素overflow:hidden。那么其浮动的子元素就会被包裹

  1. 兄弟之间划清界限
    假设现在有一对兄弟 div,其中一个加了浮动,那么两个 div 会重叠一部分


    4.png

如果让另一个 div 创建 BFC,那么这两者就会界限分明。


5.png
css优先级

内联 > ID选择器 > 类选择器 > 标签选择器。

  1. 越具体优先级越高
  2. 写在后面的覆盖前面的
  3. important ! 优先级最高。少用。
清楚浮动
.clearFix {
  content: '';
  display: block;
  clear: both;
}

js

ES6 语法知道哪些,分别怎么用?
  • 块级作用域
    let变量,const常量
  • 箭头函数
    。 默认参数
    。 剩余参数: 剩余参数语法允许我们将一个不定数量的参数表示为一个数组
    。 展开运算符: 可以展开数组
function multiply(a, b = 1) {
  return a * b;
}

console.log(multiply(5)); // 5

function fun1(...theArgs) {
  alert(theArgs.length);
}
fun1(5, 6, 7); // 弹出 "3", 因为theArgs有三个元素

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];

console.log(sum(...numbers));
// expected output: 6

[...iterableObj, '4', ...'hello', 6]; // 数组合并
  • 模板字符串
  • 对象属性加强
    。 属性定义支持短语法 obj = { x, y }
  • 解构赋值
var a, b, rest;
[a, b] = [10, 20];
console.log(a); // 10
console.log(b); // 20

[a, b, ...rest] = [10, 20, 30, 40, 50];
console.log(a); // 10
console.log(b); // 20
console.log(rest); // [30, 40, 50]

({ a, b } = { a: 10, b: 20 });
console.log(a); // 10
console.log(b); // 20

手写函数防抖和函数节流
节流

一段时间执行一次之后,就不执行第二次

functiong fn() {}
let cd = false // 技能是否在冷却
button.onclick = function () {
  if(cd) {
    // 在冷却,什么也不错
  } else {
    fn() // 执行函数  或者fn在setTimeout里面执行。相当于施法有吟唱时间
    cd = true
    setTimeout(() => {
     cd = false
    }, 3000)
  }
}
防抖

用户在1s内连续点击两次。只执行最后一次。等一秒之后再执行。如果一秒内再次触发。则清除上次的执行timeout

比如再拖动窗口的时候。用户再一秒内可能改变了很多次窗口的大小。此时我只执行最后一次

function fn () {}
var timerId = null
button.onclick = function () {
  if(timerId) {
    window.clearTimeout(timerId)
  }
  timerId = setTimeout(() => {
    fn()
    timerId = null
  }, 1000)
}

手写一个AJAX
function ajax() {
  let request = new XMLHttpRequest()
  request.open('get', 'https://www.google.com') // 请求方式和请求路径
  request.onreadystatechange = () => { // 监听状态
    if (request.readyState === 4) { // 0:代理创建 1:open方法被调用 2:send方法被调用 3:下载中  4: 下载操作已完成
        if (request.status >= 200 && request.status <300) {
            let string = request.responseText
            let object = JSON.parse(string)
        }
    }
  }
  request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 设置请求头
  request.send(data) // 要传的参数  可以使用JSON.stringify()和JSON.parse()进行转换
}

this是什么

this


闭包/立即执行函数是什么?

「函数」和「函数内部能访问到的变量」(也叫环境)的总和,就是一个闭包。

function foo(){
  var local = 1
  function bar(){ // bar 和local就形成了闭包。此时我需要把bar返回出去。这样外面就能方问到里面的局部变量
    local++
    return local
  }
  return bar
}

var func = foo()
func()

或者

!function(){
  var lives = 50
  window.奖励一条命 = function(){
    lives += 1
  }
  window.死一条命 = function(){
    lives -= 1
  }
}()

在其他js文件中就能通过windown.奖励一条命等去操作局部变量 lives

(function(){alert('我是匿名函数')}) () //用括号把函数包起来
!function(){alert('我是匿名函数')}() // 求反,我们不在意值是多少,只想通过语法检查。 常用形式
+function(){alert('我是匿名函数')}()
-function(){alert('我是匿名函数')}()
~function(){alert('我是匿名函数')}()

立即执行函数的作用 创建一个独立的作用域。

var liList = ul.getElementsByTagName('li')
for(var i=0; i<6; i++){
  liList[i].onclick = function(){
    alert(i) // 为什么 alert 出来的总是 6,而不是 0、1、2、3、4、5。 因为i是全局变量
  }
}
var liList = ul.getElementsByTagName('li')
for(var i = 0; i< 6: i++) {
  !function(ii){
    liList.onclick = function() {
      alert(ii) // 0 1 2 3 4 5
    }
  }(i)
}

JSONP是什么

jsonp的核心是动态添加<script>标签来调用服务器提供的js脚本。

例子一

跨域服务器
文件:remote.js
代码:
alert('我是远程文件');

本地
<script type="text/javascript" src="跨域服务器/remote.js"></script>

例子二

跨域服务器

文件:remote.js
代码:
localHandler({"result":"我是远程js带来的数据"});

本地

<script type="text/javascript"> 
    var localHandler = function(data){
        alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result); 
    }; 
</script> 
<script type="text/javascript" src="跨域服务器/remote.js"></script>
例子三(我需要告诉服务器我的回调名称及参数)

跨域服务器

文件:flightResult.php
代码:
flightHandler({ "code":"CA1998", "price": 1780, "tickets": 5 });

本地

<script type="text/javascript"> 
    // 得到航班信息查询结果后的回调函数 
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
    }; 
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) 
    var url = "跨域服务器/flightResult.php?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性 
    var script = document.createElement('script'); 
    script.setAttribute('src', url); 
    // 把script标签加入head,此时调用开始 
    document.getElementsByTagName('head')[0].appendChild(script); 
</script>

CORS是什么

它允许浏览器向跨源服务器。
浏览器将CORS请求分成两类:简单请求非简单请求

只要同时满足以下两大条件,就属于简单请求。

  • 请求方法是以下三种方法之一:
    HEAD
    GET
    POST
  • HTTP的头信息不超出以下几种字段:
    Accept
    Accept-Language
    Content-Language
    Last-Event-ID
    Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。
Origin字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

GET /cors HTTP/1.1
Origin: http://api.bob.com // 来自哪里
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段(详见下文),就知道出错了,从而抛出一个错误,被XMLHttpRequestonerror回调函数捕获。

如果Origin指定的域名在许可范围内,服务器返回的响应,会多出几个头信息字段。

//它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
Access-Control-Allow-Origin: http://api.bob.com 该字段是必须的。
// 该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。
Access-Control-Allow-Credentials: true
withCredentials 属性

CORS请求默认不发送Cookie和HTTP认证信息。

一方面服务器端需要同意,设置
Access-Control-Allow-Credentials: true
另一方面前端开发设置
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

非简单请求

比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json

非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)

服务器收到"预检"请求以后,检查了Origin(来源)、Access-Control-Request-Method(请求方法)和Access-Control-Request-Headers(额外发送的头信息)字段以后,确认允许跨源请求,就可以做出回应。

一旦服务器通过了"预检"请求,以后每次浏览器正常的CORS请求,就都跟简单请求一样

深拷贝
JSON.parse(JSON.stringify())

能完成大部分数据得深拷贝。但存在问题

1.undefined、function、symbol这三种类型的值就是非安全的,所以格式化后,就被过滤掉了

  1. set、map这种数据格式的对象,也并没有被正确处理,而是处理成了一个空对象
  2. 循环引用报错
  3. 相同的引用会被重复复制

**写一个递归调用得函数进行深拷贝

function deepCopy(data) {
      if(typeof data !== 'object' || data === null){
          throw new TypeError('传入参数不是对象')
      }
      let newData = {};
      const dataKeys = Object.keys(data);
        dataKeys.forEach(value => {
        const currentDataValue = data[value];
        // 基本数据类型的值和函数直接赋值拷贝 
       if (typeof currentDataValue !== "object" || currentDataValue === null) {
            newData[value] = currentDataValue;
        } else if (Array.isArray(currentDataValue)) {
           // 实现数组的深拷贝
          newData[value] = [...currentDataValue];
        } else if (currentDataValue instanceof Set) {
           // 实现set数据的深拷贝
           newData[value] = new Set([...currentDataValue]);
        } else if (currentDataValue instanceof Map) {
           // 实现map数据的深拷贝
           newData[value] = new Map([...currentDataValue]);
        } else { 
           // 普通对象则递归赋值
           newData[value] = deepCopy(currentDataValue);
        } 
     }); 
    return newData;
}

测试数据

// 测试数据项
var data = {
  age: 18,
  name: "liuruchao",
  education: ["小学", "初中", "高中", "大学", undefined, null],
  likesFood: new Set(["fish", "banana"]),
  friends: [
    { name: "summer",  sex: "woman"},
    { name: "daWen",   sex: "woman"},
    { name: "yang",    sex: "man" }
  ], 
  work: { 
    time: "2019", 
    project: { name: "test",obtain: ["css", "html", "js"]} 
  }, 
  play: function() {console.log("玩滑板");}
}

如何用正则实现 trim()?

function trim(string){
    return string.replace(/^\s+|\s+$/g, '')
}

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

不用class

function Animal(name){ 
    this.name = name; 
    this.colors = ["red", "blue", "green"]; 
} 
 
Animal.prototype.sayName = function(){ 
    console.log(this.name); 
}

function Dog(name, age){   
    //继承属性 
    Animal.call(this, name); 
    this.age = age; 
} 
 
let f = function () {}
f.prototype = Animal.prototype

//继承方法 
Dog.prototype = new f();  
Dog.prototype.constructor = Dog; 
Dog.prototype.sayAge = function(){ 
    alert(this.age); 
}; 

用class实现继承

class Animal{
     constructor(color){
         this.color = color
     }
     move(){}
 }
 class Dog extends Animal{
     constructor(color, name){
         super(color)
         this.name = name
     }
     say(){}
 }

数组去重

  1. 利用indexOf实现去重。

indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (res.indexOf(arr[i]) === -1) {
            res.push(arr[i])
        }
    }
    return res
}
  1. 相邻元素去重

先用sort进行排序

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    arr = arr.sort()
    let res = []
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            res.push(arr[i])
        }
    }
    return res
}
  1. 使用set

set中的值是唯一的

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    return [...new Set(arr)]
}

DOM

事件冒泡、事件捕获、事件委托
<div class="father">
  <div class="child"></div>
</div>

用户点击,当father和child都存在点击事件时,先执行哪一个事件
事件冒泡认为应该先从子元素开始执行。往后面冒泡。
事件捕获则是从父元素开始执行。最后执行子元素。
event.stopPropagation()可组织事件冒泡或者捕获。
在子元素点击事件执行时添加stopPropagation就可以组织父元素的点击事件执行
addEventListener第三个参数可以设置事件冒泡或者事件捕获

 ul.addEventListener('click', function(e){
     if(e.target.tagName.toLowerCase() === 'li'){
         fn() // 执行某个函数
     }
 }) // 默认为false。事件冒泡

高阶版

当li里面有个span。点击了span

function delegate(element, eventType, selector, fn) {
     element.addEventListener(eventType, e => {
       let el = e.target
       while (!el.matches(selector)) {
         if (element === el) {
           el = null
           break
         }
         el = el.parentNode
       }
       el && fn.call(el, e, el)
     })
     return element
   }

HTTP

HTTP 状态码知道哪些?分别什么意思?
  1. 100 Continue
    这个临时响应表明,迄今为止的所有内容都是可行的,客户端应该继续请求,如果已经完成,则忽略它。
  2. 102 Processing
    此代码表示服务器已收到并正在处理该请求,但没有响应可用。
  3. 200 OK
    请求成功
  4. 201 Created
    该请求已成功,并因此创建了一个新的资源。这通常是在POST请求,或是某些PUT请求之后返回的响应。
  5. 204 No content
    服务器成功处理了请求,但不需要返回任何实体内容
  6. 301 Moved Permanently
    被请求的资源已永久移动到新位置.
  7. 302 Found
    请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。
  8. 400 Bad Request
    1、语义有误,当前请求无法被服务器理解。除非进行修改,否则客户端不应该重复提交这个请求。
    2、请求参数有误。
  9. 403 Forbidden
    服务器已经理解请求,但是拒绝执行它。权限
  10. 404 No Found
    请求失败,请求所希望得到的资源未被在服务器上发现。
  11. 500 Internal Server Error
    服务器遇到了不知道如何处理的情况。

2开头一般表示成功。3开头表示需要进一步的操作。4开头表示客户端错误。5开头表示服务器端错误。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 简述JS中this的指向和如何改变它的指向 javascript中,this是动态绑定的,它可以是全局对象、当前对...
    我是一小白白阅读 225评论 0 0
  • 一、谈谈Runtime 1、OC是一门动态性比较强的编程语言,允许很多操作推迟到程序运行时再进行 2、OC的动态性...
    奋斗的小马达阅读 285评论 0 1
  • 1、 [1,2,3].map(parseInt)输出结果? 答案:1,NaN,NaN 解析: ar...
    像鱼_真好听阅读 558评论 0 1
  • 小编费力收集:给你想要的面试集合 1.C++或Java中的异常处理机制的简单原理和应用。 当JAVA程序违反了JA...
    八爷君阅读 4,544评论 1 114
  • 面试题一:Java1.equals与==的区别:==是判断两个变量或实例是不是指向同一个内存空间 equals是判...
    请叫我财迷阅读 1,013评论 0 2