打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
常见前端面试题及答案(下)

51.你是如何组织自己的代码?是使用模块模式,还是使用经典继承的方法?

请看文章-JavaScript之模块化编程和Javascript之对象的继承


52.请指出JavaScript宿主对象和原生对象的区别?

原生对象


ECMA-262 把本地对象(native object)定义为“独立于宿主环境的 ECMAScript 实现提供的对象”。


“本地对象”包含哪些内容:Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、EvalError、RangeError、ReferenceError、SyntaxError、TypeError、URIError。


由此可以看出,简单来说,本地对象就是 ECMA-262 定义的类(引用类型)。


内置对象


ECMA-262 把内置对象(built-in object)定义为“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。


同样是“独立于宿主环境”。根据定义我们似乎很难分清“内置对象”与“本地对象”的区别。而ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。如此就可以理解了。内置对象是本地对象的一种。


宿主对象


何为“宿主对象”?主要在这个“宿主”的概念上,ECMAScript中的“宿主”当然就是我们网页的运行环境,即“操作系统”和“浏览器”。


所有非本地对象都是宿主对象(host object),即由 ECMAScript 实现的宿主环境提供的对象。所有的BOM和DOM都是宿主对象。因为其对于不同的“宿主”环境所展示的内容不同。其实说白了就是,ECMAScript官方未定义的对象都属于宿主对象,因为其未定义的对象大多数是自己通过ECMAScript程序创建的对象。


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.你何时优化自己的代码?

请看文章JavaScript之高效编程 及JavaScript编码风格指南。


56.你能解释一下JavaScript中的继承是如何工作的吗?

原型链等。


57.在什么时候你会使用document.write()?

大多数生成的广告代码依旧使用document.write(),虽然这种用法会让人很不爽。


58.请指出浏览器特性检测,特性推断和浏览器UA字符串嗅探的区别?

特性检测:为特定浏览器的特性进行测试,并仅当特性存在时即可应用特性。


User-Agent检测:最早的浏览器嗅探即用户代理检测,服务端(以及后来的客户端)根据UA字符串屏蔽某些特定的浏览器查看网站内容。


特性推断:尝试使用多个特性但仅验证了其中之一。根据一个特性的存在推断另一个特性是否存在。问题是,推断是假设并非事实,而且可能导致可维护性的问题。


59.请尽可能详尽的解释AJAX的工作原理。

请参考文章AJAX工作原理。


60.请解释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是一个是跨域的,还有就是二者接收参数形式不一样!


61.你使用过JavaScript模板系统吗?

如有使用过,请谈谈你都使用过哪些库,比如Mustache.js,Handlebars等等。


62.请解释变量声明提升。

在JS里定义的变量,存在于作用域链里,而在函数执行时会先把变量的声明进行提升,仅仅是把声明进行了提升,而其值的定义还在原来位置。示例如下:


复制代码

1 var test = function() {2     console.log(name); // 输出:undefined3     var name = 'jeri';4     console.log(name); // 输出:jeri5 }6 7 test();

复制代码

上述代码与下述代码等价。


复制代码

1 var test = function() {2     var name;3     console.log(name); // 输出:undefined4     name = 'jeri';5     console.log(name); // 输出:jeri6 }7 8 test();

复制代码

由以上代码可知,在函数执行时,把变量的声明提升到了函数顶部,而其值定义依然在原来位置。


63.请描述下事件冒泡机制。

冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标(document对象)的顺序触发。


捕获型事件:事件从最不精确的对象(document 对象)开始触发,然后到最精确(也可以在窗口级别捕获事件,不过必须由开发人员特别指定)。


支持W3C标准的浏览器在添加事件时用addEventListener(event,fn,useCapture)方法,基中第3个参数useCapture是一个Boolean值,用来设置事件是在事件捕获时执行,还是事件冒泡时执行。而不兼容W3C的浏览器(IE)用attachEvent()方法,此方法没有相关设置,不过IE的事件模型默认是在事件冒泡时执行的,也就是在useCapture等于false的时候执行,所以把在处理事件时把useCapture设置为false是比较安全,也实现兼容浏览器的效果。




64.'attribute'和'property'的区别是什么?

1. 定义


Property:属性,所有的HTML元素都由HTMLElement类型表示,HTMLElement类型直接继承自Element并添加了一些属性,添加的这些属性分别对应于每个HTML元素都有下面的这5个标准特性: id,title,lang,dir,className。DOM节点是一个对象,因此,他可以和其他的JavaScript对象一样添加自定义的属性以及方法。property的值可以是任何的数据类型,对大小写敏感,自定义的property不会出现在html代码中,只存在js中。


Attribute:特性,区别于property,attribute只能是字符串,大小写不敏感,出现在innerHTML中,通过类数组attributes可以罗列所有的attribute。


2. 相同之处


标准的 DOM properties 与 attributes 是同步的。公认的(非自定义的)特性会被以属性的形式添加到DOM对象中。如,id,align,style等,这时候操作property或者使用操作特性的DOM方法如getAttribute()都可以操作属性。不过传递给getAttribute()的特性名与实际的特性名相同。因此对于class的特性值获取的时候要传入“class”。


3. 不同之处


1).对于有些标准的特性的操作,getAttribute与点号(.)获取的值存在差异性。如href,src,value,style,onclick等事件处理程序。

2).href:getAttribute获取的是href的实际值,而点号获取的是完整的url,存在浏览器差异。


