前端面试题

HTML相关

1、XHTML和HTML有什么区别

HTML是一种基本的WEB网页实际语言,XHTML是一种基于XML的置标语言

最主要的不同:

    1. XHTML 元素必须被正确的嵌套;
    1. XHTML 元素必须被关闭;
    1. XHTML 标签名必须用小写字母;
    1. XHTML 文档必须拥有根元素。

2、什么是语义化的HTML?

    1. 直观的认识标签,对于搜索引擎的抓取有好处,用正确的标签做正确的事。HTML语义化就是让页面的内容结构化,便于对浏览器、搜索引擎解析;
    1. 在没有css样式加持的情况下也以一种文档格式显示,并且是容易阅读的。搜索引擎的爬虫依赖于标记来确定上下文和各个关键字的权重,利于SEO。
    1. 使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解。

3、常见的浏览器内核有哪些?

    1. Trident内核 IE、360、搜狗等
    1. Gecko内核 Netscape6及以上版本、Firefox
    1. Presto内核 Opera7及以上
    1. Webkit Safari、Chrome等

4、H5有哪些新特性?移除了哪些元素?如何处理HTML5新标签的浏览器兼容问题?

新特性

    1. canvas绘图;
    1. 本地离线存储localStorage长期存储数据,浏览器关闭后数据不丢失;
    1. sessionStorage数据在浏览器关闭后会自动删除;
    1. 用于媒体回放的video和audio;
    1. 语义化更好的内容标签如article、footer、header、nav、setion;
    1. 表单控件 calendar、date、time、email、url、search;
    1. 新的技术 web worker、web socket、geolocation。

移除元素

    1. 纯表现元素 font、big、center、u、tt、s;
    1. 对可用性产生负面影响的元素:frame、frameset、noframes

兼容

IE8/IE7/IE6支持通过document.createElement方法产生的标签,可以利用这一特性让这些浏览器支持HTML5新标签。

5、如何实现浏览器内多个标签页之间的通信?

调用 localStroage、cookie 等本地存储方式

6、HTML5为什么只需要写!DOCTYPE HTML?

HTML5 不基于 SGML,因此不需要对DTD进行引用,但是需要doctype来规范浏览器的行为(让浏览器按照他们应该的方式来运行);而HTML4.0基于SGML,所以需要对DTD进行引用,才能告知浏览器文档所使用的文档类型。

7、Doctype作用?标准模式与兼容模式各有什么区别?

!DOCTYPE声明位于HTML文档中的第一行,处于html标签之前。告知浏览器的解析器用什么文档标准解析这个文档。DOCTYPE不存在或格式不正确会导致文档以兼容模式呈现。

标准模式的排版和JS运作模式都是以该浏览器支持的最高标准运行。在兼容模式中,页面以宽松的向后兼容的方式显示,模拟老式浏览器的行为以防止站点无法工作。

8、label的作用是什么?怎么用?

label标签是用来定义表单控制间的关系,当用户选择该标签时,浏览器会自动将焦点转到和标签相关的表单控件上。

用法:



or

CSS相关

1、如何居中div?如何居中一个浮动元素?

//居中div
margin: 0 auto

//居中浮动元素
float:left;
position:relative;
left:50%;

//居中绝对定位div
position:absolute; 
top: 50%; 
left: 50%;
margin:-100px 0px 0px -100

2、经常遇到的浏览器兼容性有哪些?简述原因和解决办法?

1)不同浏览器的标签,默认的margin和padding不同

解决方案:加一个全局的*{margin:0;padding:0;}来统一。

2)IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。

解决方案:在float的标签样式控制中加入 display:inline;将其转化为行内属性。

3)在IE6,IE7中元素高度超出自己设置高度。

原因:IE8以前的浏览器中会给元素设置默认的行高的高度导致的。

解决方案:加上overflow:hidden或设置line-height为更小的高度。

4)min-height在IE6下不起作用

解决方案:添加 height:auto !important;height:xxpx;其中xx就是min-height设置的值。

5)a(有href属性)标签嵌套下的img标签,在IE下会带有边框

解决方案:加上a img{border:none;}样式。

6)IE6下border:none无效

