每到毕业季,看着自己带出的学生找到理想的工作,心中亦是十分欣慰。学生求职中,经常会问我一些面试中的问题,每次耐心地帮他们解答,对他们帮助很大。
临近毕业的学生很多恐惧面试,所以在学校内部我整理了一些面试题册子与学生分享,学生受益颇多。再后来,为使在这里毕业的更多学生持续地学习更广阔的知识,爱创课堂组织了一个“爱创课堂每日一题”活动,每天推出一道与工作相关的技术问题,受到广大毕业学生好评……
通过这些活动我认识到,不论是在面试中,还是工作中,通过学习了解确实可以避免少踩一些坑,少走一些弯路,于是我将培训学校内部用的前端面试知识,整理成一本书。
希望能够与更多的读者分享爱创课堂的知识;希望《前端程序员面试秘籍》能够帮助那些正在找工作的人顺利找到工作;也希望这本书能够帮助那些在工作中遇到问题而踌躇不前的人顺利解决问题;同时也希望这本书能够帮助那些学习前端、期望了解前端更多知识的人。
1.JavaScript有哪些垃圾回收机制?
答:有以下垃圾回收机制。
标记清除(mark and sweep)
这是JavaScript最常见的垃圾回收方式。当变量进入执行环境的时候,比如在函数中声明一个变量,垃圾回收器将其标记为“进入环境”。当变量离开环境的时候(函数执行结束),将其标记为“离开环境”。
垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量,以及被环境中变量所引用的变量(闭包)的标记。在完成这些之后仍然存在的标记就是要删除的变量。
引用计数(reference counting)
在低版本的IE中经常会发生内存泄漏,很多时候就是因为它采用引用计数的方式进行垃圾回收。
引用计数的策略是跟踪记录每个值被使用的次数。当声明了一个变量并将一个引用类型赋值给该变量的时候,这个值的引用次数就加1。如果该变量的值变成了另外一个,则这个值的引用次数减1。当这个值的引用次数变为0的时候,说明没有变量在使用,这个值没法被访问。
因此,可以将它占用的空间回收,这样垃圾回收器会在运行的时候清理引用次数为0的值占用的空间。
在IE中虽然JavaScript对象通过标记清除的方式进行垃圾回收,但是BOM与DOM对象是用引用计数的方式回收垃圾的。也就是说,只要涉及BOM和DOM,就会出现循环引用问题。
2.列举几种类型的DOM节点
答:有以下几类DOM节点。
整个文档是一个文档节点。
每个HTML标签是一个元素节点。
每一个HTML属性是一个属性节点。
包含在HTML元素中的文本是文本节点。
3.谈谈script标签中defer和async属性的区别。
答:区别如下。
(1)defer属性规定是否延迟执行脚本,直到页面加载为止。async属性规定脚本一旦可用,就异步执行。
(2)defer并行加载JavaScript文件,会按照页面上script标签的顺序执行。async并行加载JavaScript文件,下载完成立即执行,不会按照页面上script标签的顺序执行。
4.说说你对闭包的理解。
答:使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染;缺点是闭包会常驻内存,增加内存使用量,使用不当很容易造成内存泄漏。在JavaScript中,函数即闭包,只有函数才会产生作用域。
闭包有3个特性。
(1)函数嵌套函数。
(2)在函数内部可以引用外部的参数和变量。
(3)参数和变量不会以垃圾回收机制回收。
5.解释一下unshift()方法。
答:该方法在数组启动时起作用,与push()不同。它将参数成员添加到数组的答顶部。下面给出一段示例代码。
var name=["john"]
name.unshift("charlie");
name.unshift("joseph","Jane");
console.log(name);
输出如下所示。
[" joseph "," Jane ", " charlie ", " john "]
6.encodeURI()和decodeURI()的作用是什么?
答:encodeURl()用于将URL转换为十六进制编码。而decodeURI()用于将编码的URL转换回正常URL。
7.为什么不建议在JavaScript中使用innerHTML?
答:通过innerHTML修改内容,每次都会刷新,因此很慢。在innerHTML中没有验证的机会,因此更容易在文档中插入错误代码,使网页不稳定。
8.如何在不支持JavaScript的旧浏览器中隐藏JavaScript代码?
答:在<script>标签之后的代码中添加“<!--”,不带引号。
在</script>标签之前添加“// -->”,代码中没有引号。
旧浏览器现在将JavaScript代码视为一个长的HTML注释,而支持JavaScript的浏览器则将“<!--”和“// -->”作为一行注释。
9.在DOM操作中怎样创建、添加、移除、替换、插入和查找节点?
答:具体方法如下。
(1)通过以下代码创建新节点。
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
(2)通过以下代码添加、移除、替换、插入节点。
appendChild()
removeChild()
replaceChild()
insertBefore() //并没有insertAfter()
(3)通过以下代码查找节点。
getElementsByTagName() //通过标签名称查找节点
getElementsByName() //通过元素的name属性的值查找节点(IE容错能力较强,会得到一个数
//组,其中包括id等于name值的节点)
getElementById() //通过元素Id查找节点,具有唯一性
10.如何实现浏览器内多个标签页之间的通信?
答:调用localstorge、cookie等数据存储通信方式。
11.null和undefined的区别是什么?
答:null是一个表示“无”的对象,转为数值时为0;undefined是一个表示“无”的原始值,转为数值时为NaN。
当声明的变量还未初始化时,变量的默认值为undefined。
null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在的对象。
undefined表示“缺少值”,即此处应该有一个值,但是还没有定义,典型用法是如下。
(1)如果变量声明了,但没有赋值,它就等于undefined。
(2)当调用函数时,如果没有提供应该提供的参数,该参数就等于undefined。
(3)如果对象没有赋值,该属性的值为undefined。
(4)当函数没有返回值时,默认返回undefined。
null表示“没有对象”,即此处不应该有值,典型用法是如下。
(1)作为函数的参数,表示该函数的参数不是对象。
(2)作为对象原型链的终点。
12.new操作符的作用是什么?
答:作用如下。
(1)创建一个空对象。
(2)由this变量引用该对象。
(3)该对象继承该函数的原型(更改原型链的指向)。
(4)把属性和方法加入到this引用的对象中。
(5)新创建的对象由this引用,最后隐式地返回this,过程如下。
var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);
13.JavaScript延迟加载的方式有哪些?
答:包括defer和async、动态创建DOM(创建script,插入DOM中,加载完毕后回调、按需异步载入JavaScript。
14.call()和apply() 的区别和作用是什么?
答:作用都是在函数执行的时候,动态改变函数的运行环境(执行上下文)。
call和apply的第一个参数都是改变运行环境的对象。
区别如下。
call从第二个参数开始,每一个参数会依次传递给调用函数;apply的第二个参数是数组,数组的每一个成员会依次传递给调用函数。
如:
func.call(func1, var1, var2, var3)
对应的apply写法为:
func.apply(func1, [var1, var2, var3])
15.哪些操作会造成内存泄漏?
答:内存泄漏指不再拥有或需要任何对象(数据)之后,它们仍然存在于内存中。
提示:垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为0(没有其他对象引用过该对象),或对该对象的唯一引用是循环的,那么该对象占用的内存立即被回收。
如果setTimeout 的第一个参数使用字符串而非函数,会引发内存泄漏。
闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)等会造内存泄漏。
16.列举IE与finefox的不同之处。
答:不同之处如下。
(1)IE支持currentStyle;Firefox使用getComputStyle。
(2)IE使用innerText;Firefox使用textContent。
(3)在透明度滤镜方面,IE使用filter:alpha(opacity= num);Firefox使用-moz-opacity: num。
(4)在事件方面,IE使用attachEvent:Firefox使用addEventListener。
(5)对于鼠标位置:IE使用event.clientX;Firefox使用event.pageX。
(6)IE使用event.srcElement;Firefox使用event.target。
(7)要消除list的原点,IE中仅须使margin:0即可达到最终效果;Firetox中需要设置margin:0、padding:0和list-style:none。
(8)CSS圆角:IE7以下不支持圆角。
17.讲解一下JavaScript对象的几种创建方式。
答:有以下创建方式。
(1)Object构造函数式。
(2)对象字面量式。
(3)工厂模式。
(4)安全工厂模式。
(5)构造函数模式。
(6)原型模式。
(7)混合构造函数和原型模式。
(8)动态原型模式。
(9)寄生构造函数模式。
(10)稳妥构造函数模式。
18.如何实现异步编程?
答:具体方法如下。
方法 1,通过回调函数。优点是简单、容易理解和部署;缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程混乱,而且每个任务只能指定一个回调函数。
方法 2,通过事件监听。可以绑定多个事件,每个事件可以指定多个回调函数,而且可以“去耦合”(Decoupling),有利于实现模块化;缺点是整个程序都要变成事件驱动型,运行流程会变得很不清晰。
方法 3,采用发布/订阅方式。性质与“事件监听”类似,但是明显优于后者。
方法 4,通过Promise对象实现。Promise对象是CommonJS工作组提出的一种规范,旨在为异步编程提供统一接口。它的思想是,每一个异步任务返回一个Promise对象,该对象有一个then方法,允许指定回调函数。
19.请解释一下JavaScript的同源策略。
答:同源策略是客户端脚本(尤其是JavaScript)的重要安全度量标准。它最早出自Netscape Navigator 2.0,目的是防止某个文档或脚本从多个不同源装载。
这里的同源策略指的是协议、域名、端口相同。同源策略是一种安全协议。指一段脚本只能读取来自同一来源的窗口和文档的属性。
20.为什么要有同源限制?
答:我们举例说明。比如一个黑客,他利用Iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名、密码登录时,他的页面就可以通过JavaScript读取到你表单上input中的内容,这样黑客就会轻松得到你的用户名和密码。
21.在JavaScript中,为什么说函数是第一类对象?
答:第一类函数即JavaScript中的函数。这通常意味着这些函数可以作为参数传递给其他函数,作为其他函数的值返回,分配给变量,也可以存储在数据结构中。
22.什么是事件? IE与Firefox的事件机制有什么区别? 如何阻止冒泡?
答:事件是在网页中的某个操作(有的操作对应多个事件)。例如,当单击一个按钮时,就会产生一个事件,它可以被JavaScript侦测到。
在事件处理机制上,IE支持事件冒泡;Firefox同时支持两种事件模型,也就是捕获型事件和冒泡型事件。
阻止方法是ev.stopPropagation()。注意旧版IE中的方法ev.cancelBubble = true。
23.函数声明与函数表达式的区别?
答:在JavaScript中,在向执行环境中加载数据时,解析器对函数声明和函数表达式并非是一视同仁的。解析器会首先读取函数声明,并使它在执行任何代码之前可用(可以访问)。至于函数表达式,则必须等到解析器执行到它所在的代码行,才会真正解析和执行它。
24.如何删除一个cookie?
答:为了删除cookie,要修改expires,代码如下。
document.cookie = 'user=icketang;expires = ' + new Date(0)
25.编写一个方法,求一个字符串的长度(单位是字节)。
答:假设一个英文字符占用一字节,一个中文字符占用两字节:
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("hello 爱创课堂!"));
26.对于元素,attribute和property的区别是什么?
答:attribute是DOM元素在文档中作为HTML标签拥有的属性;property就是DOM元素在JavaScript中作为对象拥有的属性。
对于HTML的标准属性来说,attribute和property是同步的,会自动更新,但是对于自定义的属性来说,它们是不同步的。
27.解释延迟脚本在JavaScript中的作用。
答:默认情况下,在页面加载期间,HTML代码的解析将暂停,直到脚本停止执行。这意味着,如果服务器速度较慢或者脚本特别“沉重”,则会导致网页延迟。在使用Deferred时,脚本会延迟执行,直到HTML解析器运行。这缩短了网页的加载时间,并且它们的显示速度更快。
28.什么是闭包(closure)?
答:为了说明闭包,创建一个闭包。
function hello() {
// 函数执行完毕,变量仍然存在
var num = 100;
var showResult= function() { alert(num); }
num++;
return showResult;
}
var showResult= hello();
showResult()//执行结果:弹出101
执行hello()后,hello()闭包内部的变量会存在,而闭包内部函数的内部变量不会存在,使得JavaScript的垃圾回收机制不会收回hello()占用的资源,因为hello()中内部函数的执行需要依赖hello()中的变量。
29.如何判断一个对象是否属于某个类?
答:使用instanceof关键字,判断一个对象是否是类的实例化对象;使用constructor属性,判断一个对象是否是类的构造函数。
30.JavaScript中如何使用事件处理程序?
答:事件是由用户与页面的交互(例如单击链接或填写表单)导致的操作。需要一个事件处理程序来保证所有事件的正确执行。事件处理程序是对象的额外属性。此属性包括事件的名称和事件发生时采取的操作。
张容铭 著
本书针对前端知识所涉及的方方面面,总结归纳了30个模块,提出了1076道前端面试题,模拟了真实的面试场景。从面试官的角度出发,针对某一知识点,并以面试官的口吻提出疑问。在解答问题过程中,站在应试者的角度给出答案。让读者进入真实的企业面试氛围。书中面试题极具针对性,并具有一定的独立性,读者可以根据个人喜好,可以针对性地阅览某一章节。
邀请10名好友关注异步图书10天,即可免费获得异步新书。
长按二维码,可以关注我们哟
每天与你分享IT好文。
点击阅读原文,购买《前端程序员面试秘籍》
阅读原文