前端面试题
1、什么是优雅降级和渐进增强?
优雅降级:web站点在所有新式浏览器中都能正常工作,如果用户用的是老式浏览器,则代码会检查它们能否正常工作。由于IE独特的盒模型布局问题,针对不同版本的IE的hack实践过优雅降级了,为那些无法支持功能的浏览器增加候选方案,使之在老式浏览器上以某种形式降级体验却不至于完全失效。
一开始就构建完整的功能,然后在针对低版本的浏览器进行兼容。
渐进增强:从被所有浏览器支持的基本功能开始,逐步的添加那些只有新式浏览器支持的功能,向页面增加无害于基础浏览器的额外样式和功能。当浏览器支持时,它们会自动呈现出来并发挥作用。
针对低版本的浏览器进行构建页面,保证最基本功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。
2、说说你对语义化的理解?
- 特定的标签去做特定的事情。
- 和搜索引擎建立良好沟通,有利于SEO爬虫抓取更多的有效信息,更好的理解我们的页面,爬虫依赖于标签来确定上下文和各个关键字的权重。
- 在缺少样式的情况下,页面不至于太乱。
- 结构清晰,语义化更具可读性,利于前端人员的开发和维护。
3、请说出几种减少页面加载时间的方法?
- 优化图片。
- 图像格式的选择(GIF:提供的颜色较少,可以用在一些对颜色要求不高的地方)。
- 优化css(压缩合并css,如:margin-top,margin-left)
- 网址后加斜杠(如:www.myweb.com/目录,会判断这个目录是什么文件类型)。
- 标明高度和宽度(如果浏览器没有找到这两个参数,它需要一边下载图片一边计算大小,如果图片很多,浏览器需要不断的调整页面。这不但影响速度,也影响浏览体验。当浏览器知道了高度和宽度参数后,即使图片暂时无法显示,页面上也会腾出图片的空位,然后继续加载后面的内容。从而减少了加载时间,提升浏览体验。
- 减少http请求(合并文件,雪碧图)。
4、标准浏览器模式和怪异模式之间的区别是什么?
W3C标准推出后,浏览器都开始采纳新标准,但是存在一个问题,就是如何保证旧的网页还能继续浏览,因为之前的网页都是根据旧的渲染方法编写的,如果用新的标准来渲染,会导致页面异常。为了保持浏览器渲染的兼容性,使旧的页面能够正常浏览,浏览器都保存了旧的渲染方法。这样浏览器就产生了Quirks mode(怪异模式)和Standars mode(标准模式),两种渲染方法共存于一个浏览器上。
IE的盒模型标准和标准的W3C盒模型:IE的width包括padding和border,标准的width不包括padding和border。
在js中如何判断当前浏览器正在以何种方式解析?
document对象有个compatMode属性,它有两个值:BackCompat对应quirks mode,CSS1Compat对应strict mode。
5、data-属性的作用是什么?
data-*属性用于存储页面或应用程序的私有自定义数据。data-*属性赋予我们在所有HTML元素上嵌入自定义data属性的能力。存储的数据能够被页面的javascript利用,以创建更好的用户体验(不进行AJAX调用或服务器端数据库查询)。
data-*属性包括两部分:
- 属性名不应该包含任何大写字母,并且在前缀“data-”之后必须至少有一个字符。
- 属性值可以是任意字符串。
6、列举不同的清除浮动的技巧,以及它们的适用场景?
- 使用空标签清除浮动。在浮动标签后面添加一个空标签定义clear:both,弊端就是增加了无意义标签。
- 使用overflow。给包含浮动元素的父标签添加css属性overflow:auto;zoom:1;zoom用于兼容IE6。
- 使用after伪类对象清除浮动。该方法只适用于非IE浏览器。需要注意以下几点:伪对象中必须设置height:0,否则该元素会比实际高出若干像素。content属性是必须的,但其值可以为空。
- 浮动外部元素。
7、解释一下你对盒模型的理解,以及如何在css中告诉浏览器使用不同的盒模型来渲染页面?
盒模型由内容区、内边距(padding)、边框(border)、外边距(margin)构成。
CSS3引入了一个新的属性:box-sizing,它具有content-box和border-box两个值。
- 当我们设置box-sizing:content-box时,浏览器对盒模型的解释遵从我们之前认识到的W3C标准,当它定义width和height时,它的宽度和高度不包括padding和border。
- 当我们设置box-sizing:border-box时,浏览器对盒模型的解释与IE6之前的版本相同,当它定义width和height时,它的宽度和高度包括padding和border。
8、请解释以下事件委托?
Javascript事件委托是一种简单的技巧,通过它你可以把事件处理器添加到一个父元素上,这样就避免了把事件处理器添加到多个子元素上,造成内存的浪费。
当我们需要对很多元素添加事件处理器时,可以通过将事件添加到它们的父节点上而将事件委托给父节点来触发事件处理函数。这主要得益于事件的冒泡机制。事件委托用到了两个在javascript事件中常被忽略的特性:事件冒泡及目标元素。
document.querySelector(".ele").on("click"function(ev){
var ev=ev || window.event;
var target=ev.target || ev.srcElement;
})
9、call和apply的区别是什么?
call方法:
- 语法:call(thisObj,Object)
- 定义:调用一个对象的一个方法,以另一个对象替换当前对象。
- 说明:call方法可以用来代替另一个对象调用一个方法。call方法可将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象。如果没有提供thisObj参数,那么Global对象被用作thisObj。
apply方法:
- 语法:apply(thisObj,[argArray])
- 定义:应用某一对象的一个方法,用另一个对象替换当前对象。
- 说明:如果argArray不是一个有效的数组或者不是arguments对象,那么将导致一个TypeError。如果没有提供argArray和thisObj任何一个参数,那么Global将被用作thisObj,并且无法传递任何参数。
对于call和apply两者在作用上是相同的,但是两者在参数上有以下区别:
对于第一个参数意义都一样,但是对于第二个参数:apply传入的是一个参数数组,也就是将多个参数组合成一个数组传入,而call则作为call的参数传入(从第二个参数开始)。使用apply的好处是可以直接将当前函数的arguments对象作为apply的第二个参数传入。
10、你如何优化自己的代码?
详见文章Javascript之高效编程和Javascript编码风格指南。
11、在什么时候你会使用document.write()?
大多数生成的广告代码依旧使用document.write(),虽然这种用法会让人很不爽。
12、请解释一下AJAX的工作原理?
详见文章AJAX工作原理。
13、请解释jsonp的工作原理,以及它为什么不是真正的AJAX?
JSONP(JSON with Padding)是一个简单高效的跨域方式,html中的script标签可以加载并执行其它域的javascript,于是我们可以通过script标签动态加载其它域的资源。例如我要从域A的页面pageA加载域B的数据,那么在域B的页面pageB中我以JavaScript的形式声明pageA需要的数据,然后在 pageA中用script标签把pageB加载进来,那么pageB中的脚本就会得以执行。JSONP在此基础上加入了回调函数,pageB加载完之后会执行pageA中定义的函数,所需要的数据会以参数的形式传递给该函数。JSONP易于实现,但是也会存在一些安全隐患,如果第三方的脚本随意地执行,那么它就可以篡改页面内容,截获敏感数据。但是在受信任的双方传递数据,JSONP是非常合适的选择。
AJAX是不跨域的,而JSONP是一个是跨域的,还有就是二者接收参数形式不一样!
14、请描述下事件冒泡机制?
冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。
捕获型事件:事件从最不精确的对象(document对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。
支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,其中第三个参数useCapure是一个boolean值,用来设置事件是在事件捕获时执行,还是在事件冒泡时执行。而不兼容W3C标准的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是useCapture等于false时执行,所以在处理事件时把useCapture设置为false是比较安全的,也实现浏览器的兼容效果。
15、请指出document.onload和document.ready两个事件的区别?
页面加载完成有两种事件,一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件),二是onload,指示页面包含图片等文件在内的所有元素都加载完成。
16、==和===有什么区别?
首先,== equality 等同,=== identity 恒等。==, 两边值类型不同的时候,要先进行类型转换,再比较。===,不做类型转换,类型不同的一定不等。
先说 ===,这个比较简单。下面的规则用来判断两个值是否===相等:
- 如果类型不同,就[不相等]
- 如果两个都是数值,并且是同一个值,那么[相等];(!例外)的是,如果其中至少一个是NaN,那么[不相等]。(判断一个值是否是NaN,只能用isNaN()来判断)
- 如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。
- 如果两个值都是true,或者都是false,那么[相等]。
- 如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。
- 如果两个值都是null,或者都是undefined,那么[相等]。
再说 ==,根据以下规则:
- 如果两个值类型相同,进行 === 比较。
- 如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较:
- 如果一个是null、一个是undefined,那么[相等]。
- 如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。
- 如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
- 如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。非js核心的对象,令说(比较麻烦,我也不大懂)
- 任何其他组合,都[不相等]。
17、请描述一下Javascript的继承模式?
详见文章Javascript之对象的继承。
18、Javascript里函数参数arguments是数组吗?
在函数代码中,使用特殊对象arguments,开发者无需明确指出参数名,通过下标就可以访问相应的参数。
arguments虽然有些数组的性质,但其并非真正的数组,只是一个类数组对象。其并没有数组的很多方法,不能像真正的数组那样调用jion()、concat()、pop()等方法。
19、解释“deferreds”?
开发网站过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步操作(比如遍历一个大型数组),它们都不是立即能得到结果的。
通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。
但是,在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。
简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是“延迟”,所以deferred对象的含义就是“延迟”到未来的某个点再执行。
20、请指出.get(),.eq()的区别?
eq返回的是一个jquery对象。get返回的是一个html对象。
21、请指出.bind(),.live(),.delegae()的区别?
.bind()
- 这是最直接的绑定方法。jQuery扫描文档找到所有目标元素,然后给每一个找到的元素的绑定事件添加处理函数。
- 优点:
· 这个方法提供了一种在各个浏览器之间对事件处理的兼容性解决方案。
· 非常方便简单的绑定事件到元素上。
· .click(),.hover()...这些非常方便的事件绑定,都是bind的一种简化处理方式。
· 对于利用ID选择出来的元素是非常好的,不仅仅是可以很快的hook上去(因为一个页面只有一个ID),而且当事件发生时,handler可以立即被执行(相对于后面的live,delegate)。
- 缺点:
· 它会绑定事件到所有的选出来的元素上。
· 它不会绑定到在它执行完后动态添加的那些元素上。
· 当元素很多时,会出现效率问题。
· 当页面加载完的时候,你才可以bind(),所以可能产生效率问题。
.live()
- jQuery绑定处理函数到指定的元素,并把‘click’和‘a’作为函数的参数。有事件冒泡到指定元素节点的时候,检查这个事件是不是click事件,target element能不能匹配‘a’css选择器,如果两个条件都是true,处理函数执行。
- 优点:
· 这里只有一次的事件绑定,而不想bind()那样给所有元素挨个绑定。
· 那些动态添加的elements依然可以触发那些早先绑定的事件,因为事件真正的绑定是在指定的元素上。
· 你可以在document ready之前就可以绑定那些需要的事件。
- 缺点:
· 从1.7开始已经不被推荐了,所以你也可以开始逐步淘汰它了。
· Chaining没有被正确的支持。
· 当使用event.stopPropagation()是没用的,因为都要到达document。
· 。。。
.delegate()
- jQuery绑定处理函数到指定的元素,并把‘click’和‘a’作为函数的参数。有事件冒泡到指定元素节点的时候,检查这个事件是不是click事件,target element能不能匹配‘a’css选择器,如果两个条件都是true,处理函数执行。
- 优点:
· 你可以选择你把这个事件放到那个元素上了。
· chaining被正确的支持了。
· jQuery仍然需要迭代查找所有的selector/event data来决定那个子元素来匹配,但是因为你可以决定放在那个根元素上,所以可以有效的减小你所要查找的元素。
· 可以用在动态添加的元素上。
- 缺点:
· 需要查找那个那个元素上发生了那个事件了,尽管比document少很多了,不过,你还是得浪费时间来查找。
为什么推荐使用live()或delegate()而不用bind()?
- 绑定事件处理函数到还不存在DOM中的元素。 bind 方法直接绑定函数到每个单独的元素,不能绑定到还没有添加到页面里的元素,如果你写了$(‘a’).bind(…),然后用ajax给页面增加了新的链接,新添加的链接不会绑定事件。live 或 delegate 或者其它绑定到祖先元素的事件,让现在有的元素,或者以后增的元素都可以使用。
- 绑定处理函数到一个元素或者少数几个元素,监听后代元素,而不是绑定100个相同的处理函数到单独的元素。这样更有性能优势。
.On()
- 其实.bind(), .live(), .delegate()都是通过.on()来实现的,.unbind(), .die(), .undelegate(),也是一样的都是通过.off()来实现的。
优点:
· 提供了一种统一绑定事件的方法。
· 仍然提供了.delegate()的优点,当然如果需要你也可以直接用.bind()。
缺点:
· 也许会对你产生一些困扰,因为它隐藏了一前面我们所介绍的三种方法的细节。
结论:
用.bind()的代价是非常大的,它会把相同的一个事件处理程序hook到所有匹配的DOM元素上。
不要再用.live()了,它已经不再被推荐了,而且还有许多问题。
.delegate()会提供很好的方法来提高效率,同时我们可以添加一事件处理方法到动态添加的元素上。
我们可以用.on()来代替上述的3种方法。
22、jQuery为开发插件提供了两个方法,分别是:
- $.extend(obj); 扩展jQuery本身,为类添加新的方法。
- $.fn.extend(obj); 给jQuery对象添加方法。