解决方案:用:border:0或border:0 none;或border:none:border-color:transparent;,推荐用第三种方案。

3、CSS3的新特性

  • 选择器(E:last-child)
  • @Font-face
  • 圆角
  • 多列布局
  • 阴影效果
  • 弹性盒子
  • 特效
  • 渐变效果

4、CSS优化、提高性能的方法有哪些?

  • 加载性能,不要用import、压缩等,减少文件体积,减少阻塞加载,提高并发
  • 选择器性能 建议使用ID,类选择器,避免属性,后代选择器,通用选择器。组合选择器,优化最右边的关键选择器。
  • 渲染性能 是不是大量使用了 text-shadow?是不是开了字体抗锯齿?CSS 动画怎么实现的?合理利用 GPU 加速了吗?
  • 可维护性能 命名合理吗?结构层次设计是否足够健壮?对样式进行抽象复用了吗?

5、简要说说CSS的元素分类?

  • 块级元素:div、h1、form、ul、li、p
  • 行内元素:span、a、label、input、img
  • CSS盒模型:内容、border、margin、padding

6、CSS清除浮动的几种方法

  • 父级 div 定义 height;
  • 父级 div 定义 display:table;
  • 结尾处使用带 clear 属性的空 div;
  • 使用 CSS 的 overflow 属性(hidden、auto);
  • 使用 CSS的 :after 伪元素。

7、display有哪些值?说明他们的作用。

  • block 块类型。默认宽度为父元素宽度,可设置宽高,换行显示。
  • none 缺省值。象行内元素类型一样显示。
  • inline 行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。
  • inline-block 默认宽度为内容宽度,可以设置宽高,同行显示。
  • list-item 象块类型元素一样显示,并添加样式列表标记。
  • table 此元素会作为块级表格来显示。
  • inherit 规定应该从父元素继承 display 属性的值。

8、position的值, relative和absolute分别是相对于谁进行定位的?

  • absolute 生成绝对定位的元素, 相对于最近一级的 定位不是 static 的父元素来进行定位。
  • fixed(老IE不支持)生成绝对定位的元素,通常相对于浏览器窗口或 frame 进行定位。
  • relative 生成相对定位的元素,相对于其在普通流中的位置进行定位。
  • static 默认值。没有定位,元素出现在正常的流中
  • sticky 生成粘性定位的元素,容器的位置根据正常文档流计算得出

9、CSS引入的方式有哪些? link和@import的区别是?

内联 内嵌 外链 导入

区别:同时加载

前者无兼容性,后者CSS2.1以下浏览器不支持
Link 支持使用javascript改变样式,后者不可

10、CSS选择器 ~ 和 + 有什么区别?

~ 匹配所有兄弟元素,+ 匹配紧挨着的兄弟元素。

另外:> 匹配所有子元素,(空格) 匹配所有后代元素。

11、CSS中的常见单位?

    1. px: 绝对单位,页面按精确像素展示;
    1. em: 相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算,整个页面内1em不是一个固定的值;
    1. rem: 相对单位,可理解为“root em”,相当于根节点html的字体大小来计算。
    1. vm: viewpoint width,视窗宽度,1vm等于视窗宽度的1%;
    1. vh: viewpoint height,视窗高度,1vh等于视窗高度的1%。

JS相关

1、谈一谈JavaScript作用域链

当执行一段 JavaScript 代码(全局代码或函数)时,JavaScript 引擎会为其创建一个作用域(又称为执行上下文),在页面加载后会首先创建一个全局作用域,然后每执行一个函数,会建立一个对应的作用域,从而形成一条作用域链。每个作用域都有一条对应的作用域链,链头是全局作用域,链尾是当前函数作用域。

作用域链的作用是用于解析标识符,当函数被创建时(不是被执行),会将this、arguments、命名参数和该函数中所有局部变量添加到当前作用域中。当JavaScript需要查找变量x的时候(这个过程被称为解析),它首先会从作用域链中的链尾(也就是当前作用域)进行查找是否有x属性,如果没有找到就顺着作用域链继续查找,直到查找到链头(也就是全局作用域链),仍未找到该变量的话,就认为这段代码的作用域链上不存在x变量,并抛出一个引用错误的异常。

