前端(JS)

前端面试题(js)

var、let、const区别

  1. var存在变量提升,而let、const没有
  2. let、const有块级作用域,而var没有
  3. var 在同一块作用域可以重复声明多个相同的变量,后者覆盖前者,let、const重复声明会报错
    4.let、var声明变量后可以进行改变值,const声明不能修改([对象、数组]的属性和方法可以改变

合并对象的方法可以写几种

const obj1 = {a:‘a’,b:‘b’,c:‘c’};
const obj2 = {c:‘c’,d:‘d’,e:‘e’};
方式一:使用ES6的拓展运算符
{…obj1,…obj2}
方式二:Object.assign(obj1,obj2);
方式三:手写遍历
function assign(obj1,obj2){
for(let key in obj2){
obj1[key] = obj2[key];
}
return obj1;
}
assign(obj1,obj2);

三. find,filter,some和every的区别

  1. find 条件符合就找到第一个符合的元素返回,否则返回 undefined
  2. filter 如果条件符合 就返回一个新的数组(多个元素),否则返回空数组[]
  3. every()是对数组中每一项运行给定函数,如果该函数对每一项返回true,则返回true。 有点&&的意思
  4. some()是对数组中每一项运行给定函数,如果该函数对任一项返回true,则返回true。有点||的意思

四.延迟加载JS有哪些方式

  1. defer 是等html全部解析完成,才会执行js代码,顺次执行js脚本。
  2. async 是和html解析同步的(并行的),不是顺次执行js脚本(谁先加载完谁先执行)
  3. 使用js动态创建

五.原型链

  1. 原型可以解决什么问题:解决了对象的共享属性、方法
  2. 谁有原型:函数拥有prototype、对象拥有__proto__
  3. 对象查找属性或者方法的顺序
    先在对象本身查找 > 构造函数中查找 > 对象的原型 > 构造函数的原型中 > 当前原型的原型中查找
  4. 原型链的最顶端是null在这里插入图片描述

localstorage、sessionstorage、cookie的区别

一、存储的时间有效期不同
1、cookie的有效期是可以设置的,默认的情况下是关闭浏览器后失效
2、sessionStorage的有效期是仅保持在当前页面,关闭当前会话页或者浏览器后就会失效
3、localStorage的有效期是在不进行手动删除的情况下是一直有效的

二、存储的大小不同
1、cookie的存储是4kb左右,存储量较小,一般页面最多存储20条左右信息
2、localStorage和sessionStorage的存储容量是5Mb(官方介绍,可能和浏览器有部分差异性)

三、与服务端的通信
1、cookie会参与到与服务端的通信中,一般会携带在http请求的头部中,例如一些关键密匙验证等。
2、localStorage和sessionStorage是单纯的前端存储,不参与与服务端的通信

JS微任务和宏任务

  1. js是单线程的语言。
  2. js代码执行流程:同步执行完==>事件循环
    同步的任务都执行完了,才会执行事件循环的内容
    进入事件循环:请求、定时器、事件…
  3. 事件循环中包含:【微任务、宏任务】
    微任务:promise.then
    宏任务:setTimeout…
    要执行宏任务的前提是清空了所有的微任务
    流程:同步 > 事件循环【微任务和宏任务】> 微任务 > 宏任务 > 微任务…

什么是函数柯里化

答:是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数而且返回结果的新函数的技术。

把接受多个参数的函数转换成接受一个单一参数的函数

// 普通方法varadd =function(x, y){returnx + y;} add(3,4)//7

// 柯里化 var foo = function(x) {

returnfunction(y){returnx + y }} foo(3)(4)// 7

什么是Promise对象,有哪些用法

答: Promise对象的定义

Promise是异步编程的一种解决方案,它是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise

是一个对象,从它可以获取异步操作的消息。可以用来解决“回调地狱”的问题。Promise 提供统一的

API,各种异步操作都可以用同样的方法进行处理。promise对象是一个构造函数,用来生成Promise实例; Promise对象的特点

(1)对象的状态不受外界影响,promise对象代表一个异步操作,有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态,这也是promise这个名字的由来“承若”;

(2)一旦状态改变就不会再变,任何时候都可以得到这个结果,promise对象的状态改变,只有两种可能:从pending变为fulfilled,从pending变为rejected。这时就称为resolved(已定型)。如果改变已经发生了,你再对promise对象添加回调函数,也会立即得到这个结果,这与事件(event)完全不同,事件的特点是:如果你错过了它,再去监听是得不到结果的。

