前端js面试题

1、原型、原型链

原型:js中一切皆对象,对象都有一个隐式的属性_proto_,它指向该对象的原型-prototype(原型对象)

原型链:我们调用对象的某个属性,如果该对象上没有该属性,则会向上在该对象的原型对象上找,有则返回,如果没有的话继续向原型的原型上找,直到Object的原型,Object的prototype为null,如果没有找到该属性则返回undefind。我们把整个访问的过程称为原型链

tips: 通过Object.create(null) 创建的对象没有原型对象

varA=function(){}

A.prototype.n=1

var b=new A()

A.prototype={n:2,m:3}

varc=newA()

console.log(b.n,b.m,c.n,c.m)   //1 undefind 2 3

varF=function(){};

Object.prototype.a=function(){

    console.log('a()')

};

Function.prototype.b=function(){

    console.log('b()')

}

var f=newF();

f.a()//? a()f.b()//? errF.a()//? a()F.b()//? b()

2、闭包、闭包的优缺点、闭包的应用场景

闭包:js的作用域中内部函数可以访问外部函数的变量,反之则不行,但是我们为能够达到这一目的,就使用内部函数应用外部函数的变量,把该内部函数通过外部函数return到外部去执行,就形成了闭包。

缺点:长期占用内存、容易造成内存泄漏

优点:私有话属性或变量、避免外部环境污染

应用场景:

A、防抖(清除旧定时器,开始新的定时器)、节流(上一个定时器没有结束,则return 不执行新的定时器)

B、函数柯里化

C、<ul>

<li>1</li>

<li>2</li>

<li>3</li>

</ul>

给li循环绑定点击事件,弹出 i

3、字符串的常用方法

indexOf()  查找某字符串对应的下标,如果找不到返回-1

split(sep)  将字符串按照指定的字符切割成数组元素,sep表示指定的字符

slice(start,end)  截取字符串,start开始的下标,end结束的下标,不包含end本身;如果end为空截取到最后,如果为负数表示倒数。

substr(start,count)  截取字符串,start开始的下标,count截取的长度,如果count为空截取到最后,如果start为负值表示倒数

substring(start,end)  截取字符串,start开始的下标,end结束的下标,不包含end本身,如果end为空截取到最后;如果下标为负数,自动转为0

4、Set、Map、和Array的异同、用法

Set:创建类似数组的数据结构,但成员是唯一(基本数据类型无重复,应用数据类型可以重复)

常用方法:size()、add()、delete()、clear()、has()可以使用该方法求交集/差集、keys()、values()、entries()、forEach()

Map:以键值对的行书存储数据,key可以是任何数据类型

常用方法:size()、set(key,value)、get(key)、delete()、clear()、has()、keys()、values()、entries()、forEach()

Set/Map转Array:

Array.from(set)

const arr = [ ...set ]

const arr = [ ...map.values ]

5、类数组转成数组的方法

const arr = Array.from(args)

const arr = Array.prototype.slice.call(args)或者[].splice.call(args)

const arr = [ ...args ]

6、宏任务微任务

js是单线程,但是它有个事件队列机制来处理异步操作,事件队列中有包含宏任务和微任务。像常用的setTimeout,setInterval就是宏任务,Promise()的.then(()=>{})/.catch(()=>{})/.finally(()=>{}) 回调都是微任务。js先执行主线程任务,然后看如果有可以执行的微任务就会被执行,再看如果有宏任务就被执行,执行完继续主线程任务-然后就一遍一遍这循环执行,这也就是它的事件循环机制

7、深拷贝、浅拷贝

js的数据类型分为基本数据类型(Number/String/Boolean/Null/undefind)和引用数据类型Object(包含Function

/Array/Date/Regex)。浅拷贝对基本数据类型来说拷贝的是值,但对引用数据类型来说拷贝的只是引用, 深拷贝针对的是引用数据类型,拷贝的是值。

我们常用的拷贝方法有:

1、Object.assgin()  仅第一层是深拷贝

2、ES6的扩展运算符(...)仅第一层是深拷贝

3、JSON.parse( JSON.stringify(target) )  会丢失函数、会把时间对象变成字符串、会把正则对象变成空对象

4、利用递归手写深拷贝方法

function deepClone1(obj) {

  var objClone = Array.isArray(obj) ? [] : {};

  if (obj && typeof obj === "object") {

    for (key in obj) {

      if (obj.hasOwnProperty(key)) {

        if (obj[key] && typeof obj[key] === "object") {

          objClone[key] = deepClone1(obj[key]);

        } else {

          objClone[key] = obj[key];

        }

      }

    }

  }

  return objClone;

}

8、数组去重

1、利用对象访问属性的方法,判断对象中是否存在key

2、利用reduce方法遍历数组,reduce第一个参数是遍历需要执行的函数,第二个参数是item的初始值

varobj={};