2、原型是什么?原型链是什么?

JavaScript中的每个对象都有一个prototype属性,我们称之为原型,而原型的值也是一个对象,因此它也有自己的原型,这样就串联起来了一条原型链,原型链的链头是object,它的prototype比较特殊,值为null。

原型链的作用是用于对象继承,函数A的原型属性(prototype property)是一个对象,当这个函数被用作构造函数来创建实例时,该函数的原型将被作为原型赋值给所有实例对象,比如我们创建一个数组,数组的方法便从数组的原型上继承而来。

原型五项规则

    1. 所有的引用类型(数组、对象、函数),都具有对象特性,即可自由扩展属性(除了null除外)
    1. 所有的引用类型(数组、对象、函数),都有一个 __proto__(隐式原型)属性,属性值是一个普通的对象;
    1. 所有的函数,都有一个prototype(显式原型)属性,属性值也是一个普通的对象;
    1. 所有的引用类型(数组、对象、函数),__proto__ 属性值指向它的构造函数的prototype属性值;
    1. 当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__(即它的构造函数的prototype)中寻找。

3、构造函数,原型对象,实例对象三者之间的关系

每创建一个函数,该函数都会自动带有一个prototype属性。该属性是一个指针,指向一个对象,该对象称之为原型对象。

原型对象上默认有一个属性constructor,该属性也有一个指针,指向其关联的构造函数。

通过调用构造函数产生的实例对象,都拥有一个内部属性,指向了原型对象。其实例对象能够访问原型对象上的所有对象和方法。

总结:三者的关系是,每个构造函数都有一个原型对象,原型对象上包含着一个指向构造函数的指针,而实例都包含着一个指向原型对象的内部指针。通俗的讲,实例可以通过内部指针访问到原型对象,原型对象可以通过constructor找到构造函数。

4、什么是闭包?闭包的作用?

闭包就是函数中的函数,里面的函数可以访问外面函数的变量,外面的变量是这个内部函数的一部分。

闭包就是函数能够记住并访问它的词法作用域,即使当这个函数在它的词法作用域之外执行时。

闭包作用

    1. 使用闭包可以访问函数中的变量;
    1. 可以将变量长期保存在内存中,生命周期比较长。

闭包使用场景

    1. 函数作为返回值
    1. 函数作为参数传递

闭包不能滥用,否则会导致内存泄漏,影响网页的性能。闭包使用完成后,要立即释放资源,将引用变量指向 null 。

4、JSON是什么

JSON(JavaScript Object Notation)是一种轻量级的数据交换格式。它是基于 JavaScript 的一个子集。数据格式简单,易于读写,占用宽带小。是前后台交互最常见的一种数据格式。JSON也只不过就是一个js对象而已

常用方法

JSON.stringify({name: 'xiaoxin', age: 20}) //对象转为字符串
JSON.parse('{name: \'xiaoxin\', age: 20}') //字符串转为对象

5、JavaScript有几种类型的值?区别是什么?

两大类

  • 栈: 原始数据类型(Undefined、Null、Boolean、Number、String、Symbol);
  • 堆: 引用数据类型(Object、Array、Function)

区别

原始数据类型 直接存储在栈(stack)中的简单数据段,占用空间小、大小固定,属于被频繁使用数据。

引用数据类型 存储在堆(heap)中的对象,占用空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,首先会检索其在栈中的地址,然后从堆中获取实体。

6、谈谈对this的理解?

this 表示当前对象,this 的指向是根据调用的上下文来决定的,默认指向 window 对象,指向 window 对象时可以省略不写,例如

this.alert() === window.this.alert() === alert()

,调用的上下文环境包括全局和局部。

执行时才能确认值,定义时无法确认

全局环境 就是在中,这里的 this 始终指向的是 window 对象;

局部环境

    1. 在全局作用域下直接调用函数,this 指向 window(普通执行);
    1. 对象函数调用,哪个函数调用就指向哪个对象(对象属性执行);
    1. 使用 new 实例化对象,在构造函数中 this 指向实例化对象(构造函数执行);
    1. 使用 call 或 apply 可以改变 this 的指向。

7、同步和异步的区别?