有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。

Promise也有一些缺点。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。第三,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

Promise对象的用法

是一个构造函数,这个构造函数里有两个参数,分别是:resolve(成功之后的回调函数)、reject(失败之后的回调函数)。

因为promise表示的是一个异步操作,每当我们new一个promise实例,就表示一个具体的异步操作,那么这个异步操作的结果就只能有两种状态:成功/失败,两者都需要回调函数resolve/reject返回。所以内部拿到操作的结果后,无法使用return把操作结果返回给调用者,这时候只能用回调函数的形式来把成功或失败的结果返回给调用者。

promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数
then方法可以接受连个回调函数作为参数,第一个回调函数是promise对象的状态变为resolved时调用,第二个回调函数是promise对象的状态变为rejected时调用,其中,第二个函数是可选的,不一定要提供,这两个函数都接受promise对象传出的值作为参数;

*通过。then指定回调函数的时候,成功的回调函数必须传,失败的回调函数可以胜利。 如果前面的promise执行失败,不详影响后续操作终止,捕获异常的两种方式: ①可以为每个promise指定失败回调;

function(err){ console.log(……) }) ②最后加catch(function(err){

console.log(……) })//表示如前面有任意一个有报错,立即报错,并终止后面的;如果前面无报错,前面正常执行。

4.如何通过Promise对象实现ajax?
getJSON是对XMLHTTPRequest对象的封装,用于发出一个针对JSON数据的HTTP请求,并且返回一个promise对象,需要注意的是,在getJSON内部,resolve函数和reject函数调用时,都带有参数;

如果调用resolve函数和reject函数时带有参数,那么他们的参数会被传递给回调函数,reject函数的参数通常是Error对象的实例,表示抛出的错误,resolve函数的参数除了正常的值以外,还可以是另一个promise实例;

什么是REST,用起来有什么好处

答:

REST是一种设计API的模式。最常用的数据格式是JSON。由于JSON能直接被JavaScript读取,所以,以JSON格式编写的REST风格的API具有简单、易读、易用的特点。通过REST模式设计的API可以把web

app 全部功能进行封装,可以很容易的实现前后端分离,使的前端代码易编写,后端代码易测试。

一直在测试REST模式的WEB SERVICE接口,客户端的HTTP的请求方式一般分为四种:GET、POST、PUT、DELETE,这四种请求方式有什么不同呢。简单的说,GET就是获取资源,POST就是创建资源,PUT就是更新资源,DELETE就是删除资源。具体来说:

PUT:PUT请求是向服务器端发送数据的,从而改变信息,该请求就像数据库的update操作一样,用来修改数据的内容,但是不会增加数据的种类等,也就是说无论进行多少次PUT操作,资源不会增加。

DELETE:DELETE请求顾名思义,就是用来删除某一个资源的,该请求就像数据库的delete操作。

GET:GET操作是安全的。所谓安全是指不管进行多少次操作,资源的状态都不会改变,GET只是访问和查看资源。

POST:操作不是安全的,每次请求都会创建资源,当我们多次发出POST请求后,其结果是创建出了多个资源。还有一点需要注意的就是,创建操作可以使用POST,也可以使用PUT,区别在于POST 是作用在一个集合资源之上的(/uri),而PUT操作是作用在一个具体资源之上的(/uri/xxx),再通俗点说,如果URL可以在客户端确定,那么就使用PUT,如果是在服务端确定,那么就使用POST,比如说很多资源使用数据库自增主键作为标识信息,而创建的资源的标识信息到底是什么只能由服务端提供,这个时候就必须使用POST。

下面说说GET和POST的区别:

1、GET请求的数据会附在URL之后(就是把数据放置在HTTP协议头中),以?分割URL和传输数据,参数之间以&相连,如:getCitycode?lat=100.22&lon=35.33

POST把提交的数据则放置在是HTTP包的包体中。

2、在浏览器上,GET方式提交的数据是有限制的,例如有时候请求的URL太长,会返回错误;但如果是客户端GET请求,是没有数据的限制的。POST没有限制,可传较大量的数据。