65.为什么扩展JavaScript内置对象不是好的做法?

66.为什么扩展JavaScript内置对象是好的做法?

67.请指出document.onload和document.ready两个事件的区别。

页面加载完成有两种事件,一是ready,表示文档结构已经加载完成(不包含图片等非文字媒体文件),二是onload,指示页面包含图片等文件在内的所有元素都加载完成。


68.==和===有什么不同?

首先,== equality 等同,=== identity 恒等。 ==, 两边值类型不同的时候,要先进行类型转换,再比较。 ===,不做类型转换,类型不同的一定不等。


先说 ===,这个比较简单。下面的规则用来判断两个值是否===相等: 


如果类型不同,就[不相等] 

如果两个都是数值,并且是同一个值,那么[相等];(!例外)的是,如果其中至少一个是NaN,那么[不相等]。(判断一个值是否是NaN,只能用isNaN()来判断) 

如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]。 

如果两个值都是true,或者都是false,那么[相等]。 

如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。 

如果两个值都是null,或者都是undefined,那么[相等]。 

再说 ==,根据以下规则: 


如果两个值类型相同,进行 === 比较。 

如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较: 

如果一个是null、一个是undefined,那么[相等]。 

如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。 

如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。 

如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法。js核心内置类,会尝试valueOf先于toString;例外的是Date,Date利用的是toString转换。非js核心的对象,令说(比较麻烦,我也不大懂) 

任何其他组合,都[不相等]。 

69.你如何从浏览器的URL中获取查询字符串参数。

以下函数把获取一个key的参数。


