记阿里前端第一次电面(蚂蚁金服)

记阿里前端第一次电面

前端妹子一枚,研究生二年级,学习前端半年多,以前从未找过工作,今年春天想先投投实习练练手。实验室投前端的同学有六个,前几天,大家陆陆续续也都接到了阿里的面试电话,所以心里一直惴惴不安。终于,3月4号星期六早上十点多便接到了浙江杭州的电话,本来觉得没准备好还想推一推的,最后一咬牙觉得就这样吧,于是便开始电面。 面试官是个声音很温柔的男生,简单自我介绍后,便开始问一些基础问题了。


Q&A

1..
Q:谈谈闭包
A:闭包指的是有权访问另一个函数作用域中变量的函数,创建闭包的常见方式,就是在一个函数内部创建另一个函数。要理解闭包,首先必须理解Javascript特殊的变量作用域。变量的作用域无非就是两种:全局变量和局部变量。函数内部可以直接读取全局变量,但在函数外部无法读取函数内的局部变量。如果我们有时候需要得到函数内的局部变量。正常情况下,这是办不到的,只有通过变通方法才能实现。那就是在函数的内部,再定义一个函数。

 function f1(){
    var n=999;
    function f2(){
      alert(n); // 999
    }
  }

在上面的代码中,函数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(); // 999

2..
Q:那闭包的用处有什么?
A:闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

function f1(){
    var n=999;
    nAdd=function(){n+=1}
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
  nAdd();
  result(); // 1000

在这段代码中,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是不允许跨域的。不过 像<script>,<link>,<img>,<iframe>这些标签是允许跨域的,但你并不能修 改这些资源,比如iframe里的内容。

为什么浏览器要实现同源限制?我们举例说明:比如一个黑客,他利用iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名和密码登录时,如果没有同源限制,他的页面就可以通过 JavaScript读取到你的表单中输入的内容,这样用户名和密码就轻松到手了.又比如你登录了OSC,同时浏览了恶意网站,如果没有同源限制,该恶意 网站就可以构造AJAX请求频繁在OSC发广告帖.

6..
Q:跨域的几种方式?
A:1)CORS(跨域源资源共享)
是W3C的一个工作草案,定义了在必须访问跨源资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想,就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
IE8通过XDomainRequest对象支持CORS,其他浏览器通过XHR对象原生支持CORS。即使浏览器对CORS的支持程度并不都一样,但所有浏览器都支持简单的请求。跨浏览器方案:
检查XHR是否支持CORS的最简单方式,就是检查是否存在withCredentials属性,再结合检测XDomainRequest对象是否存在,就可以兼顾所有浏览器了。

function createCORSRequest(method, url){
  var xhr = new XMLHttpRequest();
  If(“withCredentials” in xhr){
     xhr.open(method, url, true);
  }else if(typeof  XDomainRequest !=”undefined”){
     xhr = new XDomainRequest();
     xhr.open(method, url);
  }else {
     xhr = null;
} 
     return xhr;
}
var request = createCORSRequest(“get”,”http://www.somewhere-else.com/page/”);
If(request){
  request.onload = function(){
//对request.responseText进行处理
}
  request.send();
}

2)JSONP
JSONP由两部分组成:回调函数和数据。
JSONP为JSON的一种“使用模式”,可以用与解决主流浏览器的跨域数据访问问题。一般而言,不同服务器上网页是无法沟通的,但是html中<script>元素为一个例外。JSONP就是利用<script>元素的开放策略,网页中可以得到从其他源中动态产生的JSON资料,JSONP抓到的资料不是JSON而是js。类似的<script>、<img>、<iframe>均不受跨域影响。
JSONP是一个非正式的传输协议,实现了AJAX不可跨域的缺陷,该协议允许用户传递一个callback参数给服务器端,然后服务端返回数据时将这callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回的数据。
例子:

var flightHandler=function(data){...}
var url=".....?Code=123&callback=flightHandler";
var script=document.createElement(“script”);
script.setAttribute(“src”,url);
document.getElementsByTagName(“Head”)[0].appendChild(script); 

上面代码中url中传递了一个code参数,并通过callback参数告诉服务器,我的本地回调函数叫做fightHandler所以请将查询结果传入这个函数中调用。Ext和jQuery会自动生成回调函数,并将数据取出来工success属性方法调用,Ext和jQuery等框架将JSONP作为AJAX的一种形式进行封装。

虽然很多框架将JSONP和AJAX以同样的方式封装在一起,操作方式也很相似,然而实际上这二者之间大相径庭。主要表现在一下的不同:
① AJAX的原理是XMLHttpRequest,而JSONP的原理是script。
② JSONP的兼容性更好,在更加古老的浏览器中都可以运行,但是AJAX则需要XMLHttpRequest和ActiveX的支持。
③ JSONP仅仅支持以GET方式请求,而AJAX支持GET和POST方式。

3)使用window.name来进行跨域
window对象有个name属性,该属性有个特征:即在一个窗口(window)的生命周期内,窗口载入的所有的页面都是共享一个window.name的,每个页面对window.name都有读写的权限,window.name是持久存在一个窗口载入过的所有页面中的。

4)使用HTML5的window.postMessage方法跨域

跨文档消息传送(XDM),指来自不同域的页面间传递消息,XDM的核心是postMessage()方法,向另一个地方传递数据,指的是包含在当前页面中的<iframe>元素,或者由当前页面弹出的窗口。

7..
Q:什么是CSRF攻击?举例?如何防御CSRF?
A:CSRF 即:跨站点请求伪造

网站A :为恶意网站。
网站B :用户已登录的网站。
当用户访问 A站 时,A站 私自访问 B站 的操作链接,模拟用户操作。

假设B站有一个删除评论的链接:`http://b.com/comment/?type=delete&id=81723`
A站 直接访问该链接,就能删除用户在 B站 的评论。

CSRF 的攻击策略

因为浏览器访问 B站 相关链接时,会向其服务器发送 B站 保存在本地的Cookie,以判断用户是否登陆。所以通过 A站 访问的链接,也能顺利执行。

CSRF 防御技巧

  • 验证码

几乎所有人都知道验证码,但验证码不单单用来防止注册机的暴力破解,还可以有效防止CSRF的攻击。
验证码算是对抗CSRF攻击最简洁有效的方法。
但使用验证码的问题在于,不可能在用户的所有操作上都需要输入验证码。
只有一些关键的操作,才能要求输入验证码。
不过随着HTML5的发展。
利用canvas标签,前端也能识别验证码的字符,让CSRF生效。

  • Referer Check

Referer Check即来源检测。
HTTP Referer 是 Request Headers 的一部分,当浏览器向web服务器发出请求的时候,一般会带上Referer,告诉服务器用户从哪个站点链接过来的。
服务器通过判断请求头中的referer,也能避免CSRF的攻击。

  • Token

CSRF能攻击成功,根本原因是:操作所带的参数均被攻击者猜测到。

既然知道根本原因,我们就对症下药,利用Token。
当向服务器传参数时,带上Token。这个Token是一个随机值,并且由服务器和用户同时持有。
Token可以存放在用户浏览器的Cookie中,
当用户提交表单时带上Token值,服务器就能验证表单和Cookie中的Token是否一致。
(前提,网站没有XSS漏洞,攻击者不能通过脚本获取用户的Cookie)

总结:问的都不难,但自己的理解都不够深入,再加上语言表达能力不强,导致表现不佳。以上是查阅资料后写的完整答案。不管怎样,总归是人生的第一次面试,再接再厉了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值