前端面试题(一)
本文最后更新于:2025年1月29日 凌晨
H5新特性
- 拖拽释放(Drap and drop) API ondrop
- 自定义属性 data-id
- 语义化标签,header、nav、footer、aside、article、section
- 音频自动播放属性 autoplay
- 画布 Canvas
- 离线存储 localStorage、会话存储 sessionStorage
- 表单控件,calendar、date、time、email、url、search
- 新技术,web worker、web socket、geolocation
C3新特性
- 颜色新增,RGBA、HSLA模式
- 文字阴影,text-shadow
- 盒模型,box-sizing
- 渐变,linear-gradient、radial-gradient
- 过度,transition
<animation-name>
- 自定义动画 animate @keyframe
- 媒体查询,@media screen and (max-width: 800px) { … }
- 弹性布局,flex
H5浏览器存储有哪些
- cookie,在控制台输入
document.cookie
可以看到当前页面的cookie值,是一个字符串,以分号分隔,'_octo=GH1.1.647075200.1634350299; tz=Etc%2FGMT-8'
。cookie 始终在同源的 http 请求中携带。 - localStorage,本地化持久存储,只要用户不删除,就一直存在。在控制台输入
sessionStorage
得到Storage {length: 0}
- sessionStorage,面向session 的浏览器存储,因此只存在于一个页面的生命周期内。在控制台输入
localStorage
得到Storage {ref-selector:helloqingfeng/Awsome-Front-End-learning-resource:branch: '{"refs":["master","gh-pages"],"cacheKey":"v0:1472661172.0"}', ref-selector:baozouai/shop-admin:branch: '{...}'
- indexedDB,
IDBFactory {}
- window对象上的全局变量
盒子水平垂直居中
- margin: 0 auto;
- display: table-cell;
- display: flex; jusitify-content: center; align-items: center;
- .parent { position: relative } .child { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%)}
CSS盒模型
- box model 指的是css 中所有元素都可以看作是一个个的盒子,包括内容、内边距、边框、外边距。
- 盒模型分两种
- w3c 标准盒模型,称为标准盒模型。height 属性指的是 content 内容区域的大小
- ie 标准盒模型,怪异盒模型。height 属性指的是 content+border+padding 的大小
块级元素和行内元素的区别
- 块级元素占一行,填满父元素。可以设置 width、height、margin、padding 属性
- 行内元素随着内容宽度变化而变化。自动换行。宽高无效,水平方向的margin、padding有效
选择器权重
!important > 行内样式 > ID 选择器 > 类选择器、伪类、属性 > 标签、伪元素 > 通配符 > 继承 > 浏览器默认属性
- 权重计算方式为选择符中ID
选择器的数量 x 100 + 类、伪类、伪元素的数量 x 10 + 标签、伪元素的数量
。div#app.child[name=”appName”] 的权重值为 a=1,b=2,c=1 ➡ 1+100+10x2 = 121
语义化标签
- 利用html 的原生样式减少css 样式的书写。
- 有利于SEO ,便于浏览器理解页面结构
- 样式丢失的时候也能呈现较为清晰的页面结构
- 常见的语义化标签
<header>
、<section>
、<article>
、<aside>
、<footer>
H5 事件举例
- 通过
on+<事件名字>
的形式,作为元素的属性进行指定 - onblur 失去焦点、onchange 元素改变、onclick 单击鼠标、onkeydown 按下按键时候触发、onkeypress 按下并松开时触发、onkeyup 松开按键时触发。
H5 input 元素 type 值举例
- button、checkbox、color 拾色器、date 日期字段、month 定义月、time 定义时间、email、file、hidden 隐藏输入字段、image 输入图像、number 带有微调spinner 控件的字段、password、radio、search、submit、text、url
css 三角形制作
- 画三角形的实质是设置内容宽高为0,显示其中一条边界线。
- .triangle { width: 0; height: 0; border 50px solid transparent; border-bottom: 100px solid green;}
css 中的单位,px、em、rem
- px 像素,绝对单位,相对于显示器屏幕分辨率而言。是计算机系统的数字化图像长度单位
- em 相对于当前元素内文本的字体尺寸
- rem 相对于根元素的字体尺寸, html 根元素默认 16px。
display: none 和 visibility: hidden 区别
- display: none 元素隐藏,占据的空间消失
- visibility: hidden 元素不可见,仍然占据页面空间
position 属性的值有哪些
- static:元素默认值
- relative:相对于元素原来在文档流中的定位
- absolute:相对于最近的非 static 定位祖先元素进行定位
- fixed:相对于相对于屏幕视口(viewport)的位置进行定位
- sticky:相对它的最近滚动祖先和最近块级祖先进行定位
雪碧图
- 将网站上用到的一些图片合并到一张图片上,通过减少网络请求来提高性能。
- 缺点,图片位置需要精确的指定,利用background、background-position 属性,增加了css 样式的编写难度。
css3 新增伪类,伪元素
- :first-of-type 父元素的首个p元素、:last-of-type 最后的p元素
- :nth-child(n) 括号中表达式(an+b)匹配到的元素集合(n=0,1,2,3…),还有odd、even 可用
- :not(p) 非p元素、:enabled 表单控件的可用状态、:disabled 禁用表单控件、:checked 单选框或者复选框被选中。
- ::first-line 样式添加到文本的首字母,::first-line 样式添加到文本的首行。
- 低版本的IE中,不兼容双冒号,继续使用单冒号的伪元素。
- 伪元素一般指的是特殊位置,而伪类,是特殊状态
图片懒加载原理
- 核心是,监控图片位置,在合适的位置将其加载出来。
- 设置图片的data-set 属性,为图片的url。当图片的顶点坐标Y小于页面和浏览器高度时,将data-set 内url 属性赋值给src。涉及到的API包括obj.getBoundingClientRect().top;document.documentElement.clientHeight;
JS 基本类型,引用类型
- 基本数据类型:number, string, boolean, null, undefined
- 引用数据类型:function, object, Array
- undefined 表示变量声明但是未初始化的值
- null 表示准备用来保存对象,但还没有真正保存对象的值
- undefined 派生至 null
创建对象的几种方式
- 字面量对象,
let o1 = { name: '01'}
- new 一个对象,
let o2 = new Object({ name: '02'})
- 显式的构造函数,
let o3 = function() { this.name = '03'};
- Object.create(),
let o = { name: '04'}; let o3 = Object.create(o)
区分数组和对象
- Array.isArray(),
- Aarray.isArray([]) // true
- Array.isArray({}) // false
- instanceof,
- [] instanceof Array // true
- {} instanceof Array // false
- constructor,
- {}.constructor // 返回object
- [].constructor // 返回Array
- Object.prototype.toString.call(),
- Object.prototype.toString.call([]) //[“object Array”]
- Object.prototype.toString.call({}) // [“object Object”]
伪数组(类数组)转化
- 伪数组具有length 属性,以及按照数组索引的方式存储数据。
- 转化方式
- Array.from()
- [].slice.call(eleArr) 或者 Array.prototype.slice.call(eleArr)
遍历对象属性
- Object.keys() 可枚举,非继承属性。for…in 还包括继承的可枚举属性
- Object.getOwnPropertyNames() 可枚举,不可枚举,非继承属性
- hasOwnProperty() 判断对象是否有某个属性
src 和 href 区别
- src (source) 资源,指向的内容会嵌入到标签所在位置,比如脚本,图片,iframe。解析到此类元素时。浏览器会暂停其他元素的下载和处理。知道将该元素加载、编译、执行完毕。
- href (hypertext reference) 建立和当前元素的链接。会并行下载i资源,不会停止对当前文档的处理。
dom 事件模型
- 元素发生一个事件,父元素也感受到了。那么就有了一个先后执行的问题。
- 事件由根元素开始触发,向内传播 —— 事件捕获
- 事件由目标元素,一直传播到根元素 —— 事件冒泡
- addEventListener 默认为事件冒泡机制
- 可以用 e.stopPropagation(); 或者 return false; 或者 e.preventDefault(); 停止事件在冒泡链上进一步扩大
js 定时器
- setTimeout() —— 在指定毫秒数后运行函数,一般用来模拟异步操作。
- setInterval() —— 按照设置的时间间隔运行函数,直到 clearInterval() 或者窗口被关闭
回调函数
- 软件模块之间的接口,从调用方式上可以分为 3 类,同步调用、异步调用、回调
- 同步调用就是通常所说的调用函数,一步一步执行,这是一种阻塞式调用,函数执行完毕才会返回。
- 异步调用,是一种类似于消息或者事件的机制。接口的服务在收到某种讯息或发生某种事件的时候,主动通知调用方。
- 回调函数就是一个通过函数指针调用的函数。把函数指针(地址)作为函数参数传递给另一个函数。
什么是闭包
- 闭包,closure,可以理解为一个封闭空间,一个定义在函数内部的函数。它可以通过作用域链访问外部函数的变量空间。
- 可以利用闭包的这个性质,保存外部变量,当然也会造成一些性能损失。
原型的理解
- 原型的作用是为了实现继承,和扩展对象的一种代码重用机制。
- js 中的所有元素,都可以看作是对象,他们都有一个 prototype 属性,它的值是一个对象,叫做原型,这个prototype 属性又有自己的 prototype 属性。最终链接到 Object 对象。
- prototype 属性,有一个 constructor 属性。可以用来构造对象的实例。
说下 this
- this 是一个标识符,用来指代函数执行的上下文执行环境。
- 讲 this,就一定要说一下对象的构造机制。在构造对象的时候,this 赋值为一个Object 实例,然后向其中添加属性方法。那么,对这个对象内部的函数,this 可以在它的变量表中,找到 this 所指代的对象。
- 那么一般地调用对象内部的方法,this 就是 函数前面的对象。从对象可以找到函数,那么函数内部的this, 指的就是这个对象。
- 另一个函数回调,要通过apply、call 手动声明函数的执行上下文,this 指代的是什么。
- 箭头函数,没有自己的this, 它使用的是自己定义环境中的this 指代的对象。通过作用域链是使用this。
统计出现最多的字符
1 |
|
内存泄漏
- 一些不再使用的变量,依然占据着内存空间,称为内存泄漏,(浪费掉了)
事件循环
- js 是一个单线程的语言。这意味着同一时间只能做一件事。
- 单线程不意味着阻塞,实现单线程非阻塞的方法是事件循环。
- js 中的任务可以分为同步任务和异步任务
- 同步任务就是立即执行的任务,会直接进入到主线程中执行
- 异步任务,异步执行的任务,比如ajax网络请求,setTimeout 定时函数
- 同步任务执行完毕,就会去任务队列中的任务,推入主线程执行。
- 异步任务又分为宏任务和微任务
- 执行机制为执行完宏任务后,执行所有微任务。再进行查看是有宏任务
- 常见的微任务有,Promise.then,MutationObserver,process.nextTick
Promise
- promise 是一个有状态的对象
- 将异步操作的结果和对应的处理函数结合起来
- 将异步操作以同步操作的流程表达出来,避免回调地狱
- Promise 的构造函数接收一个回调,回调有两个参数
resolve reject
,成功就调用resolve,表示promise 状态fulled,结果为resolve 返回的结果。实例化的Promise,返回的对象可以调用 then() 方法,then() 方法接收两个参数,onResolve 和 onReject 对应promise 成功或者失败的状态
手写 Promise
```js
class Promise {constructor(handler) { // define initial state this.status = "pending"; this.onFulfilledCallbacks = []; this.onRejectedCallbacks = []; // define basic transition function const resolve = value => { if (this.status === "pending") { this.status = "fulfilled"; this.value = value; this.onFulfilledCallbacks.forEach(fn => fn(value)); } }; const reject = value => { if (this.status === "pending") { this.status = "rejected"; this.value = value; this.onRejectedCallbacks.forEach(fn => fn(value)); } }; try { // call outer function passed in handler(resolve, reject); } catch (err) { reject(err); } } then(onFulfilled, onRejected) { // support chain call return new Promise((resolve, reject) => { // define handler if (this.status === "pending") { this.onFulfilledCallbacks.push(() => { try { // if return value is promise, resolve it. const fulfilledFromLastPromise = onFulfilled(this.value); if (fulfilledFromLastPromise instanceof Promise) { fulfilledFromLastPromise.then(resolve, reject); } else { resolve(fulfilledFromLastPromise); } } catch (err) { reject(err); } }); this.onRejectedCallbacks.push(() => { try { const rejectedFromLastPromise = onRejected(this.value); if (rejectedFromLastPromise instanceof Promise) { rejectedFromLastPromise.then(resolve, reject); } else { reject(rejectedFromLastPromise); } } catch (err) { reject(err); } }); } if (this.status === "fulfilled") { try { const fulfilledFromLastPromise = onFulfilled(this.value); if (fulfilledFromLastPromise instanceof Promise) { fulfilledFromLastPromise.then(resolve, reject); } else { resolve(fulfilledFromLastPromise); } } catch (err) { reject(err); } } if (this.status === "rejected") { try { const rejectedFromLastPromise = onRejected(this.value); if (rejectedFromLastPromise instanceof Promise) { rejectedFromLastPromise.then(resolve, reject); } else { reject(rejectedFromLastPromise); } } catch (err) { reject(err); } } }); }
}
// testing code
let p1 = new Promise((resolve, reject) => {setTimeout(() => resolve('resolved first one'), 1000);
});
p1.then((res) => {console.log(res); return new Promise(resolve => { setTimeout(() => resolve('resolved second one'), 1000); });
}).then(res => {
console.log(res);
});
// 1 sec later, ‘resolved first one’
// 1 sec later, ‘resolved second one’1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
实现 Promise.all, Promise.race, Promise.resolve and Promise.reject
- ```js
Promise.all = function (promises) {
return new Promise((resolve, reject) => {
let counter = 0;
const result = [];
for (let i = 0; i < promises.length; i++) {
// resolve revery promise, return result when every resolved
// when reject, return reject(err)
Promise.resolve(promises[i]).then(res => {
result[i] = res;
counter += 1;
// this check need to be here, otherwise counter would remain 0 till forloop is done
if (counter === promises.length) {
resolve(result);
}
}, err => {
reject(err);
});
}
});
};
const promise1 = Promise.resolve(3);
const promise2 = 42;
const promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
const newPromise = Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values);
});
// after 100ms, output: Array [3, 42, "foo"]```js
Promise.race = function (promises) {return new Promise((resolve, reject) => { for (let p of promises) { // iterate every promise, return the first one Promise.resolve(p).then(res => resolve(res), err => reject(err)); } });
}
// testing
const promise1 = new Promise((resolve, reject) => {setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then((value) => {console.log(value); // Both resolve, but promise2 is faster
}, err => console.log(err));
// expected output: “two”1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- ```js
Promise.resolve = function (value) {
if (value instanceof Promise) {
return value;
} else {
return new Promise((resolve, reject) => {
resolve(value);
});
}
};
Promise.reject = function (reason) {
return new Promise((resolve, reject) => reject(reason));
}
const p1 = Promise.resolve1("Success");
p1.then(res => console.log(res)); // "Success"
const p2 = Promise.reject1("No");
p2.then(_ => { }, err => console.log(err)); // "No"