同步是一种线性执行的方式,执行的流程不能跨越。一般用于流程性比较强的程序,比如用户登录;

异步是一种并行处理的方式,不必等待一个程序执行完,就可以执行其它任务。在程序中异步处理的结果通常使用回调函数来处理结果。在 JavaScript 中实现异步的方式一般是 Ajax 和 H5 新增的 Web Worker

    1. 同步会阻塞代码执行,而异步不会
    1. alert是同步,setTimeOut是异步

何时需要异步?

    1. 在可能发生等待的情况
    1. 等待过程中不能像alert一样阻塞程序运行

因此,所有的“等待的情况”都需要异步

前端使用异步的场景?

    1. 定时任务:setTimeOut、setInterval
    1. 网络请求:ajax请求、动态img加载
    1. 事件绑定

8、call和apply的区别?

相同点 两个方法产生的作用是一样的,都用来改变当前函数调用的对象;

不同点 调用的参数不同,

foo.call(this, arg1, arg2, arg3) == foo.apply(this, args) == this.foo(arg1, arg2, arg3)

9、eval是做什么的?

把字符串参数解析成JS代码运行,并返回执行的结果。

10、new操作符干了什么?

    1. 创建一个空对象 var obj = new Object();
    1. 设置原型链obj.__proto__ = Function.prototype;
    1. 让 Function 中的 this 指向 obj,并执行 Function 的函数体 var result = Function.call(obj);
    1. 判断 Function 的返回值类型,如果是值类型,返回 obj,如果是引用类型,就返回引用类型的对象。

11、造成JS内存泄漏的情况?

  • 全局变量
  • 闭包
  • DOM被清空时,事件未被清除
  • 子元素存在引用

12、写出下列结果?

console.log(null == NaN); //false
console.log(null == undefined); //true
console.log(null == false); //false
console.log(false == ''); //true
console.log(false == 0); //true
console.log(2 + 1 + '3'); //33
console.log('2' + 1 + 3); //213
console.log(Number(undefined)); //NaN
console.log(Number(NaN)); //NaN
console.log(Number(null)); //0
console.log(Number('')); //0
console.log(Number('123')); //123
console.log(isNaN(23)); //false
console.log(isNaN(NaN)); //true
console.log(isNaN(undefined));//true
console.log(isNaN(null)); //false
console.log(typeof NaN); //number
console.log(typeof '123'); //string
console.log(typeof undefined); //undefined
console.log(typeof 123); //number
console.log(typeof null); //object
console.log(typeof []); //object
console.log(typeof Array); //function
console.log(typeof console.log); //function
console.log(NaN == NaN); //false
console.log(undefined == undefined); //true

13、JS绑定事件的方法?

1)在DOM上直接绑定


 

2)在JavaScript代码中绑定事件


 

3)使用事件监听绑定

W3C标准语法:

element.addEventListener(event, function, useCapture)

  • event(必选)事件名,支持所有DOM事件;
  • function(必选)指定事件触发后执行的函数;
  • useCapture(可选)指定事件是否在捕获或冒泡阶段执行。true,捕获;false,冒泡(default);

 

IE标准语法:

element.attachEvent(event, function)

  • event(必须)事件类型,需要加“on”,例如“onClick”
  • function(必选)指定事件触发后执行的函数

14、JavaScript事件流机制?

1)冒泡型机制

事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发

2)捕获型机制

事件从最不精确的对象(document对象)开始触发,然后到最精确。

3)DOM事件流

同时支持两种事件模型:捕获型事件和冒泡型事件,但是捕获型事件先发生。两种事件都会触发DOM中的所有对象,从document对象开始,也在document对象结束。

事件捕获机制:事件从最上一级标签开始往下查找,直到捕获到事件目标;

事件冒泡机制:事件从事件目标开始,往上冒泡直到页面的最上一级标签。

事件的传播是可以阻止的:

  • 在W3C中,使用stopPropagation()方法;
  • 在IE下设置cancelBubble = true;

在捕获的事件中stopPropagation()后,后面的冒泡过程也不会发生了

阻止事件的默认行为:

  • 在W3C中,使用preventDefault()方法;
  • 在IE下设置window.event.returnValue = false

不是所有事件都能冒泡,例如:blur、focus、load、unload等

