前端常用代码片段(一) 点这里前端常用代码片段(二) 点这里前端常用代码片段(三) 点这里前端常用代码片段(四) 点这里前端常用代码片段(五) 点这里前端常用代码片段(六) 点这里
1. 简述一下你对 HTML 语义化的理解?并写出一段语义化的 HTML?
语义化是指根据内容的结构化(内容语义化),选择合适的标签(代码语义化),便于开发者阅读和写出更优雅的代码的同时,让浏览器的爬虫和机器很好的解析。
用正确的标签做正确的事情
html 语义化让页面的内容结构化,结构更清晰,便于对浏览器、搜索引擎解析
语义化的 HTML 在没有 CSS 的情况下也能呈现较好的内容结构与代码结构
搜索引擎的爬虫也依赖于 HTML 标记来确定上下文和各个关键字的权重,利于 SEO;
使阅读源代码的人对网站更容易将网站分块,便于阅读维护理解
HTML5 增加了许多语义化标签如:header footer nav article ……
语义化 HTML 示例:
<!– 这是开放的 –>
<header>
<h1>header</h1>
</header>
<section class=”main”>
main
</section>
<aside>aside</aside>
<footer>
footer
</footer>
2. HTML5 有哪些新特性、移除了那些元素?如何处理 HTML5 新标签的浏览器兼容问题?如何区分 HTML 和 HTML5?
HTML5 是定义 HTML 标准的最新的版本。该术语表示两个不同的概念:
它是一个新版本的 HTML 语言,具有新的元素,属性和行为,
它有更大的技术集,允许更多样化和强大的网站和应用程序。这个集合有时称为 HTML5 和朋友,通常缩写为 HTML5。
HTML5 新特性:
HTML5 现在已经不是 SGML 的子集,主要是关于图像,位置,存储,多任务等功能的增加
绘画 canvas;
用于媒介回放的 video 和 audio 元素;
本地离线存储 localStorage 长期存储数据,浏览器关闭后数据不丢失
sessionStorage 的数据在浏览器关闭后自动删除
语意化更好的内容元素,比如 article、footer、header、nav、section
表单控件(input type),calendar、date、time、email、url、search
新的技术 webworker, websocket, Geolocation
移除元素:
纯表现的元素 basefont,big,center,font, s,strike,tt,u
对可用性产生负面影响的元素:frame,frameset,noframes
处理 HTML5 新标签的浏览器兼容问题:
IE8/IE7/IE6 支持通过 document.createElement 方法产生的标签,可以利用这一特性让这些浏览器支持 HTML5 新标签,浏览器支持新标签后,还需要添加标签默认的样式。
可直接使用成熟的框架、比如 html5shiv
<!–[if lt IE 9]>
<script src=”html5shiv.js”></script>
<![endif]–>
如何区分 HTML 和 HTML5:
DOCTYPE 声明
新增元素
3. 为什么要初始化 CSS 样式(reset css)?
因为浏览器的兼容问题,不同浏览器对有些标签的默认值是不同的,如果没对 CSS 初始化往往会出现浏览器之间的页面显示差异
最简单粗暴的
* {
margin: 0;
padding: 0;
}
更好的选择 Normalize.css 相比于传统的 CSS reset,Normalize.css 是一种现代的、为 HTML5 准备的优质替代方案
Reset CSS: 只选对的,不选 ” 贵 ” 的,因根据具体项目来做选择权衡,不应该滥用
css 定义的权重?
页面显示样式的优先级取决于其“特殊性”’,特殊性越高,就显示最高的,当特殊性相等时,显示后者特殊性表述为 4 个部分:0,0,0,0
一个选择器的特殊性如下确定:
对于选择器是 #id 的属性值, 特殊性值为:0,1,0,0
对于属性选择器,class 或伪类,特殊性值为:0,0,1,0
对于标签选择器或伪元素,特殊性值为:0,0,0,1
通配符‘*’对特殊性值为:0,0,0,0
内联样式特殊性值为:1,0,0,0
4. 讲讲 position 的值 relative 和 absolute 的区别?
absolute:生成绝对定位的元素,相对于值不为 static 的第一个父元素进行定位
relative:生成相对定位的元素,相对于其正常位置进行定位
5. 如何水平垂直居中 div?(至少给出 2 种解决方法)
1.absolute + transform:
<div class=”parent”>
<div class=”child”>Demo</div>
</div>
<style>
.parent {
position: relative;
}
.child {
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
}
</style>
2.inline-block + text-align + table-cell + vertical-align
<div class=”parent”>
<div class=”child”>Demo</div>
</div>
<style>
.parent {
text-align: center;
display: table-cell;
vertical-align: middle;
}
.child {
display: inline-block;
}
</style>
3.flex + justify-content + align-items
<div class=”parent”>
<div class=”child”>Demo</div>
</div>
<style>
.parent {
display: flex;
justify-content: center; /* 水平居中 */
align-items: center; /* 垂直居中 */
}
</style>
6. 渐进增强 VS 优雅降级,你怎么看?
渐进增强(Progressive Enhancement):一开始就针对低版本浏览器进行构建页面,完成基本的功能,然后再针对高级浏览器进行效果、交互、追加功能达到更好的体验优雅降级(Graceful Degradation):一开始就构建站点的完整功能,然后针对浏览器测试和修复。比如一开始使用 CSS3 的特性构建了一个应用,然后逐步针对各大浏览器进行 hack 使其可以在低版本浏览器上正常浏览
7. JavaScript 数组去重?(简述思路即可)
遍历数组法:这应该是最简单的去重方法(实现思路:新建一新数组,遍历数组,值不在新数组就加入该新数组中)
// 遍历数组去重法
function unique(arr){
var _arr = []
// 遍历当前数组
for(var i = 0; i < arr.length; i++){
// 如果当前数组的第 i 已经保存进了临时数组,那么跳过,
// 否则把当前项 push 到临时数组里面
if (_arr.indexOf(arr[i]) == -1) _arr.push(arr[i])
}
return _arr
}
注意点:indexOf 为 ES5 的方法,注意浏览器兼容,需要自己实现 indexOf
对象键值对(hash) 法:速度快,高效,占用更大的内存换取更快的时间,用 JavaScript 中的 Object 对象来当做哈希表,hash 去重的核心是构建了一个 hash 对象来替代 indexOf
// hash 去重法
function unique(arr){
var _arr = [],
hash = {}
for (var i = 0; i < arr.length; i++) {
var item = arr[i]
var key = typeof(item) + item
// 对象的键值只能是字符串, typeof(item) + item 来去分 1 和 ’1’ 的情况
if(hash[key] !== 1){
_arr.push(item)
hash[key] = 1
}
}
return _arr
}
炫酷的 es6 Set 数据结构: ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值
function unique(arr){
return Array.from(new Set(arr))
// Array.from 方法用于将两类对象转为真正的数组:
// 类似数组的对象(array-like object)和可遍历(iterable)的对象
}
8. 使用原生 ajax 获取 Linus Torvalds 的 GitHub 信息(API:api.github.com/users/torva…),并将 JSON 字符串解析为 JSON 对象,并讲讲对 JSON 的了解
这是对 ajax 与 json 的考察 ajax 的全称:Asynchronous Javascript And XML,异步传输 +js+xml 现在差不多都用 JSON
创建 XMLHttpRequest 对象, 也就是创建一个异步调用对象创建一个新的 HTTP 请求, 并指定该 HTTP 请求的方法、URL 及验证信息设置响应 HTTP 请求状态变化的函数发送 HTTP 请求获取异步调用返回的数据数据处理
下面就来贴代码吧:
var api = ‘https://api.github.com/users/torvalds’
var xhr = new XMLHttpRequest() // 创建 XMLHttpRequest 对象
if(window.XMLHttpRequest){// 兼容处理
xhr = new XMLHttpRequest()
}else{
xhr = new ActiveXObject(‘Microsoft.XMLHTTP’)// 兼容 ie6 以下下
}
xhr.open(‘get’,api,true) // 设置请求信息
xhr.send() // 提交请求
// 等待服务器返回内容
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
console.log(JSON.parse(xhr.responseText)) // 使用 JSON.parse 解析 JSON 字符串
}
}
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式。它是基于 JavaScript 的一个子集。数据格式简单, 易于读写, 占用带宽小 如:{“age”:”12″, “name”:”back”}
JSON.parse() 方法解析一个 JSON 字符串
JSON.stringify() 方法将一个 JavaScript 值转换为一个 JSON 字符串
9. 简单谈谈前端性能优化
减少 http 请求次数:CSS Sprites, JS、CSS 源码压缩、图片大小控制合适;网页 Gzip,CDN 托管,data 缓存,图片服务器。
减少 DOM 操作次数,优化 javascript 性能。
少用全局变量、缓存 DOM 节点查找的结果。减少 IO 读取操作。
尽量避免使用 CSS Expression(css 表达式)又称 Dynamic properties(动态属性)。
图片预加载,将样式表放在顶部,将脚本放在底部。
10. 费波纳茨数组
就是当前项等于前两项的和
var arr=[];
for(var i=0;i<10;i++){
i<=1?arr.push(1):arr.push(arr[i-1]+arr[i-2]);
}
console.log(arr)
11. 数据排列
执行 num(1,5),返回 ’123454321’ 执行 num(2,5),返回 ’23456765432′
方法 1:
var num = function(n,m){
var arr = []
var len=(m-n)*2+1
for(var i=0;i<len;i++){
n<m?(arr.push(n++)):(arr.push(m–))
}
return arr.join()
}
num(2,5)
方法 2:
var num = function (n,m) {
let arr = [m]
for(let i = m – 1; i >= n; i–){
arr.push(i);
arr.unshift(i)
}
return arr.join()
}
num(2,5)
12. 翻转一个字符串
let a=”hello word”;
let b=[…str].reverse().join(“”);//drow olleh
13.setInterval 时间是否会有误差?产生误差的原因?其原理是什么?
setInterval 异步函数,异步执行,js 被解析的时候,碰到他,先不解析他,放他在一旁,先去解析同步的,等资源空闲下来的才去解析他,这样一来,解析其他代码肯定需要时间,这不就有延误嘛。然后解析 setInterval 内部函数不也一样需要耗时,函数简单些还好写,你要是写了一大堆,可能产生的延误就不是一点点的;
14. 布局方式
弹性布局
固定布局
流体布局
混合布局
绝对定位布局
15. 清除浮动的方式:
父级 div 定义 height
最后一个浮动元素后加空 div 标签 并添加样式 clear:both。
包含浮动元素的父标签添加样式 overflow 为 hidden 或 auto。
父级 div 定义 zoom
16. 怎么判断两个对象相等?
obj={
a:1,
b:2
}
obj2={
a:1,
b:2
}
obj3={
a:1,
b:2
}
JSON.stringify(obj)==JSON.stringify(obj2);//true
JSON.stringify(obj)==JSON.stringify(obj3);//false
17.ES6 强制参数
ES6 提供了默认参数的概念,当函数的参数未传入或者传入值为 undefined 时,会应用参数的默认值。
默认值可以是个表达式,所以我们可以将默认值设置为一个执行函数,如果该参数没有传值,就会执行我们的默认函数:
const required = () => {throw new Error(‘Missing parameter’)};
//The below function will throw an error if either “a” or “b” is missing.
const add = (a = required(), b = required()) => a + b;
add(1, 2) //3
add(1) // Error: Missing parameter.
18. 强大的 reduce
之前只是用过 reduce 做过数组求和,现在发现一些新的用法,原来 reduce 这么强大。
基础部分
reduce()方法接收一个函数 callbackfn 作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值。
语法
array.reduce(callbackfn,[initialValue])
reduce()方法接收 callbackfn 函数,而这个函数包含四个参数:
function callbackfn(preValue,curValue,index,array){}
preValue: 上一次调用回调返回的值,或者是提供的初始值(initialValue)
curValue: 数组中当前被处理的数组项
index: 当前数组项在数组中的索引值
array: 调用 reduce()方法的数组
而 initialValue 作为第一次调用 callbackfn 函数的第一个参数。
1. 没有 initialValue 初始值得情况
var arr = [0,1,2,3,4];
arr.reduce(function(preValue,curValue,index,array){
return preValue + curValue;
}); // 10
示例中的回调函数被执行四次,每次参数和返回的值如下:
2. 有 initialValue 初始值得情况
var arr = [0,1,2,3,4];
arr.reduce(function (preValue,curValue,index,array) {
return preValue + curValue;
}, 5); //15
reduce()方法会执行五次回调,每次参数和返回的值如下:
基础部分截取自 大漠 – JavaScript 学习笔记 … 全部内容可点击链接查看
实例部分
1. 使用 reduce 替代 map + filter
设想你有这么个需求:要把数组中的值进行计算后再滤掉一些值,然后输出新数组。很显然我们一般使用 map 和 filter 方法组合来达到这个目的,但这也意味着你需要迭代这个数组两次。
来看看我们如何使用 reduce 只迭代数组一次,来完成同样的结果。下面这个例子我们需要把数组中的值乘 2,并返回大于 50 的值:
const numbers = [10, 20, 30, 40];
const doubledOver50 = numbers.reduce((finalList, num) => {
num = num * 2; //double each number (i.e. map)
//filter number > 50
if (num > 50) {
finalList.push(num);
}
return finalList;
}, []);
doubledOver50; // [60, 80]
2. 使用 reduce 检测括号是否对齐封闭
下面这个例子我们用 reduce 来检测一段 string 中的括号是否前后对应封闭。
思路是定义一个名为 counter 的变量,它的初始值为 0,然后迭代字符串,迭代过程中碰到 (就加 1,碰到) 就减 1,如果括号前后对应的话,最终 couter 的值会是 0。
//Returns 0 if balanced.
const isParensBalanced = (str) => {
return str.split(”).reduce((counter, char) => {
if(counter < 0) {//matched “)” before “(”
return counter;
} else if(char === ‘(‘) {
return ++counter;
} else if(char === ‘)’) {
return –counter;
} else {//matched some other char
return counter;
}
}, 0); //<– starting value of the counter
}
isParensBalanced(‘(())’) // 0 <– balanced
isParensBalanced(‘(asdfds)’) //0 <– balanced
isParensBalanced(‘(()’) // 1 <– not balanced
isParensBalanced(‘)(‘) // -1 <– not balanced
3. 使用 reduce 计算数组中的重复项
如果你想计算数组中的每个值有多少重复值,reduce 也可以快速帮到你。下面的例子我们计算数组中每个值的重复数量,并输出一个对象来展示:
var carsObj = cars.reduce(function (obj, name) {
obj[name] = obj[name] ? ++obj[name] : 1;
return obj;
}, {});
carsObj; // => {BMW: 2, Benz: 2, Tesla: 1, Toyota: 1}
实例部分截取自 ES6 的几个小技巧 全部内容可点击链接查看
19. 用对象解构移除一个对象中的某些属性
有时你可能希望移除一个对象中的某些属性,我们一般会通过迭代这个对象(如 for..in 循环)来移除那些我们不想要的属性。实际上我们可以通过对象解构的方法将不想要的属性提取出来,并将想留下来的变量保存在 rest 参数中。
在下面的这个例子中,我们从对象中移除_internal 和 tooBig 这两个属性:
let {_internal, tooBig, …cleanObject} = {
el1: ‘1’,
el2: ‘2’,
el3: ‘3’,
tooBig:{},
_internal:”secret”
};
console.log(cleanObject); // {el1: ‘1’, el2: ‘2’, el3: ‘3’}
拓展:
1. 嵌套对象解构
let {model, engine: {vin,…uuu} } = {
model: ‘bmw 2018’,
engine: {
v6: true,
turbo: true,
vin: 12345
}
}
console.log(uuu); // {v6: true, turbo: true}
console.log(vin); // 12345
console.log(model); // ‘bmw 2018’
console.log(engine); // Uncaught ReferenceError: engine is not defined
2. 合并对象
合并两个对象,新对象中相同的属性会被放在后面的对象覆盖:
let object1 = {a:1, b:2,c:3}
let object2 = {b:30, c:40, d:50}
let merged = {…object1, …object2} //spread and re-add into merged
console.log(merged) // {a:1, b:30, c:40, d:50}
20. 判断一个数是否是整数
function isInteger(x) {return (x ^ 0) === x; }
function isIntefer(x){
return (typeof x === ‘number’) && (x % 1 === 0); // 返回布尔
}
参考文章:1.12 个常规前端面试题及小结 2.ES6 的几个小技巧