百度前端面试总结

  1. 跨域问题:

5大方法:

(1)     CORS(cross origin resources sharing跨域资源共享):ajax请求采用绝对路径,在服务器端设置Access-Control-Allow-Origin来进行。

(2)     JSONP: 主要采用的是js的引入可以跨域共享,通过callback来载入其他域的资源,形式是:callback({数据名:数据值}),但是需要后台支持,并且只支持get方式,但基本没有兼容问题,老浏览器也很支持

(3)     window.domain:通过在两个页面中设置相同的window.domain,但是window.domain只能设置成自身或者更高一级的父域,所以只能解决的是不同子域的问题,也就是主域一定要相同。

(4)     window.name: 在一个窗口(window)的生命周期中,窗口载入的所有的页面都是共享一个window.name。(不是很理解跟跨域有什么关系)

(5)     window.postMessage(message,targetOrigin)(HTML5的方法:IE8+,FireFox.Chrome,Opera等):可以用这个向其他的window对象发送消息,无论这个window对象是否属于同源或不同源。

答:什么是跨域?

概念:只要协议、域名、端口有任何一个不同,都被当作是不同的域。

URL                      说明       是否允许通信

http://www.a.com/a.js

http://www.a.com/b.js     同一域名下   允许

http://www.a.com/lab/a.js

http://www.a.com/script/b.js 同一域名下不同文件夹 允许

http://www.a.com:8000/a.js

http://www.a.com/b.js     同一域名,不同端口  不允许

http://www.a.com/a.js

https://www.a.com/b.js 同一域名,不同协议 不允许

http://www.a.com/a.js

http://70.32.92.74/b.js 域名和域名对应ip 不允许

http://www.a.com/a.js

http://script.a.com/b.js 主域相同,子域不同 不允许

http://www.a.com/a.js

http://a.com/b.js 同一域名,不同二级域名(同上) 不允许(cookie这种情况下也不允许访问)

http://www.cnblogs.com/a.js

http://www.a.com/b.js 不同域名 不允许

对于端口和协议的不同,只能通过后台来解决。

跨域资源共享(CORS

CORS(Cross-Origin Resource Sharing)跨域资源共享,定义了必须在访问跨域资源时,浏览器与服务器应该如何沟通。CORS背后的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,从而决定请求或响应是应该成功还是失败。

<script type="text/javascript">

    var xhr = new XMLHttpRequest();

    xhr.open("GET", "/trigkit4",true);

    xhr.send();

</script>

以上的trigkit4是相对路径,如果我们要使用CORS,相关Ajax代码可能如下所示:

<script type="text/javascript">

    var xhr = new XMLHttpRequest();

    xhr.open("GET", "http://segmentfault.com/u/trigkit4/",true);

    xhr.send();

</script>

代码与之前的区别就在于相对路径换成了其他域的绝对路径,也就是你要跨域访问的接口地址。

服务器端对于CORS的支持,主要就是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。


要解决跨域的问题,我们可以使用以下几种方法:

通过jsonp跨域

现在问题来了?什么是jsonp?维基百科的定义是:JSONP(JSON with Padding)是资料格式 JSON 的一种“使用模式”,可以让网页从别的网域要资料。

JSONP也叫填充式JSON,是应用JSON的一种新方法,只不过是被包含在函数调用中的JSON,例如:

callback({"name","trigkit4"});

JSONP由两部分组成:回调函数和数据。回调函数是当响应到来时应该在页面中调用的函数,而数据就是传入回调函数中的JSON数据。

在js中,我们直接用XMLHttpRequest请求不同域上的数据时,是不可以的。但是,在页面上引入不同域上的js脚本文件却是可以的,jsonp正是利用这个特性来实现的。 例如:

<script type="text/javascript">

    function dosomething(jsondata){

        //处理获得的json数据

    }

</script>

<script src="http://example.com/data.php?callback=dosomething"></script>

js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。所以jsonp是需要服务器端的页面进行相应的配合的。

<?php

$callback = $_GET['callback'];//得到回调函数名

$data = array('a','b','c');//要返回的数据

echo $callback.'('.json_encode($data).')';//输出

?>

最终,输出结果为:dosomething(['a','b','c']);

如果你的页面使用jquery,那么通过它封装的方法就能很方便的来进行jsonp操作了。

<script type="text/javascript">

    $.getJSON('http://example.com/data.php?callback=?,function(jsondata)'){

        //处理获得的json数据

    });