普通事件和事件绑定的区别?

普通事件的方法不支持添加多个,最下面的事件会覆盖上面的;事件绑定可以添加多个

15、JavaScript实现继承的几种方式?

//父类
function Animal(name) {
  this.name = name || 'Animal';

  this.sleep = function () {
    console.log(this.name + ' sleep');
  };
}
Animal.prototype.eat = function (food) {
  console.log(this.name + ' eating ' + food)
};

//原型链继承
function Cat() {
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';

//构造继承(不能继承原型方法)
function Cat(name) {
  Animal.call(this);
  this.name = name || 'Tom';
}

//实例继承
function Cat(name) {
  const instance = new Animal();
  instance.name = name || 'Tom';
  return instance;
}

//拷贝继承
function Cat(name) {
  const animal = new Animal();
  for (let p in animal) {
    Cat.prototype[p] = animal[p];
  }
  Cat.prototype.name = name || 'Tom';
}

16、简要说明对模块化开发的理解?

所谓模块化开发就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能。模块化开发的基础就是函数。

17、Ajax的工作原理?写一个Ajax请求?

Ajax的工作原理相当于在用户和服务器之间加了一个中间件(Ajax引擎),是用户操作与浏览器响应异步化。

const xhr = new XMLHttpRequest();
xhr.open('get', '/api', false);
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) { // 0 请求未初始化 1 请求已建立 2 请求已发送 3 请求处理中 4 响应已完成
        if (xhr.status == 200) { // 2xx 请求成功 3xx 请求重定向 4xx 客户端错误 5xx 服务端错误
            console.log(xhr.responseText)
        }
    }
};
xhr.send(null);

18、写出两种单例模式的实现?

//自变量
const singleton = {
    attr: 1,
    method: function () {
        return this.attr;
    }
};

//构造函数内部判断
function Construct() {
    if(Construct.unique !== undefined){
        return Construct.unique;
    }
    this.name = 'name';
    this.age = 24;
    Construct.unique = this;
}

19、ES6中Array.isArray的代码实现?

Array.isArray = function(obj) {
    return Object.prototype.toString.call(obj) == '[object Array]';
}

20、window.onload 和 DOMContentLoaded 区别

  • window.onload 页面的全部资源加载完才会执行,包括图片、视频等
  • DOMContentLoaded DOM渲染完即可执行,此时图片、视频还没有加载完

21、随机打印1-100间的10个数字,去重后取出该10个数字之间的最大值和最小值。

function randomMaxMin() {
  const numbers = [...new Set([...new Array(10)].reduce(origin => {
    origin.push(Math.ceil(Math.random() * 100));
    return origin;
  }, []))].sort((a, b) => a - b);
  return {min: numbers[0], max: numbers[numbers.length - 1]};
}

22、写一个长度一致的随机数

let random = Math.random() + '0000000000';
random = random.slice(0, 10);

23、写一个能遍历数组和对象的forEach函数

function forEach(obj, fn) {
  if (obj instanceof Array) {
    obj.forEach((item, index) => fn(index, item));
  } else {
    Object.keys(obj).forEach(key => fn(key, obj[key]));
  }
}
forEach({name: 'pp', age: 20}, (key, value) => {});
forEach([1,2,3], (index, item) => {});

24、写一个闭包的使用场景

function isFirstLoad() {
  const _list = [];
  return function (id) {
    if(_list.indexOf(id) >= 0){
      return false;
    }else{
      _list.push(id);
      return true;
    }
  };
}
const firstLoad = isFirstLoad();
console.log(firstLoad(10)); //true
console.log(firstLoad(10)); //false
console.log(firstLoad(20)); //true
console.log(firstLoad(20)); //false

25、动态创建10个标签,点击弹出对应的序号