3、POST的安全性要比GET的安全性高。这里所说的安全性和上面GET提到的“安全”不是同个概念。上面“安全”的含义仅仅是不作数据修改,而这里安全的含义是真正的Security的含义,比如:通过GET提交数据,用户名和密码将明文出现在URL上,查看浏览器的历史纪录,就可以查看到GET请求的参数,比如登录的帐号密码、搜索关键字、个人信息等。

PUT和POST方法语义中都有修改资源状态的意思,因此都不是安全的。但是PUT方法是幂等的,POST方法不是幂等的,这么设计的理由是:

HTTP协议规定,POST方法修改资源状态时,URL指示的是该资源的父级资源,待修改资源的ID信息在请求体中携带。而PUT方法修改资源状态时,URL直接指示待修改资源。因此,同样是创建资源,重复提交POST请求可能产生两个不同的资源,而重复提交PUT请求只会对其URL中指定的资源起作用,也就是只会创建一个资源。

.闭包

  1. 闭包是什么
    闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量。
  2. 闭包可以解决什么问题【闭包的优点】
    2.1 内部函数可以访问到外部函数的局部变量
    2.2 闭包可以解决的问题
    var lis = document.getElementsByTagName(‘li’);
    for(var i=0;i<lis.length;i++){
    (function(i){
    lis[i].onclick = function(){
    alert(i);
    }
    })(i)
    }
  3. 闭包的缺点
    3.1 变量会驻留在内存中,造成内存损耗问题。
    解决:把闭包的函数设置为null
    3.2 内存泄漏【ie】 ==> 可说可不说,如果说一定要提到ie
    1.优点:
    1.可以将一个变量长期储存在内存中,用于缓存
    2.可以避免全局变量的污染
    3.加强封装性,是实现了对变量的隐藏和封装
    2.闭包的缺点:
    1.因为函数执行上下文AO执行完不被释放,所以会导致内存消耗很大,增加了内存消耗量,影响 网页性能出现问题
    2.而且过度的使用闭包可能会导致内存泄漏,或程序加载运行过慢卡顿等问题的出现
    3.所以我们可以在退出函数之前 将不使用的局部变量进行删除
    应用场景
    1.定时器setTimeout
    私有化变量,封装功能集

promise、generator、async/await怎么使用,有什么区别

答: 我们知道JavaScript是单线程语言,如果没有异步编程非得卡死。 以前,异步编程的方法有下面四种 回调函数 事件监听 发布/订阅

Promise对象 现在据说异步编程终极解决方案是——async/await 更详细的介绍参考下面这篇文章:

https://www.jianshu.com/p/1c9…

8.apply/call/bind 有什么区别?