</script>

jquery会自动生成一个全局函数来替换callback=?中的问号,之后获取到数据后又会自动销毁,实际上就是起一个临时代理函数的作用。$.getJSON方法会自动判断是否跨域,不跨域的话,就调用普通的ajax方法;跨域的话,则会以异步加载js文件的形式来调用jsonp的回调函数。

JSONP的优缺点

JSONP的优点是:它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制;它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持;并且在请求完毕后可以通过调用callback的方式回传结果。

JSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。

CORSJSONP对比

CORS与JSONP相比,无疑更为先进、方便和可靠。

    1、 JSONP只能实现GET请求,而CORS支持所有类型的HTTP请求。

    2、 使用CORS,开发者可以使用普通的XMLHttpRequest发起请求和获得数据,比起JSONP有更好的错误处理。

    3、 JSONP主要被老的浏览器支持,它们往往不支持CORS,而绝大多数现代浏览器都已经支持了CORS)。

通过修改document.domain来跨子域

浏览器都有一个同源策略,其限制之一就是第一种方法中我们说的不能通过ajax的方法去请求不同源中的文档。 它的第二个限制是浏览器中不同域的框架之间是不能进行js的交互操作的。
不同的框架之间是可以获取window对象的,但却无法获取相应的属性和方法。比如,有一个页面,它的地址是http://www.example.com/a.html , 在这个页面里面有一个iframe,它的src是http://example.com/b.html, 很显然,这个页面与它里面的iframe框架是不同域的,所以我们是无法通过在页面中书写js代码来获取iframe中的东西的:

<script type="text/javascript">

    function test(){

        var iframe = document.getElementById('ifame');

        var win = document.contentWindow;//可以获取到iframe里的window对象,但该window对象的属性和方法几乎是不可用的

        var doc = win.document;//这里获取不到iframe里的document对象

        var name = win.name;//这里同样获取不到window对象的name属性

    }

</script>

<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>

这个时候,document.domain就可以派上用场了,我们只要把http://www.example.com/a.html 和http://example.com/b.html这两个页面的document.domain都设成相同的域名就可以了。但要注意的是,document.domain的设置是有限制的,我们只能把document.domain设置成自身或更高一级的父域,且主域必须相同。

1.在页面 http://www.example.com/a.html 中设置document.domain:

<iframe id = "iframe" src="http://example.com/b.html" onload = "test()"></iframe>

<script type="text/javascript">

    document.domain = 'example.com';//设置成主域

    function test(){

        alert(document.getElementById('iframe').contentWindow);//contentWindow 可取得子窗口的 window 对象

    }

</script>

2.在页面 http://example.com/b.html 中也设置document.domain:

<script type="text/javascript">

    document.domain = 'example.com';//在iframe载入这个页面也设置document.domain,使之与主页面的document.domain相同

</script>

修改document.domain的方法只适用于不同子域的框架间的交互。

使用window.name来进行跨域

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

使用HTML5window.postMessage方法跨域

window.postMessage(message,targetOrigin) 方法是html5新引进的特性,可以使用它来向其它的window对象发送消息,无论这个window对象是属于同源或不同源,目前IE8+、FireFox、Chrome、Opera等浏览器都已经支持window.postMessage方法。

  1. 块状元素,内联元素,显示上的区别和举例有哪些元素?

答:

块状元素
一般是其他元素的容器,可容纳内联元素和其他块状元素,块状元素排斥其他元素与其位于同一行,宽度(width)高度(height)起作用。常见块状元素为div和p、h1~h6,hr,pre,table、ul、ol、li等

内联元素