for (var i = 0; i < 10; i++) {
  (function (i) {
    var a = document.createElement('a');
    a.innerHTML = 'aaa' + (i + 1) + '
'; a.addEventListener('click', function (e) { e.preventDefault(); alert(i + 1); }); document.body.appendChild(a); })(i); }

最简单的方式用 let 替换 var 进行定义。

26、写一个原型继承的案例

function Elem(id) {
  this.elem = document.getElementById(id);
}
Elem.prototype.html = function (val) {
  const elem = this.elem;
  if(val){
    elem.innerHTML = val;
    return this;
  }else{
    return elem.innerHTML;
  }
};
Elem.prototype.on = function (type, fun) {
  const elem = this.elem;
  elem.addEventListener(type, fun);
  return this;
};

//exec
const div1 = new Elem('app');
div1.html('

Hello

').on('click', function () { alert('hello'); }).html('

peter

');

27、编写一个通用的事件监听函数?

function bindEvent(elem, type, selector, fn) {
  if (fn == null) {
    fn = selector;
    selector = null;
  }
  elem.addEventListener(type, function (e) {
    if (selector) {
      //代理
      const target = e.target;
      if (target.matches(selector)) {
        fn.call(target, e);
      }
    } else {
      //不是代理
      fn(e);
    }
  });
}

const div1 = document.getElementById('div1');
bindEvent(div1, 'click', 'a', function (e) {
  e.preventDefault();
  console.log(this.innerHTML);
});

const p1 = document.getElementById('p1');
bindEvent(p1, 'click', function () {
  console.log(p1.innerHTML);
});

28、js写一个冒泡排序算法

//冒泡排序
function bubble() {
  const arr = [3, 1, 2, 4];
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i - 1; j++) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  console.log(arr);
}
bubble(); //[1, 2, 3, 4]

29、JS写一个选择排序算法

//选择算法
function selection() {
  const arr = [3, 1, 2, 4];
  for (let i = 0; i < arr.length - 1; i++) {
    let min = i;
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[min]) {
        min = j;
      }
    }
    [arr[i], arr[min]] = [arr[min], arr[i]];
  }
  console.log(arr);
}
selection(); //[1, 2, 3, 4]

30、JS写一个插入排序算法


//插入排序
function insertion() {
  const arr = [3, 1, 2, 4];
  for (let i = 1; i < arr.length; i++) {
    for (let j = i - 1; j >= 0; j--) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }  
  console.log(arr);
}
insertion(); //[1, 2, 3, 4]

31、写一个二分法的函数,返回给定值的索引

//二分法找索引
function dichotomy(arr, val) {
  let start = 0, end = arr.length - 1;
  while (start < end) {
    let middle = end == 1 ? 0 : Math.floor((start + end + 1) / 2);
    if (arr[middle] > val) {
      end = middle;
    } else if (arr[middle] < val) {
      start = middle;
    } else {
      return middle;
    }
  }
  return -1;
}
console.log(dichotomy([2,3,4,5], 3)); //1

32、现有一个URL字符串“http://www.xxx.com?pn=0”,请写出删除其中的pn属性的js代码,请尽量实现完整,考虑全面。

const arr = url.split('?');
const new_url = arr[0] + '?' + arr[1].split('&')
    .reduce((origin, item) => {
      (item.split('=')[0] != 'pn') && origin.push(item);
      return origin;
    }, []).join('&');
console.log(new_url); //http://www.xxx.com

33、写一个函数,计算100以内的质数(只能被1或本身整除的数)。

const calcPrimeNumbers = sum => (
  [...new Array(sum)].reduce((origin, item, index) => {
    const [number, arr] = [++index, []];
    for (let i = 1; i <= number; i++) {
      number % i == 0 && arr.push(i);
    }
    arr.length == 2 && origin.push(number);
    return origin;
  }, [])
);
console.log(calcPrimeNumbers(100)); //[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 ]

34、用 JS 实现一个无限累加的函数 add

function add() {
  let sum = [...arguments].reduce((a, b) => a + b);

  const foo = function () {
    sum += [...arguments].reduce((a, b) => a + b);
    return foo;
  };

  foo.toString = () => sum;

  return foo;
}
console.log(add(1)(2)(3)(4)); // 10
console.log(add(1,1)(2,2)(3,3)(4,4)); // 20

35、手动实现一个sleep函数?

function sleep(time) {
  const start = Date.now();
  while (true) {
    if(Date.now() - time > start)
    break;
  }
  console.log('休息了' + time / 1000 + '秒')
}

sleep(3000); //休息了3秒

36、普通函数和箭头函数的区别?

    1. 箭头函数是匿名函数,不能作为构造函数,不能使用 new;
    1. 箭头函数不绑定 arguments,取而代之用rest参数(...)解决;
    1. 箭头函数不绑定 this,会捕获其所在的上下文的 this 值,作为自己的 this 值;
    1. 箭头函数没有原型属性。

37、如何发送携带cookie的跨域请求?

设置 withCredentials = true;

38、根据id快速查找对应的元素

const tree = {
  id: 'root',
  children: [
    { id: 1, children: [] },
    { id: 2, children: [] },
    { id: 3, children: [] },
    {
      id: 4,
      children: [
        { id: 5, children: [] },
      ]
    },
  ]
};

function find(id, node = tree) {
  if (node.id == id) {
    return node.children;
  }

  let target;
  node.children.forEach(child => {
    if (child.id == id) {
      target = child.children;
    } else {
      find(child.id, child);
    }
  });
  return target;
}

console.log(find(1)); // []

39、实现对数组进行乱序

var arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];

