前端面试题整理
前端页面由哪三层构成
结构层:由 HTML 或 XHTML之类的标记语言负责创建。标签,也就是那些出现在尖括号里的单词,对网页内容的语义含义做出了描述,但这些标签不包含任何关于如何显示有关内容的信息。例如,P标签表达了这样一种语义:“这是一个文本段。”
表示层:由CSS负责创建。CSS对 “ 如何显示有关内容 ” 的问题做出了回答。
行为层:负责回答 “ 内容应该如何对事件做出反应 ” 这一问题。这是 Javascript 语言和DOM主宰的领域。
HTML、CSS
HTML:超文本标记语言。“ 超文本 ” 就是指页面内可以包含图片、链接,甚至音乐、程序等非文字元素。
CSS:层叠样式表。是一种用来表现HTML或XML等文件样式的计算机语言。CSS不仅可以静态地修饰网页,还可以配合各种脚本语言动态地对网页各元素进行格式化。
什么是语义化的HTML?
语义化的HTML就是写出的HTML代码,符合内容的结构化(内容语义化)
,选择合适的标签(代码语义化),能够便于开发者阅读和写出更优雅
的代码的同时让浏览器的爬虫和机器很好地解析。
- 语义化有利于SEO,有利于搜索引擎爬虫更好的理解我们的网页,
从而获取更多的有效信息,提升网页的权重。- 在没有CSS的时候能够清晰的看出网页的结构,增强可读性。
- 便于团队开发和维护,语义化的HTML可以让开发者更容易的看明
白,从而提高团队的效率和协调能力。- 支持多终端设备的浏览器渲染。
常见的浏览器、内核有哪些?
浏览器:IE、Chrome、FireFox、Safari、Opera
内核:Trident、Gecko、Presto、Webkit
页面导入样式时,使用link和@import有什么区别
- link属于HTML标签,除了加载CSS外,还能用于定义RSS,定义rel连接属性等作用;而@import是CSS提供只能加载CSS;
- 页面被加载的时,link会同时被加载,而@import引用的CSS会等到页面被加载完再加载
import是CSS2.1提出的,只在IE5以上才能被识别,而link是HTML标签,无兼容问题;
清楚浮动有哪些方式?比较好的方式是哪一种
- 父级div定义height。
- 结尾处加空div标签clear:both。
- 父级div定义伪类:after和zoom。
- 父级div定义overflow:hidden。
- 父级div定义overflow:auto。
- 父级div也浮动,需要定义宽度。
- 父级div定义display:table。
- 结尾处加br标签clear:both。
比较好的是第3种,好多网站都这样用
px、em、rem的区别?
- px像素。绝对单位,像素px是相对于显示器屏幕分辨率而言的,是一个虚拟单位。是计算机系统的数字化图像长度单位,如果px要换算成物理长度,需要指定精度DPI。
- em是相对长度单位,相对于当前对象内文本的字体尺寸。如当前对行内文本的字体尺寸未被人为设置,则相对浏览器的默认字体尺寸。它会继承父级元素的字体大小,因此并不是一个固定的值。
- rem是CSS3新增的一个相对单位(root em,根em),使用rem为元素设定字体大小事,仍然是相对大小但相对的只是HTML根元素。
- 区别:IE无法调用那些使用px作为单位的字体大小,而em和rem可以缩放,rem相对的只是HTML根元素。这个单位可谓集相对大小和绝对大小的优点于一身,通过它既可以做到只修改根元素就成比例地调整所有字体大小,又可以避免字体大小逐层复合的连锁反应。目前,除了IE8及更早版本外,所有浏览器已支持rem。
选择器的优先权
内联样式表的权值最高 1000。
ID 选择器的权值为 100。
Class 类选择器的权值为 10。
HTML 标签(类型)选择器的权值为 1。
H5标签
<video>
标记定义一个视频<audio>
标记定义音频内容<source>
标记定义媒体资源<canvas>
标记定义图片<embed>
标记定义外部的可交互的内容或插件 比如flash
什么是JavaScript?
JavaScript是客户端和服务器端脚本语言,可以插入到HTML页面中,并且是目前较热门的Web开发语言。同时,JavaScript也是面向对象编程语言。
JavaScript的数据类型
基本数据类型:
字符串 String、数字 Number、布尔Boolean
复合数据类型:
数组 Array、对象 Object
特殊数据类型:
Null 空对象、Undefined 未定义
什么是未声明和未定义的变量?
未声明的变量是程序中不存在且未声明的变量。如果程序尝试读取未声明变量的值,则会遇到运行时错误。未定义的变量是在程序中声明但尚未给出任何值的变量。如果程序尝试读取未定义变量的值,则返回未定义的值。
DOM操作
- 创建新节点
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点- 添加、移除、替换、插入
appendChild()
removeChild()
replaceChild()
insertBefore() //在已有的子节点前插入一个新的子节点- 查找
getElementsByTagName() //通过标签名称
getElementsByName() //通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)
getElementById() //通过元素Id,唯一性
document.getElementByclassName //通过元素的class属性值
数组对象有哪些原生方法,列举一下
pop、push、shift、unshift、splice、reverse、sort、concat、join、slice、toString、indexOf、lastIndexOf、reduce、reduceRight
forEach、map、filter、every、some
响应事件
onclick鼠标点击某个对象;onfocus获取焦点;onblur失去焦点;onmousedown鼠标被按下
哪些操作会造成内存泄漏
全局变量、闭包、DOM清空或删除时,事件未清除、子元素存在引用
关于事件,IE与火狐的事件机制有什么区别? 如何阻止冒泡?
IE为事件冒泡,Firefox同时支持事件捕获和事件冒泡。但并非所有浏览器都支持事件捕获。jQuery中使用event.stopPropagation()方法可阻止冒泡;(旧IE的方法 ev.cancelBubble = true;)
new操作符具体干了什么呢?
- 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型;
- 属性和方法被加入到 this 引用的对象中;
- 新创建的对象由 this 所引用,并且最后隐式的返回 this
JS延迟加载的方式有哪些?
JS的延迟加载有助与提高页面的加载速度。
defer和async、动态创建DOM方式(用得最多)、按需异步载入JS
defer:延迟脚本。立即下载,但延迟执行(延迟到整个页面都解析完毕后再运行),按照脚本出现的先后顺序执行。
async:异步脚本。下载完立即执行,但不保证按照脚本出现的先后顺序执行。
谈谈this的理解
- this总是指向函数的直接调用者(而非间接调用者)
- 如果有new关键字,this指向new出来的那个对象
- 在事件中,this指向目标元素,特殊的是IE的attachEvent中的this总是指向全局对象window。
ES6 let、const
let是更完美的var
let声明的变量拥有块级作用域,let声明仍然保留了提升的特性,但不会盲目提升。
let声明的全局变量不是全局对象的属性。不可以通过window.变量名的方式访问
形如for (let x…)的循环在每次迭代时都为x创建新的绑定
let声明的变量直到控制流到达该变量被定义的代码行时才会被装载,所以在到达之前使用该变量会触发错误。
const定义常量值,不可以重新赋值,但是如果值是一个对象,可以改变对象里的属性值
const OBJ = {"a":1, "b":2};
OBJ.a = 3;
OBJ = {};// 重新赋值,报错!
console.log(OBJ.a); // 3
客户端储存的方式
客户端储存的方式有三种:cookies,sessionStorage和localStorage
cookies,sessionStorage和localStorage的区别
共同点:都是保存在浏览器端,且同源的。
Cookies:服务器和客户端都可以访问;大小只有4KB左右;有有效期,过期后将会删除;
sessionStorage和localStorage仅本地存储:只有本地浏览器端可访问数据,服务器不能访问本地存储直到故意通过POST或者GET的通道发送到服务器;可以达到5MB或更大;没有过期数据,它将保留知道用户从浏览器清除或者使用Javascript代码移除。
sessionStorage:数据在浏览器关闭后自动删除。用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。
localStorage: 本地离线存储,长期存储数据,浏览器关闭后数据不丢失。除非主动删除数据,否则数据是永远不会过期的。
什么样的布尔运算符可以在JavaScript中使用?
“And”运算符(&&),'Or'运算符(||)和'Not'运算符(!)可以在JavaScript中使用。
*运算符没有括号。
简述ajax 的过程
- 创建XMLHttpRequest对象,也就是创建一个异步调用对象
- 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
- 设置响应HTTP请求状态变化的函数
- 发送HTTP请求
- 获取异步调用返回的数据
- 使用JavaScript和DOM实现局部刷新
ajax同步和异步的区别
同步:阻塞的
-张三叫李四去吃饭,李四一直忙得不停,张三一直等着,直到李四忙完两个人一块去吃饭
=浏览器向服务器请求数据,服务器比较忙,浏览器一直等着(页面白屏),直到服务器返回数据,浏览器才能显示页面
异步:非阻塞的
-张三叫李四去吃饭,李四在忙,张三说了一声然后自己就去吃饭了,李四忙完后自己去吃
=浏览器向服务器请求数据,服务器比较忙,浏览器可以自如的干原来的事情(显示页面),服务器返回数据的时候通知浏览器一声,浏览器把返回的数据再渲染到页面,局部更新。
GET和POST的区别,何时使用POST?
GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符,有的浏览器是8000个字符
POST:一般用于修改服务器上的资源,对所发送的信息没有限制,提交的数据内容存在于http请求体中,数据不会暴漏在url地址中。
在以下情况中,请使用 POST 请求:
a. 无法使用缓存文件(更新服务器上的文件或数据库)
b. 向服务器发送大量数据(POST 没有数据量限制)
c. 发送包含未知字符的用户输入时,POST 比 GET 更稳定也更可靠
JSON
json是一种轻量级的数据交换格式,前端用于数据传输、数据请求。便于解析。
json的数据格式就是对象嵌套数组,数组嵌套对象。数组与对象相互嵌套的一种数据格式。
同源策略
跨域是由同源策略引起的
同源策略就是不同的浏览器不能读写对方的资源。同源指的是协议、域名和端口号。
如何解决跨域
JSONP跨域
websocket协议跨域
Jsonp原理(JSONP跨域只支持GET)
Ajax不能跨域,但是script标签和img标签都可以跨域。jsonp的话就是动态创建一个script标签,把jsonp数据格式(callback(json))的接口的地址赋值给我们的script标签的src属性。每一次发送jsonp请求的时候都会创建一个全局的回调函数,全局回调函数名称跟我们jsonp接口里面的函数名称是一致的。全局函数里面写的就是对请求过来数据的操作。(jsonp缺点:只能实现get一种请求。)
JavaScript原生:
var script = document.createElement('script');
script.type = 'text/javascript';
// 传参并指定回调执行函数为onBack
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
document.head.appendChild(script);
// 回调执行函数
function onBack(res) {
alert(JSON.stringify(res));
}
jQuery ajax:
$.ajax({
url: 'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "onBack", // 自定义回调函数名
data: {}
});
vue.js:
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'onBack'
}).then((res) => {
console.log(res);
})
websocket协议跨域
WebSocket是HTML5开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。
在WebSocket API中,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。
浏览器通过 JavaScript 向服务器发出建立 WebSocket 连接的请求,连接建立以后,客户端和服务器端就可以通过 TCP 连接直接交换数据。
它实现了浏览器和服务器的全双工通讯,同时允许跨域通信。
下边代码使用的是Socket.io,它很好的封装了websocket接口,提供了更简单灵活的接口,也对不支持websocket的浏览器提供了向下支持。
<div>
user input:<input type="text">
</div>
<script src="./socket.io.js"></script>
<script>
var socket = io('http://www.xxx.com:8080');
// 连接成功处理
socket.on('connect', function() {
// 监听服务端消息
socket.on('message', function(msg) {
console.log('data from server: ---> ' + msg);
});
// 监听服务端关闭
socket.on('disconnect', function() {
console.log('Server socket has closed.');
});
});
document.getElementsByTagName('input')[0].onblur = function() {
socket.send(this.value);
};
</script>
阻止默认行为
function stopDefault( e ) {
// 阻止默认浏览器动作(W3C)
if ( e && e.preventDefault ) {
e.preventDefault();
} else {
// IE中阻止函数器默认动作的方式
window.event.returnValue = false;
}
return false;
}
阻止冒泡
function stopBubble(e) {
// 如果提供了事件对象,则这是一个非IE浏览器
if ( e && e.stopPropagation ) {
// 因此它支持W3C的stopPropagation()方法
e.stopPropagation();
} else {
// 否则,我们需要使用IE的方式来取消事件冒泡
window.event.cancelBubble = true;
}
}
apply、call和bind
在严格模式下,未指定环境对象而调用函数,则this 值不会转型为window。除非明确把函数添加到某个对象或者调用apply()或call(),否则this 值将是undefined。
在非严格模式下,call、apply的第一个参数传递为null或undefined时,函数体内的this会指向默认的宿主对象,在浏览器中则是window。
- apply、call和bind比较
var obj = {
x: 81
};
var foo = {
getX: function () {
return this.x;
}
}
console.log(foo.getX.bind(obj)());
console.log(foo.getX.apply(obj));
console.log(foo.getX.call(obj));
- 很明显,bind方法后面多了一对括号。也就是说,当你希望改变上下文环境之后并且立即执行,而是回调执行的时候(多用于事件监听器函数),使用bind()方法,而apply/call则会立即执行函数。
定义一个 log 方法,让它可以代理 console.log 方法。
function log(){
console.log.apply(console, arguments);
};
log(1); //1
log(1,2); //1 2
- 给每一个 log 消息添加一个”(app)”的前辍,比如:
log("hello world"); //(app)hello world
function log(){
var args = Array.prototype.slice.call(arguments);
args.unshift('(app)');
console.log.apply(console, args);
};
- apply实现bind
function bind (fn, context) {
return function () {
return fn.apply(context, argument);
}
}
数组API
数组去重
上一篇: C++把输出结果写入到文件中