vararr=arr.reduce(function(item,next) {

obj[next.key]?'':obj[next.key]=true&&item.push(next);

returnitem;

 }, []);

3、利用new Set() 去重,去重之后可以通过Array.from(set)或者 [...set] 把set转回数组

9、cookie sessionstorage localstorage 的异同

相同点:都可以存储数据

不同点:

存储大小:cookie 4KB

    sessionstorage和localstorage 5MB

生命周期:

cookie 可以手动设置过期时间

sessionstorage 当前会话,关闭窗口或浏览器就被删除

localstorage 永久保存 除非手动删除

使用api:

cookie 操作的是字符串 比较麻烦需要手动封装方法

sessionstorage和localstorang的话有自己的getItem()和setItem()、clear()方法,使用起来比较方便

10、跨域

因为浏览器存在同源策略,协议+域名+端口 必须完全一致不然就会受到浏览器同源策略限制造成跨域。

跨域有如下常用方法:

1、proxy

2、jsonp 原理是利用<script src="https://xxx/a.html?callback=fnName"></script>不是同源策略限制

3、跨域资源贡献(CORS)服务端设置Access-Control-Allow-Origin即可

4、window.name + iframe 原理是window.name保存的字符串数据可以跨不同页面和不同的域

5、h5的postMessage() + window.onmessage() 再不同页面(或iframe)之间发送消息和接受消息

6、nginx代理 原理是因为跨域是存在与浏览器端,所以通过反向代理通过服务端获取数据

11、apply()、call()、bind() 之间的异同

相同点:三个都是改变this指向的。

区   别:call()和apply()第一个参数是指定的对象,call()之后的参数是传入该函数的值

apply()第二个参数是数组,数组中是函数执行需要的参数

bind()和call()的参数相同,不同的是bind()改变this的指向后不会立即执行,其他两个是立即执行的

tips   :使用bind()的时候最好不要直接绑定在Dom上,避免当Dom变化时需要重新绑定

12、防抖、节流函数

防抖:代码实现重在清零clearTimeout

functiondebounce(f,wait) {

lettimer

return(...args)=>{

clearTimeout(timer)

timer=setTimeout(()=>{

f(...args)

},wait)

 }

}

节流:代码实现重在开锁关锁timer=timeout; timer=null

functionthrottle(f,wait) {

lettimer

return(...args)=>{

if(timer) {return}

timer=setTimeout(()=>{

f(...args)

timer=null

},wait)

 }

}

13、数组降维

Array.prototype.concat.apply([],targetArr);

14、判断数据类型

function toType(obj) {

  return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()

}

15、箭头函数和普通function的区别

1、写法不同

2、this指向不同

function中的this执行环境的不同而不同

箭头函数的this是它自己执行环境最近非箭头函数的this

3、function可以被new 实例化,箭头函数不可以

4、function可以被声明提前,箭头函数不可以,必须先声明后使用不然会报错

16、数组的常用方法

改变原数组的:push()、pop()、unshift()、shift()、splice() 、sort()、reverse()

不改变原数组:join()、slice()、map()、filter()、forEach()、some()、every()、find()、reduce()

17、new 操作符具体做了什么

1、创建了一个空对象 let obj = {}

2、继承了该函数的原型 obj._ protp_= Fn.prototype

3、改变了该函数的this指向 let result = Fn.call(obj,...args)

4、判断该函数的返回值,如果该返回值是基本数据类型则 return obj ,否则 return result

18、Promise

它用于异步操作,它是一个构造函数,接收一个回调函数,用于异步计算,可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果而且可以在对象之间传递和操作promise,帮助我们处理队列。

有三个状态:

1、pending[待定]初始状态

2、fulfilled[实现]操作成功

3、rejected[被否决]操作失败

常用方法:

1、then()、catch()、finally()

2、all([])接收一个数组,当所有的异步请求完成之后才完成,一旦有某个异步请求报错,则直接catch

3、race([])也接收一个数组,但它是抢占执行,一旦有一个异步请求完成就算完成了

19、函数柯里化

概念:把一个接收多个参数的函数变成接收单一参数 并且返回能够接收新参数的函数 

add(1)(2)(3)(4)=10;

function add(num){

    var sum=num;

    var fn=function(v){

        sum+=v;

        return fn

    };

    fn.toString=function(){

        return sum

    };

    return fn

}

console.log(add(1)(2)(3)(4)) // 10

20、斐波那契数列

eg:1、1、2、3、5、8、13...

function fibonacci(n) {

if(n == 1 || n == 2) {

return1

    };

returnfibonacci(n - 2) + fibonacci(n - 1);

}

fibonacci(30)

21、缓存策略

1、强缓存:

强缓存两个相关字段:【Expires】-过期时间,【Cache-Control】-过期时长。

强缓存分为两种情况,一种是发送HTTP请求,一种不需要发送。