var sign = 1;

arr.sort((a, b) => {
  sign = Math.random() > 0.5 ? 1 : -1;
  return (a - b) * sign;
});

console.log(arr);

40、计算长度为100的数组前10个元素之和。

var arr = [...new Array(100)].map((item, i) => i + 1);
var result = arr.slice(0, 10).reduce((pre, current) => pre + current);
console.log(result); // 55

41、手动实现一个bind函数

Function.prototype.myBind = function (oThis) {
  let args = [...arguments].slice(1);
  const context = this;
  const bound = function () {
    args = [...args, ...arguments];
    return context.apply(this instanceof F && oThis ? this : oThis, args);
  };
  const F = function () {
  };
  F.prototype = context.prototype;
  bound.prototype = new F();
  return bound;
};

function read(name, time, book) {
  console.log(`${name} is reading ${book} at ${time}`)
}

const tomRead = read.myBind(this, 'Tom', 'morning');
tomRead('三体'); // Tom is reading 三体 at morning

42、手动实现一个深拷贝

function copy(obj) {
  const result = obj instanceof Array ? [] : {};
  for (let item in obj) {
    if (typeof obj[item] == 'object') {
      result[item] = copy(obj[item]);
    } else {
      result[item] = obj[item];
    }
  }
  return result;
}

6、HTTP状态码分别表示什么?

2xx 成功

  • 200 OK,表示从客户端发来的请求在服务器端被正确处理
  • 204 No content,表示请求成功,但响应报文不含实体的主体部分
  • 205 Reset Content,表示请求成功,但响应报文不含实体的主体部分,但是与 204 响应不同在于要求请求方重置内容
  • 206 Partial Content,进行范围请求

3xx 重定向

  • 301 moved permanently,永久性重定向,表示资源已被分配了新的 URL
  • 302 found,临时性重定向,表示资源临时被分配了新的 URL
  • 303 see other,表示资源存在着另一个 URL,应使用 GET 方法获取资源
  • 304 not modified,表示服务器允许访问资源,但因发生请求未满足条件的情况
  • 307 temporary redirect,临时重定向,和302含义类似,但是期望客户端保持请求方法不变向新的地址发出请求

4xx 客户端错误

  • 400 bad request,请求报文存在语法错误
  • 401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息
  • 403 forbidden,表示对请求资源的访问被服务器拒绝
  • 404 not found,表示在服务器上没有找到请求的资源

5xx 服务端错误

  • 500 internal sever error,表示服务器端在执行请求时发生了错误
  • 501 Not Implemented,表示服务器不支持当前请求所需要的某个功能
  • 503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求