答: 这三者的作用就是改变函数运行时this的指向。 call方法: 语法:call([thisObj[,arg1[, arg2[,

[,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象。 说明:call

方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。

如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。 apply方法: 语法:apply([thisObj[,argArray]]) 定义:应用某一对象的一个方法,用另一个对象替换当前对象。 说明:如果

argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。

如果没有提供 argArray 和 thisObj 任何一个参数,那么Global 对象将被用作 thisObj, 并且无法被传递任何参数。bind方法: 语法:bind(thisArg[, arg1[, arg2[, …]]])

定义:将接受多个参数的函数变换成接受一个单一参数。

说明:bind()方法所返回的函数的length(形参数量)等于原函数的形参数量减去传入bind()方法中的实参数量(第一个参数以后的所有参数),因为传入bind中的实参都会绑定到原函数的形参。

什么是变量提升、函数提升

答: 变量提升:

简单说就是在js代码执行前引擎会先进行预编译,预编译期间会将变量声明与函数声明提升至其对应作用域的最顶端,函数内声明的变量只会提升至该函数作用域最顶层。

当函数内部定义的一个变量与外部相同时,那么函数体内的这个变量就会被上升到最顶端。 举例来说: console.log(a); //

undefined var a = 3;

//预编译后的代码结构可以看做如下运行顺序 var a; // 将变量a的声明提升至最顶端,赋值逻辑不提升。 console.log(a);

// undefined a = 3; // 代码执行到原位置即执行原赋值逻辑

函数提升: 函数提升只会提升函数声明式写法,函数表达式的写法不存在函数提升。

函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上。

什么是事件冒泡,它是如何工作的?如何阻止事件冒泡

答:
在一个对象上触发某类事件(比如单击onclick事件),如果此对象定义了此事件的处理程序,那么此事件就会调用这个处理程序,如果没有定义此事件处理程序或者事件返回true,那么这个事件会向这个对象的父级对象传播,从里到外,直至它被处理(父级对象所有同类事件都将被激活),或者它到达了对象层次的最顶层,即document对象(有些浏览器是window)

阻止事件冒泡的几种方法 第一种: event.stopPropagation(); 第二种: return false; 第三种:

event.preventDefault();

简单说说js中的继承

答: 有以下六种方法

1.原型链继承 JavaScript实现继承的基本思想:通过原型将一个引用类型继承另一个引用类型的属性和方法。

2.借用构造函数继承(伪造对象或经典继承) JavaScript实现继承的基本思想:在子类构造函数内部调用超类型构造函数。 通过使用apply()和call()方法可以在新创建的子类对象上执行构造函数。

3.组合继承(原型+借用构造)(伪经典继承) JavaScript实现继承的基本思想:将原型链和借用构造函数的技术组合在一块,从而发挥两者之长的一种继承模式。

将原型链和借用构造函数的技术组合到一起,从而取长补短发挥两者长处的一种继承模式。

4.原型式继承 JavaScript实现继承的基本思想:借助原型可以基于已有的对象创建新对象,同时还不必须因此创建自定义的类型。

5.寄生式继承 JavaScript实现继承的基本思想:创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真正是它做了所有工作一样返回对象。

寄生式继承是原型式继承的加强版。

6.寄生组合式继承 JavaScript实现继承的基本思想:通过借用函数来继承属性,通过原型链的混成形式来继承方法。

常用的js数组操作方法有哪些

答:
Array.shift()------删除并返回第一个元素 作用:从数组中删除第一个元素(即下标为0的元素),并返回该元素。 注意:1)删除元素之后,数组的长度-1。

2)如果数组是空的,那么 shift() 方法将不进行任何操作,返回undefined值。

2.Array.pop()------删除并返回最后一个元素 作用:从数组中删除最后一个元素(即下标为length-1的元素),并返回该元素。 注意:1)删除元素之后,数组的长度-1。

2)如果数组是空的,那么 shift() 方法将不进行任何操作,返回undefined值。

Array.push(param1[,param2,…paramN])------尾部添加元素 作用:在数组的尾部添加一个元素,并返回新数组的长度。 注意:1)它是直接修改该数组,而不是重新创建一个数组。

2)它和pop是一对相反的先进后出的栈功能方法。3)它可以同时给一个数组添加多个元素。

Array.unshift(newElement1[,newElement2,…newElementN])------头部添加元素 作用:在数组的头部添加一个或多个元素,并返回新数组的长度。 注意:1)它是直接修改该数组,而不是重新创建一个数组。

2)IE浏览器不支持该方法。

5.Array.join([separator])------转换成字符串 作用:把数组的所有元素放入到一个字符串中。 注意:1)参数separator表示字符串中元素的分隔符,可以为空,默认为半角逗号。

2)该方法并不修改数组。

Array.contact(array1[,array2,…arrayN])------连接数组 作用:将两个或两个以上的数组连接成一个数组,并返回连接后的数组。 注意:1)该方法并不会改变现有的数组,而是返回被连接的多个数组的一个副本。

2)如果多个数组里有值相同的元素,那也不会重复出现,而不会把重复的元素过滤掉。

7.Array.reverse()------反转数组 作用:把数组的所有元素顺序反转。 注意:1)该方法会直接修改数组,而不会创建新的数组。

Array.slice(start[, end])------截取数组 作用:截取数组中指定位置的元素,并返回一个新的子数组。 注意:1)该方法并不会改变现有的数组,而是原数组的一个子数组。

2)参数start是必选,表示开始下标,如果start为负数,表示从末尾开始,-1表示最后一个元素,依次类推。

3)end是可选表示结束下标,如果没有指定,表示到结尾元素。

9.Array.splice()------删除指定元素 作用:从数组指定位置删除指定数量的元素,并返回被删除的元素。 注意:1)该方法会直接修改数组。

2)splice() 方法与slice() 方法的作用是不同的,splice() 方法会直接对数组进行修改,而slice只是截取原数组的一部分后返回一个子数组,并不会修改原数组。

