Zihao

Make small but daily progress

0%

前端面试题终结版

1.渐进增强 (progressive enhancement) 和优雅降级 (graceful degradation)

持优雅降级观点者认为,应该针对最高级、最完善的浏览器来设计网站。然后,再为那些被认为过时或有功能缺失的浏览器提供候选方案,使之基本可用,但不至于完全失效。这样一来,新特性在老浏览器中会降级,且一般会有一个分界点,声明不支持哪些老浏览器。有时候会警告使用老浏览器的用户,建议更换,如“您的浏览器已经老掉牙了,建议使用现代浏览器!”。

与优雅降级正好相反,持渐进增强观点者则认为,应该关注于内容本身。首先,保证最核心的功能,让任何低端的浏览器都能看到网站的内容。然后,再通过CSS或Javascript来进行效果、交互等改进,为更先进的浏览器提供渐进式增强,带来更好的用户体验。

2.JavaScript 数据类型

栈:原始数据类型(字符换,数字,布尔,Null,Undefined)
堆:引用数据类型(数组)

原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其
在栈中的地址,取得地址后从堆中获得实体

3.盒子模型

content-》padding-》border-》margin

4.box-sizing

1
2
box-sizing: content-box;
box-sizing: border-box;

box-sizing属性可以指定盒子模型种类,
content-box指定盒子模型为W3C标准盒模型,元素的高宽设定=content
border-box为IE6混杂模式盒模型。元素的高宽设定=border+padding+content
inherit 继承父元素的box-sizing属性

5.promise

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// Promise里面传入一个函数类型的参数,这个函数类型的参数接收两个参数resolve reject
var p = new Promise(function(resolve,reject){
// 异步操作
setTimeout(function(){
console.log('icessun'); // 两秒之后打印出icessun
resolve('icessun2'); // resolve是成功后的回调函数 里面的icessun2是传入的参数
},2000)
});
// 那么p是一个实例对象,可以使用then方法(Promise原型上面的方法)
p.then(function(){
console.log(arguments); // 会打印出一个类数组 ['icessun2']
})
p.then(function(data){
console.log(data); // 会打印出icessun2 data接收了resolve里面的参数
})

方便链式回调,resolve 是成功回调,reject为失败回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function getNumber(){
var p=new Promise(function(resolve,reject){
setTimeout(function(){
var num=Math.ceil(Math.random()*10); // 生成1-10 之间的随机数 Math.ceil(): 大于或等于给定数字的最小整数
if(num<=5){
resolve(num);
}else{
reject('数字太大了')
}
},2000);
});
return p;
}

getNumber().then(function(data){
console.log('resolved');
console.log(data);
},function(reason,data){
console.log('resolved');
console.log(reason); // 数字太大
console.log(data); // undefined
});

1
2
3
4
5
Promise
.all([runAsync1(),runAsync2(),runAsync3()])
.then(function(results){
console.log(results);
});

Promise.all来执行前面的三个异步的函数,all()接收一个数组参数,里面的执行最终都返回Promise对象,只有等三个异步操作都执行完成后才会进入到then里面,all会把所有的异步操作的结果放在一个数组中传给then,就是上面的results.

1
2
3
4
5
6
Promise
.race([runAsync1(),runAsync2(),runAsync3()])
.then(function(results){
console.log(results);
});

race也是Promise类上面的私有方法,对于前面的all方法来说是:谁的程序执行的慢,就等谁执行完才回调。但是对于race来说:谁的程序执行的快,就以它为标准调用回调函数,其用法基本上是一样的,把上面runAsync1函数的延迟改为1秒

6.原型与继承的过程

Js所有的函数都有一个prototype属性,这个属性引用了一个对象,即原型对象,也简称原型。

7.闭包

1
2
3
4
( function(){
var i = 1;
console.log(i)
} )
  • 1.函数嵌套函数
  • 2.函数内部可以引用外部的参数和变量
  • 3.参数和变量不会被垃圾回收机制回收

8.柯里化

在计算机科学中,柯里化(Currying),又译为卡瑞化或加里化,是把接收多个参数的函数变换成接收一个单一参数(最初函数的第一个参数)的函数,并返回接受剩余的参数而且返回结果的新函数的技术。这个技术由克里斯托弗·斯特雷奇以逻辑学家哈斯凯尔·加里命名的。

1
2
3
4
5
6
7
8
9
10
//函数定义
function add(x,y){

return x + y;

}

//函数调用

add(3,5);//8

采用柯里化将接受两个参数的函数变成接受单一参数的函数

1
2
3
4
5
6
7
8
9
10
11
12
//函数表达式
var add = function(x){

return function(y){

return x + y;

}
};

//函数调用
add(3)(5);

9.箭头函数的使用

es6 箭头函数的使用,颠覆了js的编程习惯。