复制代码

 1 function parseQueryString ( name ){ 2     name = name.replace(/[\[]/,'\\\['); 3     var regexS = '[\\?&]'+name+'=([^&#]*)'; 4     var regex = new RegExp( regexS ); 5     var results = regex.exec( window.location.href ); 6  7     if(results == null) { 8         return ''; 9     } else {10     return results[1];11     }12 }

复制代码

70.请解释一下JavaScript的同源策略。

在客户端编程语言中,如javascript和 ActionScript,同源策略是一个很重要的安全理念,它在保证数据的安全性方面有着重要的意义。同源策略规定跨域之间的脚本是隔离的,一个域的脚本不能访问和操作另外一个域的绝大部分属性和方法。那么什么叫相同域,什么叫不同的域呢?当两个域具有相同的协议, 相同的端口,相同的host,那么我们就可以认为它们是相同的域。同源策略还应该对一些特殊情况做处理,比如限制file协议下脚本的访问权限。本地的HTML文件在浏览器中是通过file协议打开的,如果脚本能通过file协议访问到硬盘上其它任意文件,就会出现安全隐患,目前IE8还有这样的隐患。


71.请描述一下JavaScript的继承模式。

关于继承请看文章JavaScript之对象的继承。


72.如何实现下列代码:[1,2,3,4,5].duplicator();//[1,2,3,4,5,1,2,3,4,5]。

73.描述一种JavaScript中实现memoization(避免重复运算)的策略。

74.什么是三元表达式?“三元”表示什么意思?

三元表达式:? :。三元--三个操作对象。


在表达式boolean-exp ? value0 : value1 中,如果“布尔表达式”的结果为true,就计算“value0”,而且这个计算结果也就是操作符最终产生的值。如果“布尔表达式”的结果为false,就计算“value1”,同样,它的结果也就成为了操作符最终产生的值。


75.JavaScript里函数参数arguments是数组吗? 

在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,通过使用下标就可以访问相应的参数。


arguments虽然有一些数组的性质,但其并非真正的数组,只是一个类数组对象。其并没有数组的很多方法,不能像真正的数组那样调用.jion(),.concat(),.pop()等方法。


76.什么是'use strict';?使用它的好处和坏处分别是什么?

在代码中出现表达式-'use strict'; 意味着代码按照严格模式解析,这种模式使得Javascript在更严格的条件下运行。


好处:


消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;

消除代码运行的一些不安全之处,保证代码运行的安全;

提高编译器效率,增加运行速度;

为未来新版本的Javascript做好铺垫。

坏处:


同样的代码,在'严格模式'中,可能会有不一样的运行结果;一些在'正常模式'下可以运行的语句,在'严格模式'下将不能运行。


77.解释'chaining'。

jQuery方法链接。直到现在,我们都是一次写一条jQuery语句(一条接着另一条)。不过,有一种名为链接(chaining)的技术,允许我们在相同的元素上运行多条jQuery命令,一条接着另一条。


提示:这样的话,浏览器就不必多次查找相同的元素。


如需链接一个动作,您只需简单地把该动作追加到之前的动作上。


78.解释'deferreds'。

开发网站的过程中,我们经常遇到某些耗时很长的javascript操作。其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是立即能得到结果的。


通常的做法是,为它们指定回调函数(callback)。即事先规定,一旦它们运行结束,应该调用哪些函数。


但是,在回调函数方面,jQuery的功能非常弱。为了改变这一点,jQuery开发团队就设计了deferred对象。


简单说,deferred对象就是jQuery的回调函数解决方案。在英语中,defer的意思是'延迟',所以deferred对象的含义就是'延迟'到未来某个点再执行。


79.你知道哪些针对jQuery的优化方法?

1.总是从ID选择器开始继承在jQuery中最快的选择器是ID选择器,因为它直接来自于JavaScript的getElementById()方法。


例如有一段HTML代码:


复制代码

 1

2    
3        

交通信号灯

4        
    5            
  • 6                 红色 7            
  • 8            
  • 9                 黄色10            
  • 11            
  • 12                 绿色13            
  • 14        
15         16    
17

复制代码

比如需要选择红绿单选框,那么可以使用一个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”);


2.在class前使用tag(标签名)在jQuery中第二快的选择器是tag(标签)选择器(比如:$(“head”))。


跟ID选择器累时,因为它来自原生的getElementsByTagName()方法。继续看刚才那段HTML代码:


在使用tag来修饰class的时候,我们需要注意以下几点:(1)不要使用tag来修饰ID,如下所示:var content=$(“div#content”);这样一来,选择器会先遍历所有的div元素,然后匹配#content。(好像jQuery从1.3.1开始改变了选择器核心后,不存在这个问题了。暂时无法考证。)(2)不要画蛇添足的使用ID来修饰ID,如下所示:var traffic_light=$(“#content#traffic_light”);


3.将jQuery对象缓存起来把jQuery对象缓存起来就是要告诉我们要养成将jQuery对象缓存进变量的习惯。


下面是一个jQuery新手写的一段代码:


1 $('#traffic_light input.on').bind('click',function(){});2 $('#traffic_light input.on').css('border','1px dashed yellow');3 $('#traffic_light input.on').css('background-color','orange');4 $('#traffic_light input.on').fadeIn('slow');

但切记不要这么做。我们应该先将对象缓存进一个变量然后再操作,如下所示:


记住,永远不要让相同的选择器在你的代码里出现多次.注:(1)为了区分普通的JavaScript对象和jQuery对象,可以在变量首字母前加上$符号。(2)上面代码可以使用jQuery的链式操作加以改善。如下所示:


复制代码

1 var $active_light = $('#traffic_light input.on');2 3 $active_light.bind('click',function(){})4 .css('border','1px dashed yellow')5 .css('background-color','orange')6 .fadeIn('slow');

复制代码

4.如果你打算在其他函数中使用jQuery对象,那么你必须把它们缓存到全局环境中。


如下代码所示:


复制代码

 1 // 在全局范围定义一个对象(例如:window对象) 2 window.$my = { 3     head:$('head'), 4     trafficLight:$('#trafficLight'), 5     trafficButton:$('#trafficButton') 6 }; 7  8 function doSomething(){ 9     // 现在你可以引用存储的结果并操作它们10     var script=document.createElement('script');11     $my.head.append(script);12 13     // 当你在函数内部操作是,可以继续将查询存入全局对象中去.14     $my.coolResults=$('#some_ul li');15     $my.otherResults=$('#some_table td');16 17     // 将全局函数作为一个普通的jquery对象去使用.18     $my.otherResults.css('border-color','red');19     $my.trafficLight.css('border-color','green');20 }21 // 你也可以在其他函数中使用它.

复制代码

这里的基本思想是在内存中建立你确实想要的东西,然后更新DOM。这并不是一个jQuery最佳实践,但必须进行有效的JavaScript操作。直接的DOM操作速度很慢。例如,你想动态的创建一组列表元素,千万不要这样做,如下所示:对直接的DOM操作进行限制。


复制代码

1 var top_100_list = [];// 假设这里是100个独一无二的字符串2 var $mylist = $('#mylist');// jQuery选择到

    元素3 4 for(var i = 0,l = top_100_list.length;i
  • ' + top_100_list[i] + '
  • ');6 }

    复制代码

    我们应该将整套元素字符串在插入进dom中之前先全部创建好,如下所示:


    1 $('#entryform input').bind('focus',function() {2     $(this).addClass('selected');3 }).bind('blur',function(){4     $(this).removeClass('selected');5 });

    5.冒泡除非在特殊情况下,否则每一个js事件(例如:click,mouseover等.)都会冒泡到父级节点。


    当我们需要给多个元素调用同个函数时这点会很有用。代替这种效率很差的多元素事件监听的方法就是,你只需向它们的父节点绑定一次。比如,我们要为一个拥有很多输入框的表单绑定这样的行为:当输入框被选中时为它添加一个class传统的做法是,直接选中input,然后绑定focus等,如下所示:


    复制代码

    1 $('#entryform').bind('focus',function(e) {2     var $cell = $(e.target); // e.target捕捉到触发的目标元素3     $cell.addClass('selected');4 }).bind('blur',function(e) {5     var $cell = $(e.target);6     $cell.removeClass('selected');7 });

    复制代码

    当然上面代码能帮我们完成相应的任务,但如果你要寻求更高效的方法,请使用如下代码:


    通过在父级监听获取焦点和失去焦点的事件,对目标元素进行操作。在上面代码中,父级元素扮演了一个调度员的角色,它可以基于目标元素绑定事件。如果你发现你给很多元素绑定了同一个事件监听,那么现在的你肯定知道哪里做错了。


    6.推迟到$(window).load。


    jQuery对于开发者来说有一个很诱人的东西,可以把任何东西挂到$(document).ready下。尽管$(document).rady确实很有用,它可以在页面渲染时,其它元素还没下载完成就执行。如果你发现你的页面一直是载入中的状态,很有可能就是$(document).ready函数引起的。你可以通过将jQuery函数绑定到$(window).load事件的方法来减少页面载入时的cpu使用率。它会在所有的html(包括iframe)被下载完成后执行。一些特效的功能,例如拖放,视觉特效和动画,预载入隐藏图像等等,都是适合这种技术的场合。


    7.压缩JavaScript。


    在线压缩地址:http://dean.edwards.name/packer/压缩之前,请保证你的代码的规范性,否则可能失败,导致Js错误。


    8.尽量使用ID代替Class。


     前面性能优化已经说过,ID选择器的速度是最快的。所以在HTML代码中,能使用ID的尽量使用ID来代替class。看下面的一个例子:


    复制代码

     1 // 创建一个list 2 var $myList = $('#myList'); 3 var myListItems = '

      '; 4  5 for(var i = 0; i < 1000;="" i="" ++)="" {="" 6=""  =""  ="" mylistitems="" +='
    • This is a list item'; 7     // 这里使用的是class 8 } 9 10 myListItems += '
    ';11 $myList.html(myListItems);12 // 选择每一个li13 14 for(var i = 0; i<1000; i++)="" {15=""  =""  ="" var="" selecteditem="$('.listItem'" +="" i);16="">

    复制代码

    在上段代码中,选择每个li总共只用了61毫秒,相比class的方式,将近快了100倍。       在代码最后,选择每个li的过程中,总共用了5066毫秒,超过5秒了。接着我们做一个对比,用ID代替class:


    9.给选择器一个上下文。


    jQuery选择器中有一个这样的选择器,它能指定上下文。jQuery(expression,context);通过它,能缩小选择器在DOM中搜索的范围,达到节省时间,提高效率。普通方式:$(‘.myDiv’)改进方式:$(‘.myDiv’,$(“#listItem”))。


    10.慎用.live()方法(应该说尽量不要使用)。


    这是jQuery1.3.1版本之后增加的方法,这个方法的功能就是为新增的DOM元素动态绑定事件。但对于效率来说,这个方法比较占用资源。所以请尽量不要使用它。例如有这么一段代码:


    复制代码

     1 13 14    

    this is first p

    15     16

    复制代码

    运行后,你会发现新增的p元素,并没用被绑定click事件。你可以改成.live(“click”)方式解决此问题,代码如下:


    复制代码

     1 $(function() { 2     $('p').live('click',function() { 3         // 改成live方式 4         alert($(this).text()); 5     }); 6  7     $('button').click(function() { 8         $('

    this is second p

    ').appendTo('body'); 9     });10 })

    复制代码

    但我并不建议大家这么做,我想用另一种方式去解决这个问题,代码如下:


    复制代码

     1 $(function() { 2     $('p').click(function() { 3         alert($(this).text()); 4     }); 5  6     $('button').click(function() { 7         $('

    this is second p

    ').click(function() { 8             // 为新增的元素重新绑定一次 9             alert($(this).text());10         }).appendTo('body');11     });12 })

    复制代码

    虽然我把绑定事件重新写了一次,代码多了点,但这种方式的效率明显高于live()方式,特别是在频繁的DOM操作中,这点非常明显。


    80.请解释.end()的用途。

    在官方的API上是这样描述end()方法的:“回到最近的一个'破坏性'操作之前。即,将匹配的元素列表变为前一次的状态。”;看样子好像是找到最后一次操作的元素的上一元素,在如下的例子中:html代码:


    复制代码代码如下:


    1

    测试内容1
    测试内容2

    jQuery代码:


    复制代码代码如下:


    1 $('

    新增内容

    ').appendTo('div').addClass('c1').end().addClass('c2');

    复制代码代码如下:


    复制代码

    1

    测试内容12    

    新增内容

    3
    4
    测试内容25    

    新增内容

    6

    复制代码

    这里我就有一点不太明白了,怎么只有第一个

    标签有两个样式,end()方法后返回的是什么,在火狐里添加了监控,得到如下结果:1.$('

    新增内容

    ').appendTo('div')返回的是:[p,p]对象数组,即新增后的两个p标签;2.$('

    新增内容

    ').appendTo('div').addClass('c1')返回的是:[p.c1,p.c1]对象数组,即添加了c1类样式后的p对象数组;3.$('

    新增内容

    ').appendTo('div').addClass('c1').end()返回的是[p.c1],是第1个
    中的

    ,在2操作中,最后“破坏”的是第2个

    中的

    ,所以他的前一次操作的对象是第1个

    中的

    ,返回的就是它;4.$('

    新增内容

    ').appendTo('div').addClass('c1').end().addClass('c2')返回的仍然是第1个
    中的

    ;现在算是有点明白了,关键是要搞清楚最后一次操作的元素的上一元素是什么。


    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()


    1 $('a').bind('click', function() {alert('That tickles!')});

    这是最简单的绑定方法了。JQuery扫描文档找出所有的$(‘a’)元素,并把alert函数绑定到每个元素的click事件上。


    .live()


    1 $('a').live('click', function() {alert('That tickles!')});

    JQuery把alert函数绑定到$(document)元素上,并使用’click’和’a’作为参数。任何时候只要有事件冒泡到document节点上,它就查看该事件是否是一个click事件,以及该事件的目标元素与’a’这一CSS选择器是否匹配,如果都是的话,则执行函数。


    live方法还可以被绑定到具体的元素(或context)而不是document上,像这样:


    1 $('a', $('#container')[0]).live(...);

    .delegate()


    1 $('#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方法。考虑下面的例子:


    1 $('a').live('click', function(){blah()}); // 或者2 $(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选择器做操作,这使得它变得非常的不灵活。


    为什么选择.live()或.delegate()而不是.bind()?

    毕竟,bind看起来似乎更加的明确和直接,难道不是吗?嗯,有两个原因让我们更愿意选择delegate或live而不是bind:


    为了把处理程序附加到可能还未存在于DOM中的DOM元素之上。因为bind是直接把处理程序绑定到各个元素上,它不能把处理程序绑定到还未存在于页面中的元素之上。


    如果你运行了$(‘a’).bind(…),而后新的链接经由AJAX加入到了页面中,则你的bind处理程序对于这些新加入的链接来说是无效的。而另一方面live和delegate则是被绑定到另一个祖先节点上,因此其对于任何目前或是将来存在于该祖先元素之内的元素都是有效的。


    或者为了把处理程序附加到单个元素上或是一小组元素之上,监听后代元素上的事件而不是循环遍历并把同一个函数逐个附加到DOM中的100个元素上。把处理程序附加到一个(或是一小组)祖先元素上而不是直接把处理程序附加到页面中的所有元素上,这种做法带来了性能上的好处。


    停止传播


    最后一个我想做的提醒与事件传播有关。通常情况下,我们可以通过使用这样的事件方法来终止处理函数的执行:


    1 $('a').bind('click', function(e) {2     e.preventDefault();3     // 或者 e.stopPropagation();4 });

    不过,当我们使用live或是delegate方法的时候,处理函数实际上并没有在运行,需要等到事件冒泡到处理程序实际绑定的元素上时函数才会运行。而到此时为止,我们的其他的来自.bind()的处理函数早已运行了。


    86.请指出$和$.fn的区别,或者说出$.fn的用途。

    Jquery为开发插件提供了两个方法,分别是:


    1 $.extend(obj);2 $.fn.extend(obj);

    1.那么这两个分别是什么意思?

    $.extend(obj);是为了扩展jquery本身,为类添加新的方法。


    $.fn.extend(obj);给JQUERY对象添加方法。


    2.$.fn中的fn是什么意思,其实是prototype,即$.fn=$.prototype;

    具体用法请看下面的例子:


    复制代码

    1 $.extend({2 3     add:function(a, b) {4         return a+b;5     }6 })7 8 $.add(5,8); // return 13

    复制代码

    注意没有,这边的调用直接调用,前面不用任何对象。直接$.+方法名


    $.fn.extend(obj);对prototype进行扩展,为jquery类添加成员函数,jquery类的实例可以使用这个成员函数。


    复制代码

     1 $.fn.extend({ 2  3     clickwhile:function(){ 4  5         $(this).click(function(){ 6             alert($(this).val()) 7         }) 8     } 9 })10 11 $('input').clickwhile(); // 当点击输入框会弹出该对象的Value值

    复制代码

    注意调用时候前面是有对象的。即$('input')这么个东西。


    87.请写出一个函数实现N!的计算。N取很大的值时,该怎么办?

    使用循环、递归都能写出函数。


    当N取值很大时,应该考虑把数值转化为字符串再进行运算。大数乘法再转化为大数加法运算,其具体算法应该有不少C语言实现,可以参考一下。


    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


    喜欢编程的宝宝可以加大牛微信 tang365666,备注数字2 ,即可免费获取更多编程学习视频,以及面试题,一定记得备注数字2
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
一些实用的 jQuery 技巧
jQuery最佳实践
2014年最新前端开发面试题(面霸题库)
javaScript知识点总结(必看篇)
jQuery性能优化28条建议
JavaScript 框架比较
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服