首先检查强缓存,这个阶段不需要发送HTTP请求,通过查找不同的字段来进行,不同的HTTP版本不同

http1.0版本,使用的是expires,http1.1使用的是cache-control

expires即过期时间,时间是相对于服务器的时间而言的,存在于服务端返回的响应头中,在这个过期时间之·        前可以直接从缓存里面获取数据,无需再次请求。

cache-control,http1.1版本中,使用的是这字段,这个字段采用的时间是过期时长,对应的是max-age

注意点:当expires和cache-control同时存在时,优先考虑cache-control。

当缓存资源失效了,也就是没有命中强缓存,接下来就进入协商缓存

2、协商缓存

强缓存失效后,浏览器在请求头中携带响应的缓存etag来向服务器发送请求,服务器根据对应的tag,来决定是否使用缓存。

分为两种,【last-modified】和【etag】。两者个有优势

last-modified:这个字段表示的是【最后修改时间】,在浏览器第一次个服务器发送请求后,服务器会在响应头中加上这个字段。浏览器接收到后,【如果再次请求】,会在请求头中携带 if-modified-since 这个字段,这个字段的值也就是服务器传来的最后修改时间。服务器拿到请求头中的 if-modified-since 的字段后,其实会和这个服务器中 该资源的最后修改时间 做对比:

如果请求头中的这个值小于最后修改时间,说明要更新了,返回新的资源,跟常规的http请求响应的流程一样,否则返回304,告诉浏览器直接使用缓存。

etag:etag是服务器根据当前文件的内容,对文件生成唯一的标识,比如md5算法,只要里面的内容有改动,这个值就会修改,服务器通过响应头把这个字段给浏览器。浏览器接收到etag值,会在下次请求的时候,将这个值作为【if-none-match】这个字段的内容,发送给服务器。服务器接收到这个【if-none-match】字段后,会跟服务器上该资源的【etag】进行比较。

如果两者一样的话,直接返回304,告诉浏览器直接使用缓存,如果不一样的话,说明内容更新了,返回新的资源,跟常规的http请求响应的流程一样。

22、301、302、303、304状态码有什么区别

301表示永久重定向,请求的资源分配了新的url

302表示临时重定向,请求的资源分配了新的url,本次暂且使用新的url,下次请求可能会改变

303表示请求的资源路径发生改变,使用GET方法请求新url。她与302的功能一样,但是明确指出使用GET方法请求新url。

304表示请求的资源未更新。该状态码不应该认为是一种错误,而是对客户端有缓存情况下服务端的一种响应。

tips:新url指的是,第一次请求返回的location

23、深度优先、广度优先

  深度优先遍历:对每一个可能的分支路径深入到不能再深入为止,而且每个结点只能访问一次。递归

  要特别注意的是,二叉树的深度优先遍历比较特殊,可以细分为先序遍历、中序遍历、后序遍历(我们前面使用的是先序遍历)。具体说明如下:

   先序遍历:对任一子树,先访问根,然后遍历其左子树,最后遍历其右子树。

   中序遍历:对任一子树,先遍历其左子树,然后访问根,最后遍历其右子树。

   后序遍历:对任一子树,先遍历其左子树,然后遍历其右子树,最后访问根。

   广度优先遍历:又叫层次遍历,从上往下对每一层依次访问,在每一层中,从左往右(也可以从右往左)访问结点,访问完一层就进入下一层,直到没有结点可以访问为止  遍历

24、介绍一下webpack

webpack是模块打包机(自动化构建工具),我们常用webpack构建我们的项目框架。在webpack中,包含entry,output,mode,module,plugin,module中我们一般会引入各种loader帮助我们翻译编译代码,(loader是从右往左执行)plugin会引入各种插件,优化构建出来的代码,mode是模式,一般分为development和production。entry是入口,output是出口。

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

推荐阅读更多精彩内容

  • FEGuideTeam/FEGuide 一份涵盖大部分前端工程师所需要掌握的核心知识。这个项目就是为了帮助那些找工...
    acc8226阅读 834评论 0 6
  • css相关 1. 万能居中 1.margin: 0 auto;水平 2.text-align: center;水平...
    chaocc阅读 948评论 0 2
  • 简单面试题 1.map与foreach区别、 共同点1.都是循环遍历数组中的每一项。2.forEach() 和 m...
    栀璃鸢年_49a3阅读 1,943评论 2 18
  • 久违的晴天,家长会。 家长大会开好到教室时,离放学已经没多少时间了。班主任说已经安排了三个家长分享经验。 放学铃声...
    飘雪儿5阅读 7,472评论 16 22
  • 今天感恩节哎,感谢一直在我身边的亲朋好友。感恩相遇!感恩不离不弃。 中午开了第一次的党会,身份的转变要...
    迷月闪星情阅读 10,548评论 0 11