内联元素不能设置宽高,竖直方向上不能设置marginpadding。但水平方向上可以设置marginpadding
内联元素只能容纳文本或者其他内联元素,它允许其他内联元素与其位于同一行,但宽度(width)高度(height)不起作用。常见内联元素为“a”、big、em、span、strong、img、textarea、label、input等

  1. 块状元素的水平、垂直居中显示如何实现?

答: 让div内的内容(包括文字及图片)垂直居中: vertical-align的值是middle,水平居中:center.

关于居中使用css为:position:fixed;left:50%;top:50%;margin-left:width/2;

margin-top:height/2; 对于ie6,只能把position:改成absolute;(在其他浏览器换成absolute也没什么问题,因为fixed与absolute定位元素是一样的)

  1. Position

答:position:absolute和float会隐式地改变display类型,不论之前什么类型的元素(display:none除外),只要设置了position:absolute、float:left或float:right中任意一个,都会让元素以display:inline-block的方式显示。

  1. cmd和amd模块化,requirejs等。。还有MVC模式

答 :

1.对于依赖的模块,AMD 是提前执行,CMD 是延迟执行。不过 RequireJS 从 2.0 开始,也改成可以延迟执行(根据写法不同,处理方式不同)。CMD 推崇 as lazy as possible.

2. CMD 推崇依赖就近,AMD 推崇依赖前置。

3. AMD 的 API 默认是一个当多个用,CMD 的 API 严格区分,推崇职责单一。比如 AMD 里,require 分全局 require 和局部 require都叫 require。CMD 里,没有全局 require,而是根据模块系统的完备性,提供 seajs.use 来实现模块系统的加载启动。CMD 里,每个 API 都简单纯粹。

  1. 变量声明提前

答:

javascript的变量声明具有hoisting机制,JavaScript引擎在执行的时候,会把所有变量的声明都提升到当前作用域的最前面。

先看一段代码

1

2

3

4

5

var v = "hello";

(function(){

  console.log(v);

  var v = "world";

})();

这段代码运行的结果是什么呢?
答案是:undefined
这段代码说明了两个问题,
第一,function作用域里的变量v遮盖了上层作用域变量v。代码做少些变动

1

2

3

4

5

var v = "hello";

if(true){

  console.log(v);

  var v = "world";

}

输出结果为"hello",说明javascript是没有块级作用域的函数是JavaScript中唯一拥有自身作用域的结构。

第二,在function作用域内,变量v的声明被提升了。所以最初的代码相当于:

1

2

3

4

5

6

var v = "hello";

(function(){

  var v; //declaration hoisting

  console.log(v);

  v = "world";

})();

声明、定义与初始化

声明宣称一个名字的存在,定义则为这个名字分配存储空间,而初始化则是为名字分配的存储空间赋初值。
用C++来表述这三个概念

1

2

3

extern int i;//这是声明,表明名字i在某处已经存在了

int i;//这是声明并定义名字i,为i分配存储空间

i = 0;//这是初始化名字i,为其赋初值为0

javascript中则是这样

1

2

var v;//声明变量v

v = "hello";//(定义并)初始化变量v

因为javascript为动态语言,其变量并没有固定的类型,其存储空间大小会随初始化与赋值而变化,所以其变量的“定义”就不像传统的静态语言一样了,其定义显得无关紧要。

声明提升

当前作用域内的声明都会提升到作用域的最前面,包括变量和函数的声明

1

2

3

4

5

6

(function(){

  var a = "1";

  var f = function(){};

  var b = "2";

  var c = "3";

})();

变量a,f,b,c的声明会被提升到函数作用域的最前面,类似如下:

1

2

3

4

5

6

7

(function(){

  var a,f,b,c;

  a = "1";

  f = function(){};

  b = "2";

  c = "3";

})();

请注意函数表达式并没有被提升,这也是函数表达式与函数声明的区别。进一步看二者的区别:

1

2

3

4

5

6

7

8

9

(function(){

  //var f1,function f2(){}; //hoisting,被隐式提升的声明

 

  f1(); //ReferenceError: f1 is not defined

  f2();

 

  var f1 = function(){};

  function f2(){}

})();

