前端面试题总结(三)JavaScript篇
一、谈谈对this的理解?
- this是一个关键字。
- this总是指向函数的直接调用者(而非间接调用者)。
- 如果有new关键字,this指向new出来的那个对象。
- 在计时器当中,this会指向window。
- 在事件中,this指向触发这个事件的对象,特殊的是,IE中的事件监听中的this指向全局对象window。
二、eval是做什么的?
- eval()函数可以把一个字符串当做一个JavaScript表达式一样去执行它。
- 它的功能是把对应的字符串解析成js代码并运行。
- 应该避免使用eval。不安全且非常耗性能(2次,一次解析成js语句,一次执行)
三、null和undefined的区别?
- null是表示“无”的对象,转为数值时为0,undefined是一个表示“无”的原始值,转为数值时为NaN。
- undefined出现在,变量被申明但没赋值、调用函数时,应该提供的参数没有提供、对象没有赋值的属性、函数没有返回值时。
- null作为函数的参数时,表示该函数的参数不是对象。null也是原型链的终点。
四、call()和apply()的区别?
作用:动态改变某个类的某个方法的运行环境(执行上下文)。
区别:
-
- apply括号里只能写两个参数,一般用于数组的操作中改变this的指向,call括号里可以写多个参数。
- apply()函数有两个参数:第一个是上下文,第二个是参数组成的数组。如果第一个参数是null,则使用全局对象代替。
- call()的第一个参数是上下文,后续是实例传入的参数序列。
- 都可以改变this指向。apply优于call。
五、new操作符具体干了什么?
- 创建一个空对象,并且this变量引用该对象,同时还继承了该函数的原型。
- 属性和方法被加入到this引用的对象中。
- 新创建的对象由this所引用,并且最后隐式的返回this。
六、性能优化的方式?
- 减少http请求次数。
- 用innerHTML代替dom操作,减少dom操作次数,优化JavaScript性能。
- 当需要设置的样式比较多时设置className而不是直接操作style。
- 减少全局变量、缓存dom节点查找的结构,减少IO读取操作。
- 避免使用css表达式。(CSS Expression又称Dynamic properties动态属性)。
- 图片预加载,将样式表放在顶部,将脚本放在底部,加上时间戳。
- 前端模板 JS+数据,减少由于HTML标签导致宽带浪费。
- 用变量保存ajax请求结果,每次操作本地变量,不用请求减少请求次数。
七、哪些常见操作会导致内存泄漏?
内存泄漏指任何对象在您不在拥有或需要它之后仍然存在。
- setTimeout的第一个参数使用字符串而非函数的话,会引发内存泄漏。
- setTimeout可以有三个参数,当第一个参数的函数括号里面有形参的时候,后面的参数可以作为实参传入。
- 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)。
- 解决方法:垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为0(没有其他对象引用过该对象),或该对象的唯一引用是循环的,那么该对象的内存即可回收。
八、原型、原型链、继承?
- 原型(prototype):构造函数的一个专有属性。原型是一个对象,其他对象可以通过他实现属性继承。
- 继承:指一个对象直接使用另一个对象的属性和方法。
- 原型链:由一些用来继承和共享属性的对象组成的有限性的对象链(在javaScript中,每个对象都有一个指向它的原型(prototype)对象的内部链接。这个原型对象又有自己的原型,直到某个对象的原型为 null 为止(也就是不再有原型指向),组成这条链的最后一环。这种一级一级的链结构就称为原型链(prototypechain))。
九、什么是闭包?为什么要用它?
- 闭包就是一个可以访问其他函数内部变量的函数。
- 使用闭包主要是为了设计已有的方法和变量。
- 在js中,函数即闭包,只有函数才会产生作用域的概念。
- 闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄漏。
- 闭包的的特性:函数内再嵌套函数、内部函数可以引用外层的参数和变量、参数和变量不会被垃圾回收机制回收。
十、typeof返回哪些数据类型?
undefined、object、number、function、Boolean。
十一、split和join的区别?
前者是切割成数组的形式,后者是将数组转换成字符串。
十二、IE和DOM事件流的区别?
执行顺序不同、参数不一样、事件加不加on、this指向问题。
十三、本地对象、内置对象、宿主对象?
- 本地对象为array、obj、regexp等可以new实例化。
- 内置对象为gload Math等不可以实例化的。
- 宿主对象为浏览器自带的document,window等。
十四、对作用域链的理解?
作用域链的作用是保证执行环境里有权访问的变量和函数是有序的,作用域链的变量只能向上访问,变量访问到window对象即被终止,作用域链向下访问变量是不被允许的。
十五、同步和异步的区别?
- 同步是阻塞模式,异步是非阻塞模式。
- 同步:脚本会停留并等待服务器发送回复然后再继续。
- 异步:脚本允许页面继续其进程并处理可能的回复,可以提高执行效率。
十六、什么叫伪数组?怎么转化为标准数组?
伪数组:无法直接调用数组方法或期望length属性有什么特殊的行为,但仍可以使用真正数组遍历的方法来遍历。
典型的是argument参数(实参对象),getElementsByTagName,childNodes之类的,返回nodeList对象都属于伪数组。
转换:使用Array.prototype.slice.call(伪数组)。
十七、js继承方式的优缺点?
- 原型链继承:字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。
- 借用构造函数继承(类式继承):没有原型,不能复用。但是解决了字面量重写原型会中段关系问题和子类型给超类型传参问题。
- 组合继承(原型链+构造函数):使用原型链实现对原型属性和方法的继承,从而通过借用构造函数实现对实例属性的继承。既通过在原型上定义方法实现了函数复用,又保证每个实例都有自己的属性。
十八、减少页面加载时间的方法?
- 优化图片。
- 图形格式选择。
- 优化css(压缩合并css)。
- 网址后加斜杠(如www.campr.com/目录,会判断这个“目录是什么文件类型,或者是目录)。
- 标明高度和宽度。
- 减少http请求。
十九、cookie的弊端?
cookie在持久保存客户端数据提供了方便,分担了服务器存储压力。
- 每个特定域名下最多生成20个cookie(IE6<=20,IE7+<=50,火狐<=50,谷歌和Safari无限制)。
- IE和Opera会清理近期最少使用的cookie,火狐会随机清理。
- cookie最大大约为4096字节,为了兼容性,一般不能超过4095字节。
- 安全性问题。
- 有些状态不能保存在客户端(表单)。
优点:极高的扩展性和可用性。
缺点:cookie数量和长度有限制,安全性问题,有些状态不能保存在客户端。
二十、document.write和innerHTML的区别?
- 前者只能重绘整个页面,后者可以重绘页面的一部分。
- document.write()可以用在两个方面:页面载入过程中实时脚本创建页面内容,以及用延时脚本创建本窗口或新窗口的内容。
- document.write只能绘制整个页面。innerHTML可以重绘页面的一部分。
二十一、js创建对象的方式?
- 工程模式。
- 构造函数模式。
- 原型模式。
- 混合构造函数和原型模式(组合模式)。
- 动态原型模式。
- 寄生构造函数模式。
- 稳妥构造函数模式。
二十一、继承的几种方式?
- 原型链继承。(字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。)
- 借用构造函数继承(类式继承)。(没有原型,不能复用。但是解决了字面量重写原型会中段关系问题和子类型给超类型传参问题。)
- 组合继承(原型+借用构造)。(使用原型链实现对原型属性和方法的继承,从而通过借用构造函数实现对实例属性的继承。既通过在原型上定义方法实现了函数复用,又保证每个实例都 有自己的属性。)
- 原型式继承。
- 寄生式继承。
- 寄生组合式继承。
二十二、异步加载和延迟加载?
- 异步加载:动态创建script标签,通过ajax区获取js代码,通过eval执行,script标签上添加的defer或async属性。
- 延迟加载:有些js代码并不是页面初始化的时候就立刻需要的,而是稍后的某些情况才需要的。
- js延迟加载的方式有哪些?
- defer和async、动态创建DOM方式(常用)、按需异步载入js。
二十三、get和post的区别?使用场景?
- get:一般用于信息获取,使用url传递参数,对所发送信息的数量也有限制,一般在2000个字符。
- post:一般用于修改服务器的资源,对所发送的信息没有限制。
- get方式需要使用Request.QueryString来取得变量的值,而post方式通过Request.Form来获取变量的值,也就是说get是通过地址栏来传值,而post是通过提交表单来传值的。
- 使用场景:
-
- 接口规定用哪个就用哪个。
- 接口两个都允许,首选get。
- 发送包含未知字符的用户输入时,post比get更稳定也更可靠。
- 无法使用缓存文件(更新服务器上的文件或数据库)使用post。
- 向服务器发送大量数据使用post。
二十四、哪些地方会出现css阻塞,哪些地方会出现js阻塞?
- js的阻塞特性:所有浏览器在下载js的时候,会阻止一切其他活动(比如其他资源下载、内容呈现等),直到js下载、解析、执行完成后才继续并行下载其他资源并呈现内容。为了提高用户体验,新一代的浏览器都支持并行下载js,但是js下载仍然会阻塞其他资源的下载(比如图片、css文件等)。
- 由于浏览器为了防止出现js修改dom树,需要重新构建dom树的情况,所以就会阻塞其他的下载和呈现。
- 嵌入js会阻塞所有内容的呈现,而外部js只会阻塞其后内容的显示,2种方式都会阻塞其后资源的下载。也就是说外部样式不会阻塞外部脚本的加载,但会阻止外部脚本的执行。
- css怎么会阻塞加载了?
-
- css本来是可以并行下载的,但是在IE6下css是会阻塞加载的。
- 当css后面跟着嵌入js的时间,该css就会出现阻塞后面资源下载的情况。而把嵌入js放到css前面,就不会出现阻塞情况了。
- 根本原因:因为浏览器会维持HTML中css和js的顺序,样式表必须在嵌入的js执行前先加载、解析完。而嵌入的js会阻塞后面的资源加载,所以就会出现css阻塞下载的情况。
- 嵌入js应该放在什么位置?
-
- 放在底部,虽然仍然会阻塞所有呈现,但不会阻塞资源下载。
- 如果放在head中,请放在css头部。
- 使用defer(只支持IE)。
- 不要在嵌入的js中运行时间较长的函数,如果一定要用,可以用setTimeout来调用。
- js无阻塞加载具体方式?
- 将脚本放在底部。link还是放在head中,可以保证在js加载前,能加载出正常显示的页面。script放在body底部。
- 成组脚本:由于每个script标签下载时阻塞页面解析过程,所以现在页面的script总数也可以改善性能。适用于内联脚本和外部脚本。
- 非阻塞脚本:等页面加载完成后,再加载js代码。也就是,在window.onload事件发出后开始下载代码。
-
- defer属性:支持IE4和fierfox3.5更高版本浏览器。
- 动态脚本元素:文档对象模型(DOM)允许你使用js动态创建HTML的几乎全部文档(无论在何处启动下载,文件额下载和运行都不会阻塞其他页面处理过程。即使在head里(除了用于下载文件的http链接)。)。
二十五、事件、IE与火狐的事件机制有什么区别?怎么阻止冒泡?
- 我们在网页中的某个操作(有的操作对应多个事件),也就是可以被JavaScript侦测到的行为。
- 事件处理机制:IE是事件冒泡、Firefox同时指出两种事件模型(捕获与冒泡)。
- ev.stopPropagation();旧IE为:ev.cancelBubble=true;
JavaScript垃圾回收的方法?
- 标记清除:(常见)
- 原理:当变量进入执行环境的时候,比如函数中申明一个变量,垃圾回收期将其标记为“进入环境”,当变量离开执行环境的时候(函数执行结束),将其标记为“离开环境”。
- 垃圾回收器会在运行的时候给存储在内存中的所有变量加一个标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量。
- 引用计数:
-
- 原理:跟踪记录每个值被使用的次数,当申明了一个变量并将一个引用类型的值赋值给该变量时,这个值的引用次数+1,如果该变量的值变成另一个,则其引用次数-1,当这个值的引用次数为0时,说明没有变量在使用,这个值没法被访问了,因此可以将其占用空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间。
在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但BOM与DOM对象却是通过引用计数回收垃圾的, 也就是说只要涉及BOM及DOM就会出现循环引用问题。
attribute和property的区别?
- attribute是dom元素在文档中作为HTML标签拥有的属性;
- property就是dom元素在js中作为对象拥有的属性;
- 对于HTML的标准属性来说,两者是同步的,会自动更新,但是对于自定义的属性来说,他们是不同步的。
二十八、什么是事件代理?
- 事件代理又称为事件委托。是JavaScript中绑定事件的常用技巧。“事件委托”就是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。
- 事件代理的原理就是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能。
- 优点:
- 可以大量节省内存占用,减少事件注册。
- 可以实现党新增子对象时无需再次对其绑定事件,对于动态内容部分尤为合适。
二十九、Web Worker和webSocket?
- Web worker主线程:
- 我们整个程序在创建一个新程序的时候,是存在着一个线程的,我们称作主线程。然后再支持我们程序的运行。它的任务是响应用户操作的。
- 作用:如果让主线程执行一个复杂的操作会很卡,我们可以吧复杂的任务通过webworkers来处理,然后把处理的结果返回给主UI,处理主UI,这样就不会影响主UI了。
-
- 通过worker = new Worker(url)加载一个js文件来创建一个worker,同时返回一个worker实例。
- 通过worker.postMessage(data)方法向我worker发送数据。
- 绑定worker.onmessage方法来接收worker发送过来的数据。
- 可以使用worker.terminate()来终止一个worker的执行。
- webSocket是web应用程序的传输协议,它提供了双向的,按需到达的数据流。他是一个HTML5协议,websocket的链接是持久的,它通过在客户端和服务器之间保持双工链接,服务器的更新可以被计时推送给客户端,二不需要客户端以一定时间间隔区轮询。
如何删除一个cookie?
- 将时间设为当前时间往前一点。
- expires设置为new Date(0);
三十一、求一个字符串的字节长度?
假设一个英文字符占一个字节,一个汉字占两个字节。
function GetBytes(str){
var len = str.length;
var bytes = len;
for(var i=0; i<len; i++){
if (str.charCodeAt(i) > 255) bytes++;
}
return bytes;
}
alert(GetBytes("你好,as"));
三十二、js对象、浏览器对象?
- js内置对象 ——Array、Boolean、Date、Math、Number、String、ReqExp、Global
- 浏览器内置对象 ——Window、Nacigator、Screen、History、Location
三十三、事件绑定和普通事件有什么区别?(传统事件绑定和符合W3C标准的事件绑定有什么区别?)
div1.οnclick=function(){};
<button οnmοuseοver=””></button>
- 如果说给同一个元素绑定了两次或者多次相同类型的事件,那么后面的绑定会覆盖前面的绑定
- 不支持DOM事件流 事件捕获阶段è目标元素阶段=>事件冒泡阶段
- addEventListener
- 如果说给同一个元素绑定了两次或者多次相同类型的事件,所以的绑定将会依次触发
- 支持DOM事件流的
- 进行事件绑定传参不需要on前端
- addEventListener(“click”,function(){},true);//此时的事件就是在事件冒泡阶段执行
- ie9开始,ie11 edge:addEventListener
- ie9以前:attachEvent/detachEvent
- 进行事件类型传参需要带上on前缀
- 这种方式只支持事件冒泡,不支持事件捕获
- 事件绑定是指把事件注册到具体的元素之上,普通事件指的是可以用来注册的事件
三十三、当一个DOM节点被点击时候,我们希望能够执行一个函数,应该怎么做?
- 直接在DOM里绑定事件:<div οnclick=”test()”></div>
- 在JS里通过onclick绑定:xxx.onclick = test
- 通过事件添加进行绑定:addEventListener(xxx, ‘click’, test)
- 那么问题来了,Javascript的事件流模型都有什么?
- “事件冒泡”:事件开始由最具体的元素接受,然后逐级向上传播
- “事件捕捉”:事件由最不具体的节点先接收,然后逐级向下,一直到最具体的
- “DOM事件流”:三个阶段:事件捕捉,目标阶段,事件冒泡
三十四、列举浏览器对象模型BOM里常用的至少4个对象,并列举window对象的常用方法至少5个
- 对象:Window document location screen history navigator
- 方法:Alert() confirm() prompt() open() close()
三十五、把 Script 标签 放在页面的最底部的body封闭之前 和封闭之后有什么区别?浏览器会如何解析它们?
- 如果说放在body的封闭之前,将会阻塞其他资源的加载
- 如果放在body封闭之后,不会影响body内元素的加载
三十六、BOM对象有哪些,列举window对象?
- window对象 ,是JS的最顶层对象,其他的BOM对象都是window对象的属性;
- document对象,文档对象;
- location对象,浏览器当前URL信息;
- navigator对象,浏览器本身信息;
- screen对象,客户端屏幕信息;
- history对象,浏览器访问历史信息;
三十七、window.onload 和 document.ready的区别?
- load要等到图片和包含的文件都加在进来之后执行;
- ready是不包含图片和非文字文件的文档结构准备好就执行;
三十八、为什么扩展javascript内置对象不是好的做法?
因为扩展内置对象会影响整个程序中所使用到的该内置对象的原型属性
三十九、JavaScript原型,原型链 ? 有什么特点?
- 原型对象也是普通的对象,是对象一个自带隐式的__proto__属性,原型也有可能有自己的原型,如果一个原型对象的原型不为null的话,我们就称之为原型链。
- 原型链是由一些用来继承和共享属性的对象组成的(有限的)对象链。
四十、请描述一下cookie,sessionStorage和localStorage的区别?
- cookie会在浏览器和服务器之间来回传递。sessionStorage和localStorage不会。
- sessionStorage和localStorage的存储空间更大、有更多丰富易用的接口、各自独立的存储空间。
- sessionStorage数据存放在服务器上,cookie存放在客户浏览器上。
- cookie安全性差,内存大小只有4kb。
- cookie可以设置有效时间,sessionStorage和localStorage不能。
- sessionStorage会在浏览器关闭后删除数据,且当访问增多时,会占用服务器性能。
- localStorage能够长期无期限保存,只能通过手动删除。
本文章出自小小菜鸟学web,转载请注明