1
2
3
4
5
6
7
8
9
10
11
12
13
// es5
var foo = function() {
var a = 20
var b = 30;
return a + b;
}

// es6
const foo = () => {
const a = 20;
const b = 30;
return a + b;
}

10.var let const

var 是全局
let 块级操作,值可变
const 值不会变

11.模板字符

模板字符是为了解决使用+号拼接字符串的不便利出现的

1
2
3
4
5
6
7
8
9
// es6
const a = 20;
const b = 30;
const string = `${a}+${b}=${a+b}`;

// es5
var a = 20;
var b = 30;
var string = a + "+" + b + "=" + (a + b);

12.展开运算符

在ES6中用…来表示展开运算符,它可以将数组方法或者对象进行展开。先来看一个例子它是如何使用的。

1
2
const arr1 = [1, 2, 3];
const arr2 = [...arr1, 10, 20, 30];

13.执行顺序

先执行脚本,然后 setTimeout 会延迟执行,那么执行到 console.log 的时候,i已经变成5了。

14.async 和 awit

async用来申明里面包裹的内容可以进行同步的方式执行,await则是进行执行顺序控制,每次执行一个await,程序都会暂停等待await返回值,然后再执行之后的await。
await后面调用的函数需要返回一个promise,另外这个函数是一个普通的函数即可,而不是generator。
await只能用在async函数之中,用在普通函数中会报错。
await命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try...catch 代码块中。

15.函数声明

函数声明:function fnName () {…};使用function关键字声明一个函数,再指定一个函数名,叫函数声明。

函数表达式:var fnName = function () {…};使用function关键字声明一个函数,但未给函数命名,最后将匿名函数赋予一个变量,叫函数表达式,这是最常见的函数表达式语法形式。

匿名函数:function () {}; 使用function关键字声明一个函数,但未给函数命名,所以叫匿名函数,匿名函数属于函数表达式,匿名函数有很多作用,赋予一个变量则创建函数,赋予一个事件则成为事件处理程序或创建闭包等等。

( function(){…} )()( function (){…} () )是两种javascript立即执行函数的常见写法

16.事件代理

当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数

17.AMD CMD CommonJS

CommonJS 适用于服务端,比如node 执行环境。同步加载不同模块之所以采用同步,是因为模块文件都存放在服务器的各个硬盘上,实际的加载时间就是硬盘的文件读取时间。

AMD ,Asynchronous Module Definition 异步模块定义。require js一次性加载全部的js文件到客户端。

CMD,common module definition ,是seajs的规范,依赖就近,用的时候再require。

18.doctype(文档类型) 的作用是什么

用来说明web设计中所用的html或xhtml的类型,指出浏览器或者其他阅读程序按照什么样的规则(W3C所发布的一个文档类型定义即DTD)集去解释文档中的标记.
在W3C标准出来之前,浏览器对页面的渲染没有同一的标准,产生了差异,quirks mod(混杂模式或者兼容模式),但在W3C标准出台之后,浏览器对页面的渲染有了同一的标准即(严格模式或标准模式)。但是为了保证以前就得页面仍然正常显示,有的浏览器就保存了这两种渲染模式(标准兼容模式)。那么究竟采用哪一种方式进行渲染,就要看DOCTYPE生命中的DTD。

DOCTYPE使浏览器按照DTD指定的渲染方式对页面进行渲染。
Web 世界中存在许多不同的文档。只有了解文档的类型,浏览器才能正确地显示文档。
HTML 也有多个不同的版本,只有完全明白页面中使用的确切 HTML 版本,浏览器才能完全正确地显示出 HTML 页面。这就是 <!DOCTYPE> 的用处。
<!DOCTYPE> 不是 HTML 标签。它为浏览器提供一项信息(声明),即 HTML 是用什么版本编写的。
如果你的页面添加了<!DOCTYPE html>那么,那么就等同于开启了标准模式,那么浏览器就得老老实实的按照W3C的标准。

19.浏览器标准模式 (standards mode) 、几乎标准模式(almost standards mode)和怪异模式 (quirks mode) 之间的区别是什么?

所谓的标准模式是指,浏览器按W3C标准解析执行代码;怪异模式则是使用浏览器自己的方式解析执行代码,因为不同浏览器解析执行的方式不一样,所以我们称之为怪异模式。浏览器解析时到底使用标准模式还是怪异模式,与你网页中的DTD声明直接相关,DTD声明定义了标准文档的类型(标准模式解析)文档类型,会使浏览器使用相应的方式加载网页并显示,忽略DTD声明,将使网页进入怪异模式(quirks mode)。
几乎标准模式(almost standards mode)是Firefox1+的设定的,类似于标准模式。

20.HTML 和 XHTML 有什么区别?