上面代码中函数声明f2被提升,所以在前面调用f2是没问题的。虽然变量f1也被提升,但f1提升后的值为undefined,其真正的初始值是在执行到函数表达式处被赋予的。所以只有声明是被提升的。

名字解析顺序

javascript中一个名字(name)以四种方式进入作用域(scope),其优先级顺序如下:
1、语言内置:所有的作用域中都有 this 和 arguments 关键字
2、形式参数:函数的参数在函数作用域中都是有效的
3、函数声明:形如function foo() {}
4、变量声明:形如var bar;

名字声明的优先级如上所示,也就是说如果一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,无论其在代码中的顺序如何。但名字的初始化却是按其在代码中书写的顺序进行的,不受以上优先级的影响。看代码:

1

2

3

4

5

6

7

8

9

(function(){

    var foo;

    console.log(typeof foo); //function

     

    function foo(){}

 

    foo = "foo";

    console.log(typeof foo); //string

})();

如果形式参数中有多个同名变量,那么最后一个同名参数会覆盖其他同名参数,即使最后一个同名参数并没有定义。

以上的名字解析优先级存在例外,比如可以覆盖语言内置的名字arguments。

命名函数表达式

可以像函数声明一样为函数表达式指定一个名字,但这并不会使函数表达式成为函数声明。命名函数表达式的名字不会进入名字空间,也不会被提升。

1

2

3

4

5

f();//TypeError: f is not a function

foo();//ReferenceError: foo is not defined

var f = function foo(){console.log(typeof foo);};

f();//function

foo();//ReferenceError: foo is not defined

命名函数表达式的名字只在该函数的作用域内部有效。

  1. 数组去重(看来是百度的常见问题,在其他人的总结中看到了答案)

答:方法一:(这个方法通过两层嵌套,实现查找,效率较低。总体思路是把数组元素逐个搬运到另一个数组,搬运的过程中检查这个元素是否有重复,如果有就直接丢掉。)

function unique(arr) {

    var result = [], isRepeated;

    for (var i = 0, len = arr.length; i < len; i++) {

        isRepeated = false;

        for (var j = 0, len = result.length; j < len; j++) {

            if (arr[i] == result[j]) {  

                isRepeated = true;

                break;

            }

        }

        if (!isRepeated) {

            result.push(arr[i]);

        }

    }

    return result;

}

方法二:(这个方法是利用hash表中(的key值存不存在的方法实现,也可以说是map、reduce的方法))

function unique(arr) {

    var result = [], hash = {};

    for (var i = 0, elem; (elem = arr[i]) != null; i++) {

        if (!hash[elem]) {

            result.push(elem);

            hash[elem] = true;

        }

    }

    return result;

//http://www.cnblogs.com/sosoft/

}

  1. Jquery的defered实现原理
  2. 继承
  3. 除去字符串中的空格

答:1.s.replace(" ","");      

2.text.replace(/s/ig,'');

  1. 闭包

答:闭包的形式是function a中return function b,b中会用到a 中的局部变量,也可能用到函数a的外部变量,根据js内存回收机制,一旦function a执行完成,a中定义的局部变量就会被回收清除,采用闭包以后就会将function b所用到的所有变量跟b绑在一起,只要function b不被清除,这些变量就不会被回收和清除。闭包容易产生内存泄露,要注意在不用b时,手动的清除b。

(实际上任何函数都是全局作用域的内部函数,都能访问全局变量,所以都是window的闭包) 

闭包的用处:闭包可以将函数中的局部变量给以保存下来,作用:

  1. 匿名函数自执行(而且这种机制不会污染对象)
  2. 缓存,再来看一个例子,设想我们有一个处理过程很耗时的函数对象,每次调用都会花费很长时间,
    那么我们就需要将计算出来的值存储起来,当调用这个函数的时候,首先在缓存中查找,如果找不到,则进行计算,
    然后更新缓存并返回值,如果找到了,直接返回查找到的值即可。闭包正是可以做到这一点,因为它不会释放外部的引用,
    从而函数内部的值可以得以保留。
  3. 实现封装
  4. 闭包的另一个重要用途是实现面向对象中的对象,传统的对象语言都提供类的模板机制,
    这样不同的对象(类的实例)拥有独立的成员及状态,互不干涉。虽然JavaScript中没有类这样的机制,但是通过使用闭包,
    我们可以模拟出这样的机制。
  1. 前端优化

