前言:本文是在GitHup上看到一个大牛总结的前端常见面试题,很多问题问的都很好,很经典、很有代表性。上面没有答案,我就整理了一下,从网上找了一些相关问题的答案。里面有一部分问题的答案我也没有进行考证,不少答案都来源于网络,或许会有疏漏之处,仅供大家参考哦!(还有一部分问题答案还未整理,大家也可以自己搜索一下答案)
1、你能描述一下渐进增强和优雅降级之间的不同吗?
如果提到了特性检测,可以加分。检测浏览器,渐进增强就是让牛b的浏览器的效果更好,优雅降级就是让2b的浏览器在功能ok的情况下效果一般。
2、线程与进程的区别
一个程序至少有一个进程,一个进程至少有一个线程.线程的划分尺度小于进程,使得多线程程序的并发性高。另外,进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率。线程在执行过程中与进程还是有区别的。每个独立的线程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。从逻辑角度来看,多线程的意义在于一个应用程序中,有多个执行部分可以同时执行。但操作系统并没有将多个线程看做多个独立的应用,来实现进程的调度和管理以及资源分配。这就是进程和线程的重要区别。
3、请解释一下什么是“语义化的HTML”。
语义化的好处:1:去掉或样式丢失的时候能让页面呈现清晰的结构:html本身是没有表现的,我们看到例如<h1>是粗体,字体大小2em,加粗;<strong>是加粗的,不要认为这是html的表现,这些其实html默认的css样式在起作用,所以去掉或样式丢失的时候能让页面呈现清晰的结构不是语义化的HTML结构的优点,但是浏览器都有有默认样式,默认样式的目的也是为了更好的表达html的语义,可以说浏览器的默认样式和语义化的HTML结构是不可分割的。2.屏幕阅读器(如果访客有视障)会完全根据你的标记来“读”你的网页.3.PDA、手机等设备可能无法像普通电脑的浏览器一样来渲染网页(通常是因为这些设备对CSS的支持较弱).4.搜索引擎的爬虫也依赖于标记来确定上下文和各个关键字的权重.5.你的页面是否对爬虫容易理解非常重要,因为爬虫很大程度上会忽略用于表现的标记,而只注重语义标记.6.便于团队开发和维护语义化的HTML就是:标题用h1-h6,文字段落用p,列表用ul li,大致如此
4、你如何对网站的文件和资源进行优化?
期待的解决方案包括:文件合并文件最小化/文件压缩使用CDN托管缓存的使用(多个域名来提供缓存)其他
5、为什么利用多个域名来提供网站资源会更有效?
浏览器同一时间可以从一个域名下载多少资源?你的浏览器能同时保持对一个域名的多少连接?显示当前主要浏览的这个参数限制:
Browser |
Max Connections/Host |
Chrome 1.0 |
6 |
Chrome 2.0 |
6 |
Firefox 3.0 |
6 |
Firefox 3.5 |
6 |
IE 6 |
2 |
IE 7 |
2 |
IE 8 |
6 |
Safari 3.2 |
4 |
Safari 4.0 |
4 |
三个最主流的原因:1.CDN缓存更方便2.突破浏览器并发限制(你随便挑一个G家的url:https://lh4.googleusercontent.com/-si4dh2myPWk/T81YkSi__AI/AAAAAAAAQ5o/LlwbBRpp58Q/w497-h373/IMG_20120603_163233.jpg,把前面的lh4换成lh3,lh6啥的,都照样能够访问,像地图之类的需要大量并发下载图片的站点,这个非常重要。)3.Cookieless,节省带宽,尤其是上行带宽一般比下行要慢。。。还有另外两个非常规原因:4.对于UGC的内容和主站隔离,防止不必要的安全问题(上传js窃取主站cookie之类的)。正是这个原因要求用户内容的域名必须不是自己主站的子域名,而是一个完全独立的第三方域名。5.数据做了划分,甚至切到了不同的物理集群,通过子域名来分流比较省事.^_^这个可能被用的不多。PS:关于Cookie的问题,带宽是次要的,安全隔离才是主要的。关于多域名,也不是越多越好,虽然服务器端可以做泛解释,浏览器做dns解释也是耗时间的,而且太多域名,如果要走https的话,还有要多买证书和部署的问题,^_^。
6、请说出三种减少页面加载时间的方法。(加载时间指感知的时间或者实际加载时间)
1.优化图片2.图像格式的选择(GIF:提供的颜色较少,可用在一些对颜色要求不高的地方)3.优化CSS(压缩合并css,如margin-top,margin-left...)4.网址后加斜杠(如www.campr.com/目录,会判断这个“目录是什么文件类型,或者是目录。)5.标明高度和宽度(如果浏览器没有找到这两个参数,它需要一边下载图片一边计算大小,如果图片很多,浏览器需要不断地调整页面。这不但影响速度,也影响浏览体验。当浏览器知道了高度和宽度参数后,即使图片暂时无法显示,页面上也会腾出图片的空位,然后继续加载后面的内容。从而加载时间快了,浏览体验也更好了。)6.减少http请求(合并文件,合并图片)。
7、如果你参与到一个项目中,发现他们使用Tab来缩进代码,但是你喜欢空格,你会怎么做?
1.建议这个项目使用像EditorConfig(http://editorconfig.org/)之类的规范2.为了保持一致性,接受项目原有的风格3.直接使用VIM的retab命令
8、请写一个简单的幻灯效果页面
如果不使用JS来完成,可以加分。(如:纯CSS实现的幻灯片效果)
9、你都使用哪些工具来测试代码的性能?
Profiler,JSPerf(http://jsperf.com/nexttick-vs-setzerotimeout-vs-settimeout),Dromaeo
10、如果今年你打算熟练掌握一项新技术,那会是什么?
nodejs,html5,css3,less
11、请谈一下你对网页标准和标准制定机构重要性的理解。
(google)w3c存在的意义就是让浏览器兼容性问题尽量小,首先是他们对浏览器开发者的约束,然后是对开发者的约束。
12、什么是FOUC(无样式内容闪烁)?你如何来避免FOUC?
FOUC-Flash Of Unstyled Content文档样式闪烁<style type="text/css"media="all">@import"../fouc.css";</style>而引用CSS文件的@import就是造成这个问题的罪魁祸首。IE会先加载整个HTML文档的DOM,然后再去导入外部的CSS文件,因此,在页面DOM加载完成到CSS导入完成中间会有一段时间页面上的内容是没有样式的,这段时间的长短跟网速,电脑速度都有关系。解决方法简单的出奇,只要在<head>之间加入一个<link>或者<script>元素就可以了。
HTML相关问题:
13、doctype(文档类型)的作用是什么?你知道多少种文档类型?
此标签可告知浏览器文档使用哪种HTML或XHTML规范。该标签可声明三种DTD类型,分别表示严格版本、过渡版本以及基于框架的HTML文档。HTML 4.01规定了三种文档类型:Strict、Transitional以及Frameset。XHTML 1.0规定了三种XML文档类型:Strict、Transitional以及Frameset。
Standards(标准)模式(也就是严格呈现模式)用于呈现遵循最新标准的网页,而Quirks(包容)模式(也就是松散呈现模式或者兼容模式)用于呈现为传统浏览器而设计的网页。
14、浏览器标准模式和怪异模式之间的区别是什么?
W3C标准推出以后,浏览器都开始采纳新标准,但存在一个问题就是如何保证旧的网页还能继续浏览,在标准出来以前,很多页面都是根据旧的渲染方法编写的,如果用的标准来渲染,将导致页面显示异常。为保持浏览器渲染的兼容性,使以前的页面能够正常浏览,浏览器都保留了旧的渲染方法(如:微软的IE)。这样浏览器渲染上就产生了Quircks mode和Standars mode,两种渲染方法共存在一个浏览器上。IE盒子模型和标准W3C盒子模型:ie的width包括:padding\border。标准的width不包括:padding\border
document对象有个属性compatMode,它有两个值:BackCompat对应quirks mode CSS1Compat对应strict mode。
15、使用XHTML的局限有哪些?
xhtml要求严格,必须有head、body每个dom必须要闭合。
一些老的浏览器并不兼容。
16、如果网页内容需要支持多语言,你会怎么做?
编码UTF-8,空间域名需要支持多浏览地址。
1、应用字符集的选择2、语言书写习惯&导航结构3、数据库驱动型网站
17、data-属性的作用是什么?
data-为前端开发者提供自定义的属性,这些属性集可以通过对象的dataset属性获取,不支持该属性的浏览器可以通过getAttribute方法获取<div data-author="david"data-time="2011-06-20"data-comment-num="10">...</div>div.dataset.commentNum;//10
需要注意的是,data-之后的以连字符分割的多个单词组成的属性,获取的时候使用驼峰风格。并不是所有的浏览器都支持.dataset属性,测试的浏览器中只有Chrome和Opera支持。
18、如果把HTML5看作做一个开放平台,那它的构建模块有哪些?
<nav>,<header>,<section>,<footer>等。
19、请描述一下cookies,sessionStorage和localStorage的区别?
sessionStorage和localStorage是HTML5 Web Storage API提供的,可以方便的在web请求之间保存数据。有了本地数据,就可以避免数据在浏览器和服务器间不必要地来回传递。sessionStorage、localStorage、cookie都是在浏览器端存储的数据,其中sessionStorage的概念很特别,引入了一个“浏览器窗口”的概念。sessionStorage是在同源的同窗口(或tab)中,始终存在的数据。也就是说只要这个浏览器窗口没有关闭,即使刷新页面或进入同源另一页面,数据仍然存在。关闭窗口后,sessionStorage即被销毁。同时“独立”打开的不同窗口,即使是同一页面,sessionStorage对象也是不同的cookies会发送到服务器端。其余两个不会。Microsoft指出InternetExplorer8增加cookie限制为每个域名50个,但IE7似乎也允许每个域名50个cookie。
CSS相关问题:
20、描述下“reset”CSS文件的作用和使用它的好处。
因为浏览器的品种很多,每个浏览器的默认样式也是不同的,所以定义一个css reset可以使各浏览器的默认样式统一。
21、解释下浮动和它的工作原理。
浮动元素脱离文档流,不占据空间。浮动元素碰到包含它的边框或者浮动元素的边框停留。
22、列举不同的清除浮动的技巧,并指出它们各自适用的使用场景。
1 |
*{margin:0;padding:0;} |
|||||
2 |
body{font:36px bold;color:#F00;text-align:center;} |
|||||
3 |
#layout{background:#FF9;} |
|||||
4 |
#layout:after{display:block;clear:both;content:”";visibility:hidden;height:0;} |
|||||
5 |
#left{float:left;width:20%;height:200px;background:#DDD;line-height:200px;} |
|||||
6 |
#right{float:right;width:30%;height:80px;background:#DDD;line-height:80px;} |
<div id=”layout”><div id=”left”>Left</div><div id=”right”>Right</div></div>
此三种方法各有利弊,使用时应择优选择,比较之下第二种方法更为可取。
23、解释下CSS sprites,以及你要如何在页面或网站中使用它。
CSS Sprites其实就是把网页中一些背景图片整合到一张图片文件中,再利用CSS的“background-image”,“background-repeat”,“background-position”的组合进行背景定位,background-position可以用数字能精确的定位出背景图片的位置。
24、你最喜欢的图片替换方法是什么,你如何选择使用。
<h2><span图片丢这里></span>Hello World</h2>把span背景设成文字内容,这样又可以保证seo,也有图片的效果在上面。一般都是:alt,title,onerror
25、讨论CSS hacks,条件引用或者其他。
各个浏览器都认识,这里给firefox用;background-color:red\9;\9所有的ie浏览器可识别;background-color:yellow\0;\0是留给ie8的+background-color:pink;+ie7定了;_background-color:orange;_专门留给神奇的ie6;:root#test{background-color:purple\9;}:root是给ie9的,@media all and(min-width:0px){#test{background-color:black\0;}}这个是老是跟ie抢着认\0的神奇的opera,必须加个\0,不然firefox,chrome,safari也都认识。。。@media screen and(-webkit-min-device-pixel-ratio:0){#test{background-color:gray;}}最后这个是浏览器新贵chrome和safari的。
26、如何为有功能限制的浏览器提供网页?你会使用哪些技术和处理方法?
百度谷歌SO SOGOU Bing
27、如何视觉隐藏网页内容,只让它们在屏幕阅读器中可用?
28、你用过栅格系统吗?如果使用过,你最喜欢哪种?
比如:Bootstrap,流式栅格系统,http://960.gs/,栅格系统延续美学
29、你用过媒体查询,或针对移动端的布局/CSS吗?
1 |
@media screen and(min-width:400px)and(max-width:700px){…} |
2 |
@media handheld and(min-width:20em),screen and(min-width:20em){…} |
媒体查询,就是响应式布局。
30、你熟悉SVG样式的书写吗?
1 |
<svg xmlns="http://www.w3.org/2000/svg"xmlns:xlink="http://www.w3.org/1999/xlink"> |
||||||
2 |
<circle cx="40"cy="40"r="24"style="stroke:#006600;fill:#00cc00"/> |
||||||
3 |
<text x="250"y="150"font-family="Verdana"font-size="10px"fill="blue">Hello,out there</text> |
||||||
4 |
<defs><styletype="text/css"><![CDATA[.sample{stroke:blue;fill:#0080FF;opacity:1;}]]></style></defs> |
||||||
5 |
<use xlink:href="#sample1"class="sample"/> |
||||||
6 |
</svg> |
31、如何优化网页的打印样式?
<link rel="stylesheet"type="text/css"media="screen"href="xxx.css"/>其中media指定的属性就是设备,显示器上就是screen,打印机则是print,电视是tv,投影仪是projection。<link rel="stylesheet"type="text/css"media="print"href="yyy.css"/>但打印样式表也应有些注意事项:
32、在书写高效CSS时会有哪些问题需要考虑?
33.使用CSS预处理器的优缺点有哪些?
LESS&SassLESS是受Sass启发而开发的工具,它列出了如下开发的理由:
“为什么要开发一个Sass的替代品呢?原因很简单:首先是语法。Sass的一个关键特性是缩进式的语法,这种语法可以产生柱式外观的代码。但是你需要花费时间学习一门新的语法以及重新构建你现在的样式表。LESS给CSS带来了很多特性,使得LESS能够和CSS无缝地紧密结合在一起。因此,你可以平滑地由CSS迁移到LESS,如果你只是对使用变量或者操作感兴趣的话,你不需要学习一整门全新的语言。”
StylusStylus相对前两者较新,可以看官方文档介绍的功能。
34.如果设计中使用了非标准的字体,你该如何去实现?
所谓的标准字体是多数机器上都会有的,或者即使没有也可以由默认字体替代的字体。
方法:
35.解释下浏览器是如何判断元素是否匹配某个CSS选择器?
从后往前判断。浏览器先产生一个元素集合,这个集合往往由最后一个部分的索引产生(如果没有索引就是所有元素的集合)。然后向上匹配,如果不符合上一个部分,就把元素从集合中删除,直到真个选择器都匹配完,还在集合中的元素就匹配这个选择器了。举个例子,有选择器:
body.ready#wrapper>.lol233
先把所有class中有lol233的元素拿出来组成一个集合,然后上一层,对每一个集合中的元素,如果元素的parent id不为#wrapper则把元素从集合中删去。再向上,从这个元素的父元素开始向上找,没有找到一个tagName为body且class中有ready的元素,就把原来的元素从集合中删去。至此这个选择器匹配结束,所有还在集合中的元素满足。大体就是这样,不过浏览器还会有一些奇怪的优化。为什么从后往前匹配因为效率和文档流的解析方向。效率不必说,找元素的父亲和之前的兄弟比遍历所哟儿子快而且方便。关于文档流的解析方向,是因为现在的CSS,一个元素只要确定了这个元素在文档流之前出现过的所有元素,就能确定他的匹配情况。应用在即使html没有载入完成,浏览器也能根据已经载入的这一部分信息完全确定出现过的元素的属性。为什么是用集合主要也还是效率。基于CSS Rule数量远远小于元素数量的假设和索引的运用,遍历每一条CSS Rule通过集合筛选,比遍历每一个元素再遍历每一条Rule匹配要快得多。
36.解释一下你对盒模型的理解,以及如何在CSS中告诉浏览器使用不同的盒模型来渲染你的布局。
说到IE的bug,在IE6以前的版本中,IE对盒模型的解析出现一些问题,跟其它浏览器不同,将border与padding都包含在width之内。而另外一些浏览器则与它相反,是不包括border和padding的。
在我们开发的过程中会发现,有时候,如果对页面中的大区域进行设置时,将border、padding计算到width和height之内,反而更灵活。但W3C的CSS2.1规范却规定了他们并不能被包含其中。考虑到这个问题,css3中引入了一个新的属性:box-sizing,它具有“content-box”和”border-box“两个值。
box-sizing:content-box
当我们设置box-sizing:content-box;时,浏览器对盒模型的解释遵从我们之前认识到的W3C标准,当它定义width和height时,它的宽度不包括border和padding。
box-sizing:border-box
当我们设置box-sizing:border-box;时,浏览器对盒模型的解释与IE6之前的版本相同,当它定义width和height时,border和padding则是被包含在宽高之内的。内容的宽和高可以通过定义的“width”和“height”减去相应方向的“padding”和“border”的宽度得到。内容的宽和高必须保证不能为负,必要时将自动增大该元素border box的尺寸以使其内容的宽或高最小为0。
37、请罗列出你所知道的display属性的全部值
值 |
描述 |
none |
此元素不会被显示。 |
block |
此元素将显示为块级元素,此元素前后会带有换行符。 |
inline |
默认。此元素会被显示为内联元素,元素前后没有换行符。 |
inline-block |
行内块元素。(CSS2.1新增的值) |
list-item |
此元素会作为列表显示。 |
run-in |
此元素会根据上下文作为块级元素或内联元素显示。 |
compact |
CSS中有值compact,不过由于缺乏广泛支持,已经从CSS2.1中删除。 |
marker |
CSS中有值marker,不过由于缺乏广泛支持,已经从CSS2.1中删除。 |
table |
此元素会作为块级表格来显示(类似<table>),表格前后带有换行符。 |
inline-table |
此元素会作为内联表格来显示(类似<table>),表格前后没有换行符。 |
table-row-group |
此元素会作为一个或多个行的分组来显示(类似<tbody>)。 |
table-header-group |
此元素会作为一个或多个行的分组来显示(类似<thead>)。 |
table-footer-group |
此元素会作为一个或多个行的分组来显示(类似<tfoot>)。 |
table-row |
此元素会作为一个表格行显示(类似<tr>)。 |
table-column-group |
此元素会作为一个或多个列的分组来显示(类似<colgroup>)。 |
table-column |
此元素会作为一个单元格列显示(类似<col>) |
table-cell |
此元素会作为一个表格单元格显示(类似<td>和<th>) |
table-caption |
此元素会作为一个表格标题显示(类似<caption>) |
inherit |
规定应该从父元素继承display属性的值。 |
38、请解释一下relative、fixed、absolute和static元素的区别
39、你目前在使用哪一套CSS框架,或者在产品线上使用过哪一套?(Bootstrap,PureCSS,Foundation等等)
JS相关问题:
40、解释下事件代理。
JavaScript事件代理则是一种简单的技巧,通过它你可以把事件处理器添加到一个父级元素上,这样就避免了把事件处理器添加到多个子级元素上。当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数。这主要得益于浏览器的事件冒泡机制。事件代理用到了两个在JavaSciprt事件中常被忽略的特性:事件冒泡以及目标元素。function getEventTarget(e){e=e||window.event;return e.target||e.srcElement;}
41、解释下JavaScript中this是如何工作的。
this永远指向函数运行时所在的对象,而不是函数被创建时所在的对象。匿名函数或不处于任何对象中的函数指向window 1.如果是call,apply,with,指定的this是谁,就是谁2.普通的函数调用,函数被谁调用,this就是谁。
42、解释下原型继承的原理。
以下代码展示了JS引擎如何查找属性:
1 |
functiongetProperty(obj,prop){ |
|||||||
2 |
if(obj.hasOwnProperty(prop)) |
|||||||
3 |
returnobj[prop] |
|||||||
4 |
else if(obj.__proto__!==null) |
|||||||
5 |
returngetProperty(obj.__proto__,prop) |
|||||||
6 |
else |
|||||||
7 |
returnundefined |
|||||||
8 |
} |
43.你是如何测试JavaScript代码的?
44.AMD vs.CommonJS?
45.什么是哈希表?
散列表(也叫哈希表),是根据关键码值直接进行访问的数据结构,也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。
46.解释下为什么接下来这段代码不是IIFE(立即调用的函数表达式):function foo(){}();.
因为在解析器解析全局的function或者function内部function关键字的时候,默认是认为function声明,而不是function表达式,如果你不显示告诉编译器,它默认会声明成一个缺少名字的function,并且抛出一个语法错误信息,因为function声明需要一个名字。
var foo=function(){};
foo();
47.描述以下变量的区别:null,undefined或undeclared?
JavaScript的最初版本是这样区分的:null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。
但是,上面这样的区分,在实践中很快就被证明不可行。目前,null和undefined基本是同义的,只有一些细微的差别。
null表示"没有对象",即该处不应该有值。典型用法是:
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
该如何检测它们?
null :表示无值;undefined : 表示一个未声明的变量,或已声明但没有赋值的变量,或一个并不存在的对象属性。==运算符将两者看作相等。如果要区分两者,要使用===或typeof运算符。
以下是不正确的用法:
var exp=undefined;if(exp==undefined){alert("undefined");}
exp为null时,也会得到与undefined相同的结果,虽然null和undefined不一样。注意:要同时判断undefined和null时可使用本法。
var exp=undefined;if(typeof(exp)==undefined){alert("undefined");}
typeof返回的是字符串,有六种可能:"number"、"string"、"boolean"、"object"、"function"、"undefined"
以下是正确的用法:
var exp=undefined;if(typeof(exp)=="undefined"){alert("undefined");}
JS中如何判断null
以下是不正确的用法:
var exp=null;if(exp==null){alert("is null");}
exp为undefined时,也会得到与null相同的结果,虽然null和undefined不一样。注意:要同时判断null和undefined时可使用本法。
var exp=null;if(!exp){alert("is null");}
如果exp为undefined或者数字零,也会得到与null相同的结果,虽然null和二者不一样。注意:要同时判断null、undefined和数字零时可使用本法。
var exp=null;if(typeof(exp)=="null"){alert("is null");}
为了向下兼容,exp为null时,typeof总返回object。
var exp=null;if(isNull(exp)){alert("is null");}
JavaScript中没有isNull这个函数。
以下是正确的用法:
var exp=null;if(!exp&&typeof(exp)!="undefined"&&exp!=0){alert("is null");}
48.什么是闭包,如何使用它,为什么要使用它?
包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成“定义在一个函数内部的函数”。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
使用闭包的注意点:
49.请举出一个匿名函数的典型用例?
50.解释“JavaScript模块模式”以及你在何时使用它。
如果有提到无污染的命名空间,可以考虑加分。
51.你是如何组织自己的代码?是使用模块模式,还是使用经典继承的方法?
52.请指出JavaScript宿主对象和原生对象的区别?
指出下列代码的区别:
function Person(){}
var person=Person();
var person=new Person();
53.call和.apply的区别是什么?
call方法:
语法:call(thisObj,Object)
定义:调用一个对象的一个方法,以另一个对象替换当前对象。
说明:
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。
如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
apply方法:
语法:apply(thisObj,[argArray])
定义:应用某一对象的一个方法,用另一个对象替换当前对象。
说明:
如果 argArray 不是一个有效的数组或者不是 arguments 对象,那么将导致一个 TypeError。
如果没有提供 argArray 和 thisObj 任何一个参数,那么 Global 对象将被用作 thisObj, 并且无法被传递任何参数。
对于apply和call两者在作用上是相同的,但两者在参数上有区别的。
对于第一个参数意义都一样,但对第二个参数:
apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,而call则作为call的参数传入(从第二个参数开始)。
如 func.call(func1,var1,var2,var3)对应的apply写法为:func.apply(func1,[var1,var2,var3])
同时使用apply的好处是可以直接将当前函数的arguments对象作为apply的第二个参数传入。
54.请解释Function.prototype.bind的作用?
55.你何时优化自己的代码?
56.你能解释一下JavaScript中的继承是如何工作的吗?
57.在什么时候你会使用document.write()?
大多数生成的广告代码依旧使用document.write(),虽然这种用法会让人很不爽。
58.请指出浏览器特性检测,特性推断和浏览器UA字符串嗅探的区别?
59.请尽可能详尽的解释AJAX的工作原理。
60.请解释JSONP的工作原理,以及它为什么不是真正的AJAX。
61.你使用过JavaScript模板系统吗?
如有使用过,请谈谈你都使用过哪些库,比如Mustache.js,Handlebars等等。
62.请解释变量声明提升。
63.请描述下事件冒泡机制。
64."attribute"和"property"的区别是什么?
65.为什么扩展JavaScript内置对象不是好的做法?
66.为什么扩展JavaScript内置对象是好的做法?
67.请指出document load和document ready两个事件的区别。
68.==和===有什么不同?
69.你如何从浏览器的URL中获取查询字符串参数。
70.请解释一下JavaScript的同源策略。
71.请描述一下JavaScript的继承模式。
72.如何实现下列代码:
[1,2,3,4,5].duplicator();//[1,2,3,4,5,1,2,3,4,5]
73.描述一种JavaScript中实现memoization(避免重复运算)的策略。
74.什么是三元表达式?“三元”表示什么意思?
75.函数的参数元是什么?
76.什么是"use strict";?使用它的好处和坏处分别是什么?
jQuery相关问题:
77、解释"chaining"。
jQuery方法链接
直到现在,我们都是一次写一条jQuery语句(一条接着另一条)。
不过,有一种名为链接(chaining)的技术,允许我们在相同的元素上运行多条jQuery命令,一条接着另一条。
提示:这样的话,浏览器就不必多次查找相同的元素。
如需链接一个动作,您只需简单地把该动作追加到之前的动作上。
78、解释"deferreds"。
开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。
通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。
但是,在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。
简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是"延迟",所以deferred对象的含义就是"延迟"到未来某个点再执行。
79你知道哪些针对jQuery的优化方法。
<div id="content">
<form method="post"action="#">
<h2>交通信号灯</h2>
<ul id="traffic_light">
<li><input type="radio"class="on"name="light"value="red"/>红色</li>
<li><input type="radio"class="off"name="light"value="yellow"/>黄色</li>
<li><input type="radio"class="off"name="light"value="green"/>绿色</li>
</ul>
<input class="button"id="traffic_button"type="submit"value="Go"/>
</form>
</div>
比如需要选择红绿单选框,那么可以使用一个tag name来限制(修饰)class,如下所示:var active_light=$(“input.on”);当然也可以结合就近的ID,如下所示:var active_light=$(“#traffic_light input.on”); 如果采用下面的选择器,那么效率是低效的。var traffic_button=$(“#content.button”);因为button已经有ID了,我们可以直接使用ID选择器。如下所示:var traffic_button=$(“#traffic_button”);当然这只是对于单一的元素来讲。如果你需要选择多个元素,这必然会涉及到DOM遍历和循环,为了提高性能,建议从最近的ID开始继承。如下所示:var traffic_lights=$(“#traffic_light input”);
在使用tag来修饰class的时候,我们需要注意以下几点:(1)不要使用tag来修饰ID,如下所示:var content=$(“div#content”);这样一来,选择器会先遍历所有的div元素,然后匹配#content。(好像jQuery从1.3.1开始改变了选择器核心后,不存在这个问题了。暂时无法考证。)(2)不要画蛇添足的使用ID来修饰ID,如下所示:var traffic_light=$(“#content#traffic_light”);
$("#traffic_light input.on").bind("click",function(){}); $("#traffic_light input.on").css("border","1px dashed yellow"); $("#traffic_light input.on").css("background-color","orange"); $("#traffic_light input.on").fadeIn("slow");
但切记不要这么做。我们应该先将对象缓存进一个变量然后再操作,如下所示:
记住,永远不要让相同的选择器在你的代码里出现多次.注:(1)为了区分普通的JavaScript对象和jQuery对象,可以在变量首字母前加上$符号。(2)上面代码可以使用jQuery的链式操作加以改善。如下所示:
var$active_light=$("#traffic_light input.on"); $active_light.bind("click",function(){}) .css("border","1px dashed yellow") .css("background-color","orange") .fadeIn("slow");
//在全局范围定义一个对象(例如:window对象)
window.$my={ head:$("head"), traffic_light:$("#traffic_light"), traffic_button:$("#traffic_button") }; function do_something(){ //现在你可以引用存储的结果并操作它们
var script=document.createElement("script"); $my.head.append(script); //当你在函数内部操作是,可以继续将查询存入全局对象中去.
$my.cool_results=$("#some_ul li"); $my.other_results=$("#some_table td"); //将全局函数作为一个普通的jquery对象去使用.
$my.other_results.css("border-color","red"); $my.traffic_light.css("border-color","green"); } //你也可以在其他函数中使用它
这里的基本思想是在内存中建立你确实想要的东西,然后更新DOM。这并不是一个jQuery最佳实践,但必须进行有效的JavaScript操作。直接的DOM操作速度很慢。例如,你想动态的创建一组列表元素,千万不要这样做,如下所示:,对直接的DOM操作进行限制。
var top_100_list=[],//假设这里是100个独一无二的字符串
$mylist=$("#mylist");//jQuery选择到<ul>元素
for(var i=0,l=top_100_list.length;i<l;i++){ $mylist.append("<li>"+top_100_list[i]+"</li>"); }
我们应该将整套元素字符串在插入进dom中之前先全部创建好,如下所示:
$("#entryform input").bind("focus",function(){ $(this).addClass("selected"); }).bind("blur",function(){ $(this).removeClass("selected"); });
$("#entryform").bind("focus",function(e){ var$cell=$(e.target);//e.target捕捉到触发的目标元素
$cell.addClass("selected"); }).bind("blur",function(e){ var$cell=$(e.target); $cell.removeClass("selected"); });
当然上面代码能帮我们完成相应的任务,但如果你要寻求更高效的方法,请使用如下代码:
通过在父级监听获取焦点和失去焦点的事件,对目标元素进行操作。在上面代码中,父级元素扮演了一个调度员的角色,它可以基于目标元素绑定事件。如果你发现你给很多元素绑定了同一个事件监听,那么现在的你肯定知道哪里做错了。
jQuery对于开发者来说有一个很诱人的东西,可以把任何东西挂到$(document).ready下。尽管$(document).rady确实很有用,它可以在页面渲染时,其它元素还没下载完成就执行。如果你发现你的页面一直是载入中的状态,很有可能就是$(document).ready函数引起的。你可以通过将jQuery函数绑定到$(window).load事件的方法来减少页面载入时的cpu使用率。它会在所有的html(包括iframe)被下载完成后执行。一些特效的功能,例如拖放,视觉特效和动画,预载入隐藏图像等等,都是适合这种技术的场合。
在线压缩地址:http://dean.edwards.name/packer/压缩之前,请保证你的代码的规范性,否则可能失败,导致Js错误。
前面性能优化已经说过,ID选择器的速度是最快的。所以在HTML代码中,能使用ID的尽量使用ID来代替class。看下面的一个例子:
//创建一个list
var$myList=$('#myList'); var myListItems='<ul>'; for(i=0;i<1000;i++){ myListItems+='<li class="listItem'+i+'">This is a list item</li>';//这里使用的是class
} myListItems+='</ul>'; $myList.html(myListItems); //选择每一个li
for(i=0;i<1000;i++){ var selectedItem=$('.listItem'+i); }
在上段代码中,选择每个li总共只用了61毫秒,相比class的方式,将近快了100倍。 在代码最后,选择每个li的过程中,总共用了5066毫秒,超过5秒了。接着我们做一个对比,用ID代替class:
jQuery选择器中有一个这样的选择器,它能指定上下文。jQuery(expression,context);通过它,能缩小选择器在DOM中搜索的范围,达到节省时间,提高效率。普通方式:$(‘.myDiv’)改进方式:$(‘.myDiv’,$(“#listItem”))
这是jQuery1.3.1版本之后增加的方法,这个方法的功能就是为新增的DOM元素动态绑定事件。但对于效率来说,这个方法比较占用资源。所以请尽量不要使用它。例如有这么一段代码:
<script type="text/javascript"> $(function(){ $("p").click(function(){ alert($(this).text()); }); $("button").click(function(){ $("<p>this is second p</p>").appendTo("body"); }); })</script>
<body>
<p>this is first p</p><button>add</button>
</body>
运行后,你会发现新增的p元素,并没用被绑定click事件。你可以改成.live(“click”)方式解决此问题,代码如下:
$(function(){ $("p").live("click",function(){//改成live方式
alert($(this).text()); }); $("button").click(function(){$("<p>this is second p</p>").appendTo("body");});})
但我并不建议大家这么做,我想用另一种方式去解决这个问题,代码如下:
$(function(){ $("p").click(function(){ alert($(this).text()); }); $("button").click(function(){ $("<p>this is second p</p>").click(function(){//为新增的元素重新绑定一次
alert($(this).text()); }).appendTo("body"); }); })
虽然我把绑定事件重新写了一次,代码多了点,但这种方式的效率明显高于live()方式,特别是在频繁的DOM操作中,这点非常明显。
80、请解释.end()的用途。
在官方的API上是这样描述end()方法的:“回到最近的一个"破坏性"操作之前。即,将匹配的元素列表变为前一次的状态。”;看样子好像是找到最后一次操作的元素的上一元素,在如下的例子中:html代码:
复制代码代码如下:
<div>测试内容1</div><div>测试内容2</div>
jQuery代码:
复制代码代码如下:
$('<p>新增内容</p>').appendTo('div').addClass('c1').end().addClass('c2');
得到的结果是:
复制代码代码如下:
<div>测试内容1<p class="c1 c2">新增内容</p></div><div>测试内容2<p class="c1">新增内容</p></div>
这里我就有一点不太明白了,怎么只有第一个<p>标签有两个样式,end()方法后返回的是什么,在火狐里添加了监控,得到如下结果:1.$('<p>新增内容</p>').appendTo('div')返回的是:[p,p]对象数组,即新增后的两个p标签;2.$('<p>新增内容</p>').appendTo('div').addClass('c1')返回的是:[p.c1,p.c1]对象数组,即添加了c1类样式后的p对象数组;3.$('<p>新增内容</p>').appendTo('div').addClass('c1').end()返回的是[p.c1],是第1个<div>中的<p>,在2操作中,最后“破坏”的是第2个<div>中的<p>,所以他的前一次操作的对象是第1个<div>中的<p>,返回的就是它;4.$('<p>新增内容</p>').appendTo('div').addClass('c1').end().addClass('c2')返回的仍然是第1个<div>中的<p>;现在算是有点明白了,关键是要搞清楚最后一次操作的元素的上一元素是什么。
81、你如何给一个事件处理函数命名空间,为什么要这样做?
任何作为type参数的字符串都是合法的;如果一个字符串不是原生的JavaScript事件名,那么这个事件处理函数会绑定到一个自定义事件上。这些自定义事件绝对不会由浏览器触发,但可以通过使用.trigger()或者.triggerHandler()在其他代码中手动触发。如果type参数的字符串中包含一个点(.)字符,那么这个事件就看做是有命名空间的了。这个点字符就用来分隔事件和他的命名空间。举例来说,如果执行.bind('click.name',handler),那么字符串中的click是事件类型,而字符串name就是命名空间。命名空间允许我们取消绑定或者触发一些特定类型的事件,而不用触发别的事件。参考unbind()来获取更多信息。
jQuery的bind/unbind方法应该说使用很简单,而且大多数时候可能并不会用到,取而代之的是直接用click/keydown之类的事件名风格的方法来做事件绑定操作。但假设如下情况:需要在运行时根据用户交互的结果进行不同click事件处理逻辑的绑定,因而理论上会无数次对某一个事件进行bind/unbind操作。但又希望unbind的时候只把自己绑上去的处理逻辑给释放掉而不是所有其他地方有可能的额外的同一事件绑定逻辑。这时候如果直接用.click()/.bind('click')加上.unbind('click')来进行重复绑定的话,被unbind掉的将是所有绑定在元素上的click处理逻辑,潜在会影响到该元素其他第三方的行为。当然如果在bind的时候是显示定义了function变量的话,可以在unbind的时候提供function作为第二个参数来指定只unbind其中一个处理逻辑,但实际应用中很可能会碰到各种进行匿名函数绑定的情况。对于这种问题,jQuery的解决方案是使用事件绑定的命名空间。即在事件名称后添加.something来区分自己这部分行为逻辑范围。比如用.bind('click.myCustomRoutine',function(){...});同样是把匿名函数绑定到click事件(你可以用自己的命名空间多次绑定不同的行为方法上去),当unbind的时候用.unbind('click.myCustomRoutine')即可释放所有绑定到.myCustomRoutine命名空间的click事件,而不会解除其他通过.bind('click')或另外的命名空间所绑定的事件行为。同时,使用命令空间还可以让你一次性unbind所有此命名空间下的自定义事件绑定,通过.unbind('.myCustomRoutine')即可。要注意的是,jQuery的命名空间并不支持多级空间。因为在jQuery里面,如果用.unbind('click.myCustomRoutine.myCustomSubone'),解除的是命名空间分别为myCustomRoutine和myCustomSubone的两个并列命名空间下的所有click事件,而不是"myCustomRoutine下的myCustomSubone子空间"。
82、请说出你可以传递给jQuery方法的四种不同值。
选择器(字符串),HTML(字符串),回调函数,HTML元素,对象,数组,元素数组,jQuery对象等。
83、什么是效果队列?
jQuery中有个动画队列的机制。当我们对一个对象添加多次动画效果时后添加的动作就会被放入这个动画队列中,等前面的动画完成后再开始执行。可是用户的操作往往都比动画快,如果用户对一个对象频繁操作时不处理动画队列就会造成队列堆积,影响到效果。jQuery中有stop这个方法可以停止当前执行的动画,并且它有两个布尔参数,默认值都为false。第一个参数为true时会清空动画队列,第二个参数为true时会瞬间完成掉当前动画。所以,我们经常使用obj.stop(true,true)来停止动画。但是这还不够!正如jQuery文档中的说法,即使第二个参数为true,也仅仅是把当前在执行的动画跳转到完成状态。这时第一个参数如果也为true,后面的队列就会被清空。如果一个效果需要多个动画同时处理,我们仅完成其中的一个而把后面的队列丢弃了,这就会出现意料之外的结果。
84、请指出.get(),[],eq()的区别。
eq:返回是一个jquery对象作用是将匹配的元素集合缩减为一个元素。这个元素在匹配元素集合中的位置变为0,而集合长度变成1 get:是一个html对象数组作用是取得其中一个匹配的元素。num表示取得第几个匹配的元素。
85、请指出.bind(),.live()和.delegate()的区别。
在操纵DOM的语境中,document是根节点。
现在我们可以较容易地说明.bind()、.live()和.delegate()的不同之处了。
.bind()
$('a').bind('click',function(){alert("That tickles!")});
这是最简单的绑定方法了。JQuery扫描文档找出所有的$(‘a’)元素,并把alert函数绑定到每个元素的click事件上。
.live()
$('a').live('click',function(){alert("That tickles!")});
JQuery把alert函数绑定到$(document)元素上,并使用’click’和’a’作为参数。任何时候只要有事件冒泡到document节点上,它就查看该事件是否是一个click事件,以及该事件的目标元素与’a’这一CSS选择器是否匹配,如果都是的话,则执行函数。
live方法还可以被绑定到具体的元素(或context)而不是document上,像这样:
$('a',$('#container')[0]).live(...);
.delegate()
$('#container').delegate('a','click',function(){alert("That tickles!")});
JQuery扫描文档查找$(‘#container’),并使用click事件和’a’这一CSS选择器作为参数把alert函数绑定到$(‘#container’)上。任何时候只要有事件冒泡到$(‘#container’)上,它就查看该事件是否是click事件,以及该事件的目标元素是否与CCS选择器相匹配。如果两种检查的结果都为真的话,它就执行函数。
可以注意到,这一过程与.live()类似,但是其把处理程序绑定到具体的元素而非document这一根上。精明的JS’er们可能会做出这样的结论,即$('a').live()==$(document).delegate('a'),是这样吗?嗯,不,不完全是。
为什么.delegate()要比.live()好用
基于几个原因,人们通常更愿意选用jQuery的delegate方法而不是live方法。考虑下面的例子:
$('a').live('click',function(){blah()});//或者$(document).delegate('a','click',function(){blah()});
速度
后者实际上要快过前者,因为前者首先要扫描整个的文档查找所有的$(‘a’)元素,把它们存成jQuery对象。尽管live函数仅需要把’a’作为串参数传递以用做之后的判断,但是$()函数并未知道被链接的方法将会是.live()。
而另一方面,delegate方法仅需要查找并存储$(document)元素。
一种寻求避开这一问题的方法是调用在$(document).ready()之外绑定的live,这样它就会立即执行。在这种方式下,其会在DOM获得填充之前运行,因此就不会查找元素或是创建jQuery对象了。
灵活性和链能力
live函数也挺令人费解的。想想看,它被链到$(‘a’)对象集上,但其实际上是在$(document)对象上发生作用。由于这个原因,它能够试图以一种吓死人的方式来把方法链到自身上。实际上,我想说的是,以$.live(‘a’,…)这一形式作为一种全局性的jQuery方法,live方法会更具意义一些。
仅支持CSS选择器
最后一点,live方法有一个非常大的缺点,那就是它仅能针对直接的CSS选择器做操作,这使得它变得非常的不灵活。
欲了解更多关于CSS选择器的缺点,请参阅Exploring jQuery.live()and.die()一文。
更新:感谢Hacker News上的pedalpete和后面评论中的Ellsass提醒我加入接下来的这一节内容。
为什么选择.live()或.delegate()而不是.bind()
毕竟,bind看起来似乎更加的明确和直接,难道不是吗?嗯,有两个原因让我们更愿意选择delegate或live而不是bind:
为了把处理程序附加到可能还未存在于DOM中的DOM元素之上。因为bind是直接把处理程序绑定到各个元素上,它不能把处理程序绑定到还未存在于页面中的元素之上。
如果你运行了$(‘a’).bind(…),而后新的链接经由AJAX加入到了页面中,则你的bind处理程序对于这些新加入的链接来说是无效的。而另一方面live和delegate则是被绑定到另一个祖先节点上,因此其对于任何目前或是将来存在于该祖先元素之内的元素都是有效的。
或者为了把处理程序附加到单个元素上或是一小组元素之上,监听后代元素上的事件而不是循环遍历并把同一个函数逐个附加到DOM中的100个元素上。把处理程序附加到一个(或是一小组)祖先元素上而不是直接把处理程序附加到页面中的所有元素上,这种做法带来了性能上的好处。
停止传播
最后一个我想做的提醒与事件传播有关。通常情况下,我们可以通过使用这样的事件方法来终止处理函数的执行:
$('a').bind('click',function(e){e.preventDefault();//或者e.stopPropagation();});
不过,当我们使用live或是delegate方法的时候,处理函数实际上并没有在运行,需要等到事件冒泡到处理程序实际绑定的元素上时函数才会运行。而到此时为止,我们的其他的来自.bind()的处理函数早已运行了。
86、请指出$和$.fn的区别,或者说出$.fn的用途。
Jquery为开发插件提供了两个方法,分别是:
$.extend(obj);$.fn.extend(obj);
1.那么这两个分别是什么意思?
$.extend(obj);是为了扩展jquery本身,为类添加新的方法
$.fn.extend(obj);给JQUERY对象添加方法。
2.$.fn中的fn是什么意思,其实是prototype,即$.fn=$.prototype;
具体用法请看下面的例子:
$.extend({
add:function(a,b){
return a+b;
}
})
$.add(5,8)//return 13
注意没有,这边的调用直接调用,前面不用任何对象。直接$.+方法名
$.fn.extend(obj);对prototype进行扩展,为jquery类添加成员函数,jquery类的实例可以使用这个成员函数。
$.fn.extend({
clickwhile:function(){
$(this).click(function(){
alert($(this).val())
})
}
})
$('input').clickwhile();//当点击输入框会弹出该对象的Value值
注意调用时候前面是有对象的。即$('input')这么个东西。
87、请优化下列选择器:
$("#bar")
代码相关的问题:
88、modulo(12,5)//2 ;问题:实现满足上述结果的modulo函数。
89、"i'm a lasagna hog".split("").reverse().join("");问题:上面的语句的返回值是什么?
答案:"goh angasal a m'i"
90、(window.foo||(window.foo="bar"));问题:window.foo的值是什么?
答案:"bar"只有window.foo为假时的才是上面答案,否则就是它本身的值。
var foo="Hello";(function(){var bar="World";alert(foo+bar);})();alert(foo+bar);
91、问题:上面两个alert的结果是什么?
答案:"Hello World"和ReferenceError:bar is not defined
92、var foo=[];foo.push(1);foo.push(2);问题:foo.length的值是什么?
答案:2
有趣的问题:
91、你编写过的最酷的代码是什么?其中你最自豪的是什么?
92、在你使用过的开发工具中,最喜欢哪个?
93、你有什么业余项目吗?是哪种类型的?
94、你最爱的IE特性是什么?