Array.toString()------转换成字符串 作用:数组转换为字符串,并返回该字符串。 注意:1)该方法和不带参数的join()方法效果一样。

js数组去重,能用几种方法实现

答:

方式一:new set
const arr= [1,2,3,2,4,1];
function unique(arr){
return […new Set(arr)]
}

方式二:Object的key是唯一
function unique(arr) {
const param = {};
arr.forEach(key => {
param[key] = key;
});
return Object.keys(param);
};

方式三:indexOf
function unique( arr ){
var brr = [];
for( var i=0;i<arr.length;i++){
if( brr.indexOf(arr[i]) == -1 ){
brr.push( arr[i] );
}
}
return brr;
}

方式四:sort
function unique( arr ){
arr = arr.sort();
var brr = [];
for(var i=0;i<arr.length;i++){
if( arr[i] !== arr[i-1]){
brr.push( arr[i] );
}
}
return brr;
}

数组中的forEach和map的区别

答: 相同点 都是循环遍历数组中的每一项
forEach和map方法里每次执行匿名函数都支持3个参数,参数分别是item(当前每一项),index(索引值),arr(原数组)

匿名函数中的this都是指向window 只能遍历数组 都不会改变原数组 区别 map方法

1.map方法返回一个新的数组,数组中的元素为原始数组调用函数处理后的值。

2.map方法不会对空数组进行检测,map方法不会改变原始数组。

3.浏览器支持:chrome、Safari1.5+、opera都支持,IE9+, 若arr为空数组,则map方法返回的也是一个空数组。 forEach方法

1.forEach方法用来调用数组的每个元素,将元素传给回调函数

2.forEach对于空数组是不会调用回调函数的。 无论arr是不是空数组,forEach返回的都是undefined。这个方法只是将数组中的每一项作为callback的参数执行一次。

jQueryajax 、fetch、 axios 有什么异同,适用场景有哪些

答:
1.jQuery ajax $.ajax({ type: ‘POST’, url: url, data: data, dataType: dataType, success: function () {}, error: function ()

{} }); 优缺点: 本身是针对MVC的编程,不符合现在前端MVVM的浪潮

JQuery整个项目太大,单纯使用ajax却要引入整个JQuery非常的不合理(采取个性化打包的方案又不能享受CDN服务)

2.axios axios({

method:‘post’,url:‘/user/12345’,data:{firstName:‘Fred’,lastName:‘Flintstone’} }) .then(function(response){console.log(response); }) 客户端支持防止CSRF/XSRF 自动转换JSON数据 取消请求 转换请求和响应数据 拦截请求和响应 支持PromiseAPI 从node.js 发出http 请求 从浏览器中创建

XMLHttpRequest axios 是一个基于Promise 用于浏览器和 nodejs 的 HTTP 客户端,它本身具有以下特征:

为什么要用axios? 4)fetch没有办法原生监测请求的进度,而XHR可以

3)fetch不支持abort,不支持超时控制,使用setTimeout及Promise.reject的实现的超时控制并不能阻止请求过程继续在后台运行,造成了量的浪费

2)fetch默认不会带cookie,需要添加配置项 1)fetchtch只对网络请求报错,对400,500都当做成功的请求,需要封装去处理

脱离了XHR,是ES规范里新的实现方式 更加底层,提供的API丰富(request, response) 更好更方便的写法

符合关注分离,没有将输入、输出和用事件来跟踪的状态混杂在一个对象里 优缺点: } console.log("Oops,

error", e); } catch(e) { console.log(data); let data =

response.json(); let response = await fetch(url); try {

3.fetch 提供了一些并发请求的接口(重要,方便了很多的操作) 客户端支持防止CSRF 支持 Promise API 从 node.js 创建 http 请求 优缺点: });

console.log(error); .catch(function(error){ })

16.es6 扩展运算符可以解决哪些问题?

答: … 代表着扩展运算符或Rest(剩余)运算符

是么是js事件循环 event loop

答: 主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。

Math.min()和Math.max()大小比较

答: Math.max() < Math.min() Math.min()如果没有参数,则返回 Infinity。Infinity 是

javascript 中全局对象的一个属性,在浏览器环境中就是 window 对象的一个属性,表示无穷大。 而 Math.max()

没有传递参数时返回的是 -Infinity。 因此 Math.min() 要比 Math.max() 大。