答:答案同网易面试题

  1. css文件引入的方法,import和link方法的区别
(1) link属于HTML标签,而@importCSS提供的; 
  (
2) 页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载;
  (
3) import只在IE5以上才能识别,而linkHTML标签,无兼容问题;
  (
4) link方式的样式的权重 高于@import的权重.

答:有4种,分别是行内式、内嵌式、链接式和导入式。

  1. 行内式:直接在html标签中用style设定css
  2. 嵌入式:采用<style>标签,  缺点是对于一个包含很多网页的网站,在每个网页中使用嵌入式,进行修改样式时非常麻烦。单一网页可以考虑使用嵌入式

3.导入式: 将一个独立的.css文件引入HTML文件中,导入式使用CSS规则引入外部CSS文件,<style>标记也是写在<head>标记中,使用的语法如下:

          <style type="text/css">

                    @import"mystyle.css"; 此处要注意.css文件的路径

         </style>

缺陷:  导入式会在整个网页装载完后再装载CSS文件,因此这就导致了一个问题,如果网页比较大则会儿出现先显示无样式的页面,闪烁一下之后,再出现网页的样式。这是导入式固有的一个缺陷。

4.链接式: 也是将一个.css文件引入到HTML文件中,但它与导入式不同的是链接式使用HTML规则引入外部CSS文件,它在网页的<head></head>标签对中使用<link>标记来引入外部样式表文件,使用语法如下:

          <link href="mystyle.css" rel="stylesheet" type="text/css"/>

          使用链接式时与导入式不同的是它会以网页文件主体装载前装载CSS文件,因此显示出来的网页从一开始就是带样式的效果的,它不会象导入式那样先显示无样式的网页,然后再显示有样式的网页,这是链接式的优点。

总结:一般来说,做网站时把样式多写在多个样式表文件中,因此我们先用链接式引入一个总的CSS文件,然后在这个CSS文件中在使用导入式来引入其他的CSS文件。但如果通过JavaScrip来动态引入CSS文件则只能使用链接式。

  1. 事件冒泡及其应用

答:事件发生的顺序是:先是事件捕获阶段:根节点逐级送到子节点。

然后是冒泡过程是:子节点到根节点往下冒。

应用是事件代理。事件代理好处:减少事件绑定的对象的内存。

其他人补充:

  1. 淘宝为何将图片放在另一个域中,实现跨域加载?

答:对于这道题,我是这么想的:不同的域名经过dns(域名解析系统)解析以后,映射到的是不同的ip地址,不同的ip地址对应的就是不同的服务器存储地址,所以淘宝将图片放在另一个域中,主要考虑的应该是服务的存储方面。而且将图片放在其他服务器上,减少主服务的存储压力,可以减少IO口的压力,加快速度。

  1. display的几种方式,具体区别?

答: 主要说一下display为inline-block和display为inline-table的区别,

这是别人的测试成果:(原文地址:http://blog.csdn.net/yenange/article/details/7520789)

  IE6/7(IE_Test) IE8(xp/2003) IE9 Chrome 18.0.1025.162 m Firefox 12.0
inline X
inline-block X ?
inline-table X

   

 该博主得出的结论是:

所以在一般情况下, 希望并排, 最好是用 inline ,  判断一下是Chrome则用 inline-table

var display= navigator.userAgent.indexOf("Chrome") > -1 ? "inline-table" : "inline";

我觉得inline-block和inline-table最大的区别是都是行内块级元素,(具体差别下次再整理,找不到好的博文)

原文地址:https://www.cnblogs.com/shixiaomiao/p/4758434.html