HTML是一种基本的WEB网页设计语言,XHTML是一个基于XML的置标语言,看起来与HTML有些相象,只有一些小的但重要的区别,XHTML就是一个扮演着类似HTML的角色的XML,所以,本质上说,XHTML是一个过渡技术,结合了XML(有几分)的强大功能及HTML(大多数)的简单特性。
HTML 和 XHTML 的区别简单来说,XHTML 可以认为是 XML 版本的 HTML,为符合 XML 要求,XHTML 语法上要求更严谨些。
以下是 XHTML 相对 HTML 的几大区别:
XHTML 要求正确嵌套
XHTML 所有元素必须关闭
XHTML 区分大小写
XHTML 属性值要用双引号
XHTML 用 id 属性代替 name 属性
XHTML 特殊字符的处理

21.如果页面使用 ‘application/xhtml+xml’ 会有什么问题吗

比较严格,必须有head、body标签且每个元素必须是关闭的。 一些老的浏览器不支持,实际上,任何最新的浏览器都将支持application/xhtml+xml媒体类型。

22.BFC规范的理解

BFC,块级格式化上下文,一个创建了新的BFC的盒子是独立布局的,盒子里面的子元素的样式不会影响到外面的元素。在同一个BFC中的两个毗邻的块级盒在垂直方向(和布局方向有关系)的margin会发生折叠。

23.你有哪些性能优化的方法?

  • 减少http请求次数:CSS Sprites,JS, CSS源码压缩,图片大小控制合适,网页Gzip,CDN托管,data缓存,图片服务器。
  • 前端模板js+数据,减少由于HTML标签导致的带宽浪费,前端用变量保存AJAX请求结果,每次操作本地变量不用请求,减少请求次数。
  • 空的src。

24.XSS原理及防范

Xss(cross-site scripting)攻击指的是攻击者往Web页面里插入恶意html标签或者javascript代码。比如:攻击者在论坛中放一个看似安全的链接,骗取用户点击后,窃取cookie中的用户私密信息;或者攻击者在论坛中加一个恶意表单, 当用户提交表单的时候,却把信息传送到攻击者的服务器中,而不是用户原本以为的信任站点。

25.XSS防范方法

  • 1.代码里对用户输入的地方和变量都需要仔细检查长度和对”<”,”>”,”;”,”’”等字符做过滤;其次任何内容写到页面之前都必须加以encode,避免不小心把html tag 弄出来。这一个层面做好,至少可以堵住超过一半的XSS 攻击。
  • 2.避免直接在cookie 中泄露用户隐私,例如email、密码等等。
  • 3.通过使cookie 和系统ip 绑定来降低cookie 泄露后的危险。这样攻击者得到的cookie 没有实际价值,不可能拿来重放。
  • 4.尽量采用POST 而非GET 提交表单。

26.XSS与CSRF有什么区别吗?

XSS是获取信息,不需要提前知道其他用户页面的代码和数据包。CSRF是代替用户完成指定的动作,需要知道其他用户页面的代码和数据包。

要完成一次CSRF攻击,受害者必须依次完成两个步骤:

  • 1.登录受信任网站A,并在本地生成Cookie。
  • 2.在不登出A的情况下,访问危险网站B。

  
CSRF的防御

  • 1.服务端的CSRF方式方法很多样,但总的思想都是一致的,就是在客户端页面增加伪随机数。
  • 2.使用验证码。

27.JavaScript 的同源策略。

协议,域名,端口相同,同源策略是一种安全协议。 指一段脚本只能读取来自同一来源的窗口和文档的属性。

为什么要有同源限制?
我们举例说明:比如一个黑客程序,他利用Iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript读取到你的表单中input中的内容,这样用户名,密码就轻松到手了。

28.解释CSS Sprites, 以及你要如何使用?

CSS Sprites其实就是把网页中一些背景图片整合到一张图片文件中,再利用CSS的“background-image”,“background- repeat”,“background-position”的组合进行背景定位,background-position可以用数字能精确的定位出背景图片的位置。

29.data-*属性的作用

为前端开发者提供自定义的属性,这些属性集可以通过对象的dataset属性获取,不支持该属性的浏览器可以通过 getAttribute方法获取

1
2
<div data-author="david" data-time="2011-06-20" data-comment-num="10">...</div>
div.dataset.commentNum; // 可通过js获取 10

data-之后的以连字符分割的多个单词组成的属性,获取的时候使用驼峰风格。

30.二分查找

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 递归算法
function binary_search(arr,low, high, key) {
if (low > high){
return -1;
}
var mid = parseInt((high + low) / 2);
if(arr[mid] == key){
return mid;
}else if (arr[mid] > key){
high = mid - 1;
return binary_search(arr, low, high, key);
}else if (arr[mid] < key){
low = mid + 1;
return binary_search(arr, low, high, key);
}
};
var arr = [1,2,3,4,5,6,7,8,9,10,11,23,44,86];
var result = binary_search(arr, 0, 13, 10);
alert(result); // 9 返回目标元素的索引值

欢迎关注我的其它发布渠道