details

  • 100 Continue 初始的请求已经接受,客户应当继续发送请求的其余部分
  • 101 Switching Protocols 服务器将遵从客户的请求转换到另外一种协议
  • 200 OK 一切正常,对GET和POST请求的应答文档跟在后面
  • 201 Created 服务器已经创建了文档,Location头给出了它的URL。
  • 202 Accepted 已经接受请求,但处理尚未完成。
  • 203 Non-Authoritative Information 文档已经正常地返回,但一些应答头可能不正确,因为使用的是文档的拷贝
  • 204 No Content 没有新文档,浏览器应该继续显示原来的文档。如果用户定期地刷新页面,而Servlet可以确定用户文档足够新,这个状态代码是很有用的
  • 205 Reset Content 没有新的内容,但浏览器应该重置它所显示的内容。用来强制浏览器清除表单输入内容
  • 206 Partial Content 客户发送了一个带有Range头的GET请求,服务器完成了它
  • 300 Multiple Choices 客户请求的文档可以在多个位置找到,这些位置已经在返回的文档内列出。如果服务器要提出优先选择,则应该在Location应答头指明。
  • 301 Moved Permanently 客户请求的文档在其他地方,新的URL在Location头中给出,浏览器应该自动地访问新的URL。
  • 302 Found 类似于301,但新的URL应该被视为临时性的替代,而不是永久性的。
  • 303 See Other 类似于301/302,不同之处在于,如果原来的请求是POST,Location头指定的重定向目标文档应该通过GET提取
  • 304 Not Modified 客户端有缓冲的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户只想比指定日期更新的文档)。服务器告诉客户,原来缓冲的文档还可以继续使用。
  • 305 Use Proxy 客户请求的文档应该通过Location头所指明的代理服务器提取
  • 307 Temporary Redirect和302(Found)相同。许多浏览器会错误地响应302应答进行重定向,即使原来的请求是 POST,即使它实际上只能在POST请求的应答是303时才能重定向。由于这个原因,HTTP 1.1新增了307,以便更加清除地区分几个状态代码: 当出现303应答时,浏览器可以跟随重定向的GET和POST请求;如果是307应答,则浏览器只能跟随对GET请求的重定向。
  • 400 Bad Request 请求出现语法错误。
  • 401 Unauthorized 客户试图未经授权访问受密码保护的页面。应答中会包含一个WWW-Authenticate头,浏览器据此显示用户名字/密码对话框,然后在填写合适的Authorization头后再次发出请求。
  • 403 Forbidden 资源不可用。
  • 404 Not Found 无法找到指定位置的资源
  • 405 Method Not Allowed 请求方法(GET、POST、HEAD、Delete、PUT、TRACE等)对指定的资源不适用。
  • 406 Not Acceptable
    指定的资源已经找到,但它的MIME类型和客户在Accpet头中所指定的不兼容
  • 407 Proxy Authentication Required
    类似于401,表示客户必须先经过代理服务器的授权。
  • 408 Request Timeout 在服务器许可的等待时间内,客户一直没有发出任何请求。客户可以在以后重复同一请求。
  • 409 Conflict 通常和PUT请求有关。由于请求和资源的当前状态相冲突,因此请求不能成功。
  • 410 Gone 所请求的文档已经不再可用,而且服务器不知道应该重定向到哪一个地址。它和404的不同在于,返回407表示文档永久地离开了指定的位置,而404表示由于未知的原因文档不可用。
  • 411 Length Required 服务器不能处理请求,除非客户发送一个Content-Length头。
  • 412 Precondition Failed 请求头中指定的一些前提条件失败
  • 413 Request Entity Too Large 目标文档的大小超过服务器当前愿意处理的大小。如果服务器认为自己能够稍后再处理该请求,则应该提供一个Retry-After头
  • 414 Request URI Too Long URI太长
  • 416 Requested Range Not Satisfiable 服务器不能满足客户在请求中指定的Range头
  • 500 Internal Server Error 服务器遇到了意料不到的情况,不能完成客户的请求
  • 501 Not Implemented 服务器不支持实现请求所需要的功能。例如,客户发出了一个服务器不支持的PUT请求
  • 502 Bad Gateway 服务器作为网关或者代理时,为了完成请求访问下一个服务器,但该服务器返回了非法的应答
  • 503 Service Unavailable 服务器由于维护或者负载过重未能应答。例如,Servlet可能在数据库连接池已满的情况下返回503。服务器返回503时可以提供一个Retry-After头
  • 504 Gateway Timeout 由作为代理或网关的服务器使用,表示不能及时地从远程服务器获得应答
  • 505 HTTP Version Not Supported 服务器不支持请求中所指明的HTTP版本

你可能感兴趣的:(前端面试题)