记阿里前端第一次电面
前端妹子一枚,研究生二年级,学习前端半年多,以前从未找过工作,今年春天想先投投实习练练手。实验室投前端的同学有六个,前几天,大家陆陆续续也都接到了阿里的面试电话,所以心里一直惴惴不安。终于,3月4号星期六早上十点多便接到了浙江杭州的电话,本来觉得没准备好还想推一推的,最后一咬牙觉得就这样吧,于是便开始电面。 面试官是个声音很温柔的男生,简单自我介绍后,便开始问一些基础问题了。
Q&A
1..
Q:谈谈闭包
A:闭包指的是有权访问另一个函数作用域中变量的函数,创建闭包的常见方式,就是在一个函数内部创建另一个函数。要理解闭包,首先必须理解Javascript特殊的变量作用域。变量的作用域无非就是两种:全局变量和局部变量。函数内部可以直接读取全局变量,但在函数外部无法读取函数内的局部变量。如果我们有时候需要得到函数内的局部变量。正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。
function f1(){
var n=999;
function f2(){
alert(n);
}
}
在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的”链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,就可以在f1外部读取它的内部变量了!
function f1(){
var n=999;
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result();
2..
Q:那闭包的用处有什么?
A:闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result();
nAdd();
result();
在这段代码中,result实际上就是闭包f2函数。它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
为什么会这样呢?原因就在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。
这段代码中另一个值得注意的地方,就是”nAdd=function(){n+=1}”这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。
3..
Q:使用闭包的问题?
A:由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。
由于IE9 之前的版本对JScript 对象和COM 对象使用不同的垃圾收集。因此闭包在IE 的这些版本中会导致一些特殊的问题。具体来说,如果闭包的作用域链中保存着一个HTML 元素,那么就意味着该元素将无法被销毁。
function assignHandler(){
var element = document.getElementById("someElement");
element.onclick = function(){
alert(element.id);
};
}
以上代码创建了一个作为element 元素事件处理程序的闭包,而这个闭包则又创建了一个循环引用。由于匿名函数保存了一个对assignHandler()的活动对象的引用,因此就会导致无法减少element 的引用数。只要匿名函数存在,element 的引用数至少也是1,因此它所占用的内存就永远不会被回收,这是IE的问题,所以闭包和内存泄漏没半毛钱关系。
解决办法,把element.id 的一个副本保存在一个变量中,从而消除闭包中该变量的循环引用同时将element变量设为null。
function assignHandler(){
var element = document.getElementById("someElement");
var id = element.id;
element.onclick = function(){
alert(id);
};
element = null;
}
4..
Q:谈谈对Ajax的了解吧?
A:Ajax是无需刷新页面就能够从服务器取得数据的一种方法。
- Ajax技术的核心是XMLHttpRequest对象(XHR对象)
- XHR对象由微软最早在IE5中引用,用于通过JavaScript从服务器取得XML数据.在IE中可能会遇到三种不同版本的XHR对象。
- 在此之后,IE7+、Firefox、Safari、Chrome、Opera都实现了相同的特性,使XHR成为了Web的一个事实标准,它们都支持原生的XHR对象。
- 虽然实现之间有差异,但XHR对象的基本用法在不同浏览器间还是相对规范的,因此可以放心地用在Web开发之中。
5…
Q:Ajax为什么不能跨域?
A:由于浏览器实现的同源策略的限制,XmlHttpRequest只允许请求当前源(域名、协议、端口)的资源,所以AJAX是不允许跨域的。不过 像