19.怎么实现对象的深浅拷贝

一、数据类型
数据分为基本数据类型(String, Number, Boolean, Null, Undefined,Symbol)和对象数据类型。
基本数据类型的特点:直接存储在栈(stack)中的数据
引用数据类型的特点:存储的是该对象在栈中引用,真实的数据存放在堆内存里

二、浅拷贝与深拷贝
深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的。
深拷贝和浅拷贝的示意图大致如下:
在这里插入图片描述

三、浅拷贝的实现方式
1.Object.assign()
Object.assign() 方法可以把任意多个的源对象自身的可枚举属性拷贝给目标对象,然后返回目标对象。但是 Object.assign()进行的是浅拷贝,拷贝的是对象的属性的引用,而不是对象本身。

注意:当object只有一层的时候,是深拷贝
2.Array.prototype.concat()
在这里插入图片描述
修改新对象会改到原对象:
在这里插入图片描述
3.Array.prototype.slice()
在这里插入图片描述
同样修改新对象会改到原对象:
关于Array的slice和concat方法的补充说明:Array的slice和concat方法不修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。
原数组的元素会按照下述规则拷贝:
如果该元素是个对象引用(不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。
对于字符串、数字及布尔值来说(不是 String、Number 或者 Boolean 对象),slice 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。

五、深拷贝的实现方式
1.JSON.parse(JSON.stringify())
原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
这种方法虽然可以实现数组或对象深拷贝,但不能处理函数
这是因为JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串,不能接受函数
在这里插入图片描述

2.手写递归方法
递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝
在这里插入图片描述

3.函数库lodash
该函数库也有提供_.cloneDeep用来做 Deep Copy
在这里插入图片描述

文件上传如何做断点续传

答: 文件断点续传是HTML5引入的新特性,HTML5的FILE

api,有一个slice方法,可以将BLOB对象进行分割。前端通过FileList对象获取到相应的文件,按照指定的分割方式将大文件分段,然后一段一段地传给后端,后端再按顺序一段段将文件进行拼接。

断点续传原理

目前比较常用的断点续传的方法有两种,一种是通过websocket接口进行文件上传,另一种是通过ajax,两种方法各有千秋,虽然websocket听起来比较高端些,但是除了用了不同的协议外其他的算法基本上都是很相似的,并且服务端要开启ws接口,这里用相对方便的ajax来说明断点上传的思路。

说来说去,断点续传最核心的内容就是把文件“切片”然后再一片一片的传给服务器。

首先是文件的识别,一个文件被分成了若干份之后如何告诉服务器你切了多少块,以及最终服务器应该如何把你上传上去的文件进行合并?

因此在文件开始上传之前,我们和服务器要有一个“握手”的过程,告诉服务器文件信息,然后和服务器约定切片的大小,当和服务器达成共识之后就可以开始后续的文件传输了。

前台要把每一块的文件传给后台,成功之后前端和后端都要标识一下,以便后续的断点。

当文件传输中断之后用户再次选择文件就可以通过标识来判断文件是否已经上传了一部分,如果是的话,那么我们可以接着上次的进度继续传文件,以达到续传的功能。

js如何处理防抖和节流

防抖:
核心:设置延时器,短时间高频率触发只有最后一次触发成功
解释:比如点击提交后,设置一个定时器,间隔1s再发送请求,如果 1s内多次请求,则清除定时器,1s后重新发送请求。也就是说,在1s内无论点击提交多少次,最后一次总是会清除上一次的延迟,继而进行自身请求。
无论你如何乱点,也只有你停止点击的最后一次会请求成功。
缺点:响应时间太久。

节流:
核心:设置状态锁,短时间高频率触发只有第一次触发成功
解释:节流就是设置状态锁,比如设置一个key作为状态锁,锁一开始是关闭的,即key值设置为false。当你点击时,会对key进行判断,如果key为false,未上锁,那么开始发起请求,并且给key上锁,即设置key为true。如果你继续点击,则对key进行判断,发现key上锁了,则不发起请求,点击无效。当请求完成后,key设置为false,则可以发送新一轮请求了。

防抖和节流区别:
函数节流不管事件触发有多频繁,都会保证在规定时间内一定会真正执行一次事件处理函数,而函数防抖只是在最后一次触发后才会执行。

22.事件委托以及优缺点

答: 优点:

1.减少事件注册,节省内存。比如,

2.在table上代理所有td的click事件。

3.在ul上代理所有li的click事件。

4.简化了dom节点更新时,相应事件的更新。比如

5.不用在新添加的li上绑定click事件。

6.当删除某个li时,不用移解绑上面的click事件。 缺点:

1.事件委托基于冒泡,对于不冒泡的事件不支持。

2.层级过多,冒泡过程中,可能会被某层阻止掉。

3.理论上委托会导致浏览器频繁调用处理函数,虽然很可能不需要处理。所以建议就近委托,比如在table上代理td,而不是在document上代理td。

4.把所有事件都用代理就可能会出现事件误判。比如,在document中代理了所有button的click事件,另外的人在引用改js时,可能不知道,造成单击button触发了两个click事件。

介绍this各种情况

答:

this的情况:

1.以函数形式调用时,this永远都是window

2.以方法的形式调用时,this是调用方法的对象

3.以构造函数的形式调用时,this是新创建的那个对象

4.使用call和apply调用时,this是指定的那个对象

5.箭头函数:箭头函数的this看外层是否有函数

如果有,外层函数的this就是内部箭头函数的this如果没有,就是window

6.特殊情况:通常意义上this指针指向为最后调用它的对象。这里需要注意的一点就是如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例

== 和 ===的区别,什么情况下用相等

==:运算符称作相等,用来检测两个操作数是否相等,这里的相等定义的非常宽松,可以允许进行类型转换

===:用来检测两个操作数是否严格相等 1、对于string,number等基础类型,=是有区别的 不同类型间比较,==之比较“转化成同一类型后的值”看“值”是否相等,===如果类型不同,其结果就是不等

同类型比较,直接进行“值”比较,两者结果一样 2、对于Array,Object等高级类型,=是没有区别的

3、基础类型与高级类型,=是有区别的 对于==,将高级转化为基础类型,进行“值”比较,因为类型不同,===结果为false

介绍下原型链(解决的是继承问题吗)

答: JavaScript原型: 每个对象都会在其内部初始化一个属性,就是prototype(原型)。 原型链:

当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念。

特点:

JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

JS里垃圾回收机制是什么,常用的是哪种,怎么处理的

答:
JS的垃圾回收机制是为了以防内存泄漏,内存泄漏的含义就是当已经不需要某块内存时这块内存还存在着,垃圾回收机制就是间歇的不定期的寻找到不再使用的变量,并释放掉它们所指向的内存。

JS中最常见的垃圾回收方式是标记清除。

工作原理:是当变量进入环境时,将这个变量标记为“进入环境”。当变量离开环境时,则将其标记为“离开环境”。标记“离开环境”的就回收内存。

工作流程:

垃圾回收器,在运行的时候会给存储在内存中的所有变量都加上标记。

去掉环境中的变量以及被环境中的变量引用的变量的标记。

再被加上标记的会被视为准备删除的变量。

垃圾回收器完成内存清除工作,销毁那些带标记的值并回收他们所占用的内存空间。

Promise和setTimeout的区别

回顾JavaScript事件循环并发模型,我们了解了setTimeout和Promise调用的都是异步任务,这一点是它们共同之处,也即都是通过任务队列进行管理/调度。那么它们有什么区别吗?

任务队列

前文已经介绍了任务队列的基础内容和机制,可选择查看,本文对任务队列进行拓展介绍。JavaScript通过任务队列管理所有异步任务,而任务队列还可以细分为MacroTask

Queue和MicoTask Queue两类。 MacroTask Queue MacroTask

Queue(宏任务队列)主要包括setTimeout,setInterval, setImmediate,

requestAnimationFrame, NodeJS中的`I/O等。 MicroTask Queue MicroTask

Queue(微任务队列)主要包括两类: 独立回调microTask:如Promise,其成功/失败回调函数相互独立;

复合回调microTask:如 Object.observe, MutationObserver 和NodeJs中的

process.nextTick ,不同状态回调在同一函数体; MacroTask和MicroTask

JavaScript将异步任务分为MacroTask和MicroTask,那么它们区别何在呢? 依次执行同步代码直至执行完毕;

检查MacroTask 队列,若有触发的异步任务,则取第一个并调用其事件处理函数,然后跳至第三步,若没有需处理的异步任务,则直接跳至第三步;

检查MicroTask队列,然后执行所有已触发的异步任务,依次执行事件处理函数,直至执行完毕,然后跳至第二步,若没有需处理的异步任务中,则直接返回第二步,依次执行后续步骤;

最后返回第二步,继续检查MacroTask队列,依次执行后续步骤; 如此往复,若所有异步任务处理完成,则结束;

介绍下广度优先遍历(BFS)和深度优先遍历(DFS)

答:

1.广度优先遍历 英文缩写为BFS即Breadth FirstSearch。其过程检验来说是对每一层节点依次访问,访问完一层进入下一层,而且每个节点只能访问一次。对于上面的例子来说,广度优先遍历的

结果是:A,B,C,D,E,F,G,H,I(假设每层节点从左到右访问)。 先往队列中插入左节点,再插右节点,这样出队就是先左节点后右节点了。

广度优先遍历树,需要用到队列(Queue)来存储节点对象,队列的特点就是先进先出。例如,上面这颗树的访问如下:

首先将A节点插入队列中,队列中有元素(A);

将A节点弹出,同时将A节点的左、右节点依次插入队列,B在队首,C在队尾,(B,C),此时得到A节点;

继续弹出队首元素,即弹出B,并将B的左、右节点插入队列,C在队首,E在队尾(C,D,E),此时得到B节点;

继续弹出,即弹出C,并将C节点的左、中、右节点依次插入队列,(D,E,F,G,H),此时得到C节点;

将D弹出,此时D没有子节点,队列中元素为(E,F,G,H),得到D节点; 。。。以此类推。。

2.深度优先遍历 英文缩写为DFS即Depth First Search.其过程简要来说是对每一个可能的分支路径深入到不能再深入为止,而且每个节点只能访问一次。对于上面的例子来说深度优先遍历的结果就是:A,B,D,E,I,C,F,G,H.(假设先走子节点的的左侧)。

深度优先遍历各个节点,需要使用到栈(Stack)这种数据结构。stack的特点是是先进后出。整个遍历过程如下:

先往栈中压入右节点,再压左节点,这样出栈就是先左节点后右节点了。 首先将A节点压入栈中,stack(A);

将A节点弹出,同时将A的子节点C,B压入栈中,此时B在栈的顶部,stack(B,C);

将B节点弹出,同时将B的子节点E,D压入栈中,此时D在栈的顶部,stack(D,E,C);

将D节点弹出,没有子节点压入,此时E在栈的顶部,stack(E,C); 将E节点弹出,同时将E的子节点I压入,stack(I,C);

…依次往下,最终遍历完成。 代码:也是以二叉树为例。

for in和for of的区别

答:

1.推荐在循环对象属性的时候,使用for…in,在遍历数组的时候的时候使用for…of

2.for…in循环出的是key,for…of循环出的是value

3.注意,for…of是ES6新引入的特性。修复了ES5引入的for…in的不足

4.for…of不能循环普通的对象,需要通过和Object.keys()搭配使用

30.typeof和instanceof 区别?

答: 在javascript中,判断一个变量的类型可以用typeof   (1)

数字类型、typeof返回的值是number。比如说:typeof(1),返回值是number   (2)

字符串类型,typeof返回的值是string。比如typeof(“123”返回值时string)   (3)

布尔类型,typeof返回的值是boolean。比如typeof(true)返回值时boolean   (4)

对象、数组、null返回的值是object。比如typeof(window),typeof(document),typeof(null)返回的值都是object

(5) 函数类型,返回的值是function。比如:typeof(eval),typeof(Date)返回的值都是function。

(6)

不存在的变量、函数或者undefined,将返回undefined。比如:typeof(abc)、typeof(undefined)都返回undefined

在javascript中,instanceof用于判断某个对象是否被另一个函数构造。

使用typeof运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回”object”。ECMAScript引入了另一个Java运算符instanceof来解决这个问题。Instanceof运算符与typeof运算符相似,用于识别正在处理的对象的类型。与typeof方法不同的是,instanceof方法要求开发者明确地确认对象为某特定类型

常见的继承有几种方法

答:
1.原型链继承

2.构造函数继承(经典继承)

3.组合方式继承(构造函数 + 原型链)

4.es6方法继承

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值