快速搞定前端技术一面-匹配大厂面试要求
[学习笔记]快速搞定前端技术一面 匹配大厂面试要求
简介
HTML、CSS
HTML语义化
- 让人更容易读懂(增加代码可读性)
- 让搜索引擎更容易读懂(SEO)
块状元素、内联元素
- 块状元素:独占一行。
display:block/table div h1 h2 table ui ol p 等
- 内联元素:不独占,向后排列。
display:inline/inline-block; span img input button
盒模型宽度
- offsetWidth = (内容宽度 + 内边距 + 边框),无外边距。
- 答案:122px
box-sizing:border-box
1 | #div1 { |
margin相关
margin 纵向重叠
相邻元素的margin-top和margin-bottom会发生重叠(取最大值)
空白内容的
<p></p>
也会重叠答案:15px
margin 负值
- margin-top 和 margin-left 负值,元素向上、向左移动
- margin-right负值,右侧元素左移,自身不受影响;margin-bottom负值,下方元素上移,自身不受影响
line-height 继承问题
css - 响应式
rem
rem是一个长度单位;
px,绝对长度单温;
em,相对长度单位,相对于父元素;
rem,相对长度单位,相对于根元素,让用于响应式布局。
响应式布局常用方案
- media-query,根据不同屏幕宽度设置根元素 font-size
1 | @media only screen and(max-width:374px) { |
JS 基础
变量类型和计算
值类型、引用类型
1 | // 值类型 |
值类型存储于 栈
引用类型存储于 堆
应用类型存储的是内存地址,d = c,表示d和c指向同一块内存
1 | // 常见引用类型 |
typeof
- 识别所有值类型
- 识别函数
- 判断是否是引用类型(不可再细分、不能区分数组、对象、null)
1 | // 区分数组 和 对象 |
深拷贝
1 | /** |
变量计算-类型转换
字符串拼接
1 | 100 + 10 // 110 number |
== 运算符
1 | 100 == '100' // true |
1 | // 日常使用中 除了 == null 之外,其他都一律使用 === |
truly变量、falsely变量
- truly 变量:!!a === true 的变量
- false 变量:!!a === false 的变量
1 | // 举例、1 两次去反、1 是 truly 变量 |
1 | // 以下是 falsely 变量。除此之外都是 truly 变量 |
- if 语句判断就是 truly 变量;如
if('')1;else 0; // 0
原型和原型链
类型判断–instanceof
1 | // Object 是所有类的父类,基类 |
原型–隐士原型、显示原型
1 | // class 实际上是函数 ,语法糖 |
- 每个 class 都有显示原型
prototype
- 每个实例都有隐式原型
__proto__
- 实例的
__proto__
执行对应 class 的prototype
基于原型和执行规则
- 获取属性 xialuo.name 或执行方法 xialuo.sayhi() 时
- 先在自身属性和方法寻找
- 找不到,去
__proto__
总查找
原型链
1 | // class Student 是 class People 的子类 |
1 | xialuo.hasOwnProperty('name') // true |
instanceof 原理
1 | xialuo instanceof People // true |
提示
- class 是 ES6 语法规范,由 ECMA 委员会发布
- ECMA 只规定语法规则,即只规定代码的书写规范,不规定如何使用
- 以上实现方式 为 V8 引擎的实现方式,也是主流实现方式
作用域和闭包
作用域、自由变量
1 | // 创建 10 个 `<a>` 标签,点击的时候弹出来对应的序号 |
- 全局作用域
- 函数作用域
- 块级作用域(ES6新增)
自由变量
- 一个变量在当前作用域没有定义,但被使用了
- 向上级作用域,一层一层一次寻找,指导找到为止
- 如果找到全局作用域都没找到,则报错 xx is not defined
闭包
- 作用域应用的特殊情况,有两种表现
- 函数作为参数被传递
- 函数作用返回值被返回
1 | // 函数作为返回值 |
1 | // 函数作为参数 |
闭包:自由变量从函数定义的地方开始找,依次向上级作用域查找。
闭包的实际应用
- 隐藏数据
1 | function createCache() { |
this 赋值问题
常见情况
- 作为普通函数
- 使用 call apply bind
- 作为对象方法被调用
- 在 class 方法中调用
- 箭头函数
this 在各个场景中取值:函数执行的时候确定的,不是函数定义的时候确认的
1 | function fn1() { |
call apply bind 简介-区别
改变函数执行时的上下文,即改变函数运行时的 this 指向
call 和 apply
1
2obj.call(thisObj, arg1, arg2, ...);
obj.apply(thisObj, [arg1, arg2, ...]);
两者作用一致,都是把
obj
(即this)绑定到thisObj
,这时候thisObj
具备了obj
的属性和方法。或者说thisObj
『继承』了obj
的属性和方法。绑定后会立即执行函数。唯一区别是apply接受的是数组参数,call接受的是连续参数。
bind的使用
1 | obj.bind(thisObj, arg1, arg2, ...); |
把obj绑定到thisObj,这时候thisObj具备了obj的属性和方法。与call和apply不同的是,bind绑定后不会立即执行。需要调用
JS 异步
异步基础
单线程和异步
- JS 是单线程语言,只能同时做一件事
- 浏览器和 nodejs 已支持 JS 启动进程,如 Web Worker
- JS 和 DOM 渲染共用同一个线程,因为 JS 可修改 DOM 结构
- 异步不会阻塞代码运行,同步会阻塞代码执行
回调地狱-callback hell
Promise 基础
异步进阶
JS 如何执行
- 从前到后,一行一行执行
- 如果某一行执行错误,则停止下面代码的执行
- 先把同步代码执行完,在执行异步
event loop(事件循环/事件轮循)
JS 是单线程运行的,异步要基于回调来实现;event loop 就是异步回调的实现原理
- event loop 过程
- 同步代码,一行一行放在 Call StacK 执行
- 遇到异步,会先“记录”下,等待时机(定时、网络请求)
- 时机到了,就移动到 Callback Queue
- 如 Call Stack 为空(即同步代码执行完)Event Loop 开始工作
- 轮询查找 Callback Queue,如有则移动到 Call Stack 执行
- 然后继续轮询查找(永动机一样)
DOM 事件和 event loop
异步(setTimeout,ajax等)使用回调,基于 event loop
DOM 事件(dom事件不是异步)也使用回调,基于 event loop
Promise 进阶
- Promise 的三种状态
- pending
- resolved
- rejected
- resolved 触发 then 回调,rejected 触发 catch 回调
- then 和 catch 改变状态(没有报错,都返回resolved)
- then 正常返回 resolved,里面有报错则返回 rejected
- catch 正常返回 resolved,里面有报错则返回 rejected
async/await
- 产生背景
异步回调 callback hell —> Promise then catch 链式调用,但也是基于回调函数 —> async\await是同步语法,彻底消灭回调函数
- 立即调用函数表达式 参考链接 IIFE
1 | // 感叹号,用来分割上一行(上一行没分号结尾的话) |
- async/await 只是一个语法糖
async/await 与promise 关系
- await 相当于 Promise then
- promise catch 可以使用 try catch 代替
- async 封装 promise 返回 promise
执行循序例题
1 | async function async1() { |
1 | async function async1() { |
for … of
- for … in 以及 forEach for 是常规的同步遍历
- for … of 常用于异步的遍历
1 | function muti(num) { |
宏任务 macroTask 和微任务 microTask
1 | console.log('start') // 1 |
宏任务:setTimeout seInterval Ajax DOM 事件;DOM 渲染后触发;微任务是 ES6 语法规定的
微任务:Promise async/await;DOM 渲染前触发;宏任务是由浏览器规定的
微任务执行时机比宏任务要早
event-loop 和 dom 渲染的关系
- 每次 Call Stack 清空(即每次轮询结束),即同步任务执行完
- 都是 DOM 重新渲染的机会,DOM 结构如有改变则重新渲染
- 然后再去触发下一次 Event Loop
1 | <div id="container"></div> |
题目
1 | async function async1() { |
JS Web API
- JS 基础知识,规定语法 ECMA 262 标准
- JS Web API,网页操作的 API W3C 标准
DOM
DOM:Document Object Model
Vue 和 React 框架应用广泛,封装了 DOM 操作
DOM 节点操作
1 | const div1 = document.getElementById('div1') // 元素 |
property:修改 dom 结构的变量,不表现在 html 中
1 | const pList = document.querySelectorAll('p') |
attribute:修改 dom 结构的属性,表现在 html 中
1 | const pList = document.querySelectorAll('p') |
- property:修改对象属性,不会体现到 html 结构中
- attribute:修改 html 属性,会修改 html 结构
- 两者都有可能引起 DOM 重新渲染;优先选择 property
DOM 结构操作
- 新增/插入节点
1 | const div1 = document.getElementById('div1') |
- 获取子元素列表、获取父元素
1 | // 获取子元素列表 |
- 删除节点
1 | const div1 = document.getElementById('div1') |
DOM 性能
DOM 操作非常 “昂贵”,避免频繁的 DOM 操作
DOM 查询作缓存
- 将频繁操作改为一次性操作
BOM
- BOM:Browser Object Model
navigator、screen
1 | // navigator、浏览器标识 |
location、history
1 | location.href // "https://coding.imooc.com/class/chapter/400.html#Anchor" |
事件
事件绑定
1 | const btn = document.getElementById('btn1') |
事件冒泡
- 基于 DOM 树形结构
- 事件会顺着触发元素向上冒泡
- 应用场景:事件代理
1 | <body> |
事件代理
扩展阅读:掘金:js中的事件委托或事件代理详解
Ajax
1 | // 手写一个简单的 ajax |
XMLHttpRequest
1 | // get 请求 |
xhr.readySate
- 0—未初始化,还没有调用 send() 方法
- 1—载入,已调用 send() 方法,正在发送请求
- 2—载入完成,sedn() 方法执行完成,已经接收到全部相应内容
- 3—交互,正在解析相应内容
- 4—完成,相应内容解析完成,可以在客户端调用
xhr.status
- http 状态码
- 2xx:表示成功处理请求,如 200
- 3xx:需要重定向,浏览器直接跳转,如 301 302 304
- 4xx:客户端请求错误,如 404 403
- 5xx:服务端错误
跨域
同源策略
- ajax 请求时,浏览器要求当前网页和 server 必须同源(为了保证安全)
- 同源:协议、域名、端口三者必须一致
- 加载图片 css js 可无视同源策略;img src、link href、script src
jsonp
JSONP是一种发送JSON数据而无需担心跨域问题的方法。
JSONP不使用该
XMLHttpRequest
对象。JSONP使用
<script>
标记代替。由于跨域策略,从另一个域请求文件可能会导致问题。
从另一个域请求外部脚本不会出现此问题。
JSONP利用了这一优势,并使用脚本标签而不是
XMLHttpRequest
对象来请求文件。
1 | // jQuery 实现 jsonp |
CORS
- 服务端设置 http header,服务端的设置
1 | // 跨域的域名称,不建议直接写 "*" |
存储
cookie
- 本身用于浏览器和 server 通讯
- 被 ”借用“ 到本地存储来
- 可用 document.cookie = ‘…’ 来修改
- 最大 4k
- 默认跟随 http 请求,发送到服务器
localStorage 和 sessionStorage
HTML5 专门为存储而设计,最大可存 5M(每个域)
localStorage 数据会永久储存,触发代码或手动删除
sessionStorage 数据只存在于当前会话,浏览器关闭则清空
一般用 localStorage 会更多一些
Http
http 状态码和http methods,仅仅使一个约束规范。可以更改(不建议)
http 状态码
- 状态码分类
- 1xx:服务器收到请求
- 2xx:请求成功,如 200
- 3xx:重定向,如 302
- 4xx:客户端错误,如 404
- 5xx:服务端错误,如 500
- 常用状态码
- 200 成功
- 301 永久重定向 配合 location,浏览器自动处理。如换域名,浏览器会存缓存。
- 302 临时重定向 配合 location,浏览器自动处理。如搜索引擎的跳转链接、短网址的跳转。
- 304 资源未被修改,两次请求的内容是相同的
- 404 资源未找到
- 404 没有权限
- 500 服务器错误
- 504 网关超时
http methods
- 传统 methods
- get 获取服务器的数据
- post 向服务器提交数据
- 现在的 methods
- get 获取数据
- post 新建数据
- patch/put 更新数据
- delete 删除数据
Restful API
- 一种新的 API 设计方法(早已推广使用)
- 传统 API 设计:把每个 url 当做一个功能
- Restful API 设计:把每个 url 当做一个唯一的资源
如何设计成一个资源?
- 尽量不用 url 参数
- 传统 API 设计:
/api/list?pageIndex=2
- Restful API 设计:
/api/list/2
- 传统 API 设计:
- 用 method 表示操作类型
- 传统 API 设计,如
- post 请求
/api/create-blog
创建博客 - post 请求
/api/update-blog?id=100
更改博客内容 - get 请求
/api/get-blog?id=100
获取博客内容
- post 请求
- Restful API
- post 请求
/api/blog
新建博客 - patch 请求
/api/blog/100
更新博客 - get 请求
/api/blog/100
获取博客内容
- post 请求
- 传统 API 设计,如
http headers
常见的 Request Headers:请求头
常见 Response Headers:响应头
自定义 header:如,Authentication;常用语接口鉴权
缓存相关的 headers
http 缓存
http 缓存-强制缓存
Cache-Control
- Response Headers 中
- 控制强制缓存的逻辑
- 例如:cache-control: max-age=2592000 单位是秒
- cache-control的值
- max-age:缓存的最大过期时间
- no-cache:不用强制缓存,交给服务端处理
- no-store:不缓存,让服务端再次返回
- private:用户缓存
- public:允许中间路由、代理进行缓存
Expires
- 同在 Response Headers 中
- 同为控制缓存过期
- 已被 Cache-Control 代替
http缓存-协商缓存(对比缓存)
- 服务端缓存策略,服务端判断这个文件是否需要缓存
- 服务器判断客户端资源,是否和服务端资源一样
- 一致则返回 304 ,负责返回 200 和最新的资源
资源标识
- 在 Response Headers 中,有两种
- last-Modified 资源的最后修改时间
- Etag 资源的唯一标识(一个字符串,类似人类的指纹)
- 两者会优先使用 Etag
- Last-Modified 只能精确到秒级
- 如果资源被重复生成,而内容不变,则 Etag 更精确
Last-Modified
Etag
刷新页面对缓存的影响
三种刷新方式
- 正常操作:地址栏输入url、跳转链接、前进后退
- 手动刷新:F5、点击刷新按钮、右击菜单刷新
- 强制刷新:ctrl + F5
不同刷新操作、不同缓存策略
- 正常操作:强制缓存有效,协商缓存有效
- 手动刷新:强制缓存失效,协商缓存有效
- 强制刷新:强制缓存失效,协商缓存失效
开发环境
git
- 最常用的代码版本管理工具
- 常用 git 命令
- git add .
- git checkout xxx
- git commit -m “xxx”
- git push origin master
- git pull origin master
webpack 和 babel
为什么需要
- ES6 模块化,浏览器暂不支持
- ES6 语法,浏览器并不完全支持
- 压缩代码,整合代码,让网页加载更快
webpack 配置
注意版本问题:最新版本的需要配置一些其他项
所以我的是指定版本安装:和视频演示的版本一致
npm install webpack@4.41.0 webpack-cli@3.3.9 webpack-dev-server@3.8.2 html-webpack-plugin@3.2.0 -D
初始化:
npm init -y
–> 生成 package.json 文件安装 webpack 依赖:
npm install webpack webpack-cli -D
-D 选项为开发依赖webpack.config.js 文件基本配置
- ```javascript
const path = require(‘path’)
module.exports = {
mode: ‘development’, // production development
entry: path.join(__dirname, ‘src’, ‘index.js’),
output: {
filename: ‘bundle.js’,
path: path.join(__dirname, ‘dist’),
},
}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
* Ïpachage.json scripts 配置:`"build": "webpack"` 打包命令
* 扩展 html 打包; 安装插件
* `npm i html-webpack-plugin -D`
* `npm i webpack-dev-server -D `
* webpack.config.js 配置
* ```javascript
const path = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
mode: 'development', // production development
entry: path.join(__dirname, 'src', 'index.js'),
output: {
filename: 'bundle.js',
path: path.join(__dirname, 'dist'),
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, 'src', 'index.html'),
filename: 'index.html', // 打包后的 dist 下的文件名
}),
],
devServer: {
port: 3000,
contentBase: path.join(__dirname, 'dist'),
},
}
- ```javascript
package.json 配置
- ```javascript
“scripts”: {
“dev”: “webpack-dev-server”,
“build”: “webpack [–config webpack.config.js]”,
“test”: “echo "Error: no test specified" && exit 1”
},1
2
3
4
5
6
7
8
9
10
11
12
13
* `npm run dev` 执行本地运行
##### babel 配置、转义为 ES5
* `npm i @babel/core @babel/preset-env babel-loader -D`
* `.babelrc` 文件配置
* ```javascript
{
"presets": ["@babel/preset-env"]
}
- ```javascript
webpack.config.js 配置
- ```javascript
module: {
rules: [
{
test: /.js$/, // 符合此正则的走 babel-loader 插件
loader: [‘babel-loader’],
include: path.join(__dirname, ‘src’), // 此目录下的走 babel-loader 插件
exclude: /node_modules/, // 排除此目录
},
],
},1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
##### ES6 模块化
* 第一种方式
```javascript
// a.js 导出多个
export function fn() {
console.log('fn')
}
export const name = 'a'
export const obj = {
name: 'zhangsan',
}
// index.js 导入,需要解构
import { fn, name, obj } from './a'
fn() // 正常使用
console.log(name,obj)
- ```javascript
第二种方式
1 | // 导出一个 |
生产环境配置
webpack.prod.js
package.json scripts
"build": "webpack --config webpack.prod.js",
```javascript
const path = require(‘path’)
const HtmlWebpackPlugin = require(‘html-webpack-plugin’)module.exports = {
mode: ‘production’, // production development
entry: path.join(__dirname, ‘src’, ‘index.js’),
output: {
filename: ‘bundle.[contenthash].js’,// contenthash 根据代码内容计算出的哈希值
path: path.join(__dirname, ‘dist’),
},
module: {
rules: [
{
test: /.js$/, // 符合此正则的走 babel-loader 插件
loader: [‘babel-loader’],
include: path.join(__dirname, ‘src’), // 此目录下的走 babel-loader 插件
exclude: /node_modules/, // 排除此目录
},
],
},
plugins: [
new HtmlWebpackPlugin({
template: path.join(__dirname, ‘src’, ‘index.html’),
filename: ‘index.html’, // 打包后的 dist 下的文件名
}),
],
}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
完整 webpack demo [gitee仓库](https://gitee.com/yishen_yishen/webpack-demo)
## 运行环境
### 网页加载渲染过程
#### 加载资源的过程
* DNS 解析:域名 -> IP 地址
* 浏览器根据 IP 地址向服务器发起 http 请求
* 服务器处理 http 请求,并返回给浏览器
#### 渲染过程
* 根据 HTML 代码生成 DOM Tree;DOM:document object model
* 根据 CSS 代码生成 CSSOM
* 将 DOM Tree 和 CSSOM 整合形成 Render Tree(渲染树)
* 根据 Render Tree 渲染页面
* 遇到 `<script>` 则暂停渲染,优先加载并执行 JS 代码,完成在继续
* 直至 Render Tree 渲染完成
##### window.onload 和 DOMContentLoaded区别
```javascript
document.addEventListener('DOMContentLoaded', function () {
// DOM 渲染完即可执行,此时图片、视频可能还没有加载完成
console.log('1')
})
window.addEventListener('load', function () {
// 页面的全部资源加载完,才会执行,包括图片、视频等
console.log('2')
})
性能优化
性能优化原则
- 多使用内存、缓存或其他方法
- 减少 CPU 计算量,减少网络加载耗时
- (适用于所有编程的性能优化—空间换时间)
从何入手
让加载更快
- 减少资源代码:压缩代码
- 减少访问次数:合并代码,SSR 服务端渲染,缓存
- 使用更快的网络:CDN
让渲染更快
- CSS 放 head ,JS 放在 body 最下面
- 今早开始执行 JS ,用 DOMContentLoaded 触发
- 懒加载(图片懒加载,上滑加载更多)
- 对 DOM 查询进行缓存
- 频繁 DOM 操作,合并到一起插入 DOM 结构
- 节流 throttle 防抖 debounce
SSR–Server-Side Rendering
- 服务端渲染:将网页和数据一起加载,一起渲染
- 非 SSR (前后端分离):先加载网页,再加载数据,再渲染数据
防抖 debounce
监听一个输入框,文字变化后触发 change 事件;直接用 keyup 事件,则会频繁触发 change 事件;
防抖:用户输入结束或暂停时,才会触发 change 事件。
扩展阅读:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/5
1 | // 纯 JS 中写法 |
1 | // 封装一下,使其实用性更强 |
节流 throttle
拖拽一个元素时,要随时按到该元素被拖拽的位置;直接用 drag 事件,则会频繁触发,很容易导致卡顿;节流:无论拖拽速度多快,都会每隔 100ms 触发一次
1 | <!-- 基础写法 --> |
1 | // 封装一下 |
安全
扩展阅读:前端安全系列(一):如何防止XSS攻击?
XSS 跨站请求攻击
一个博客网站,我发表一篇博客,其中嵌入
<script>
脚本;脚本内容:获取 cookie,发送到我的服务器(服务器 配合跨域);发布这篇博客,有人查看它,我轻松收割访问者的 cookie
- XSS 预防
XSRF 跨站请求伪造
- XSRF 预防
面试题
下面的三级标题,代表的是此小节视频对应的标题。四级标题为对应的面试题。
何为变量提升
变量提升
1 | // 变量提升 ES5 |
typeof 判断类型
- undefined、string、number、boolean、symbol
- object(typeof null === ‘object’)
- function
手写深度比较 isEqual
手写深度比较 lodash.isEqual
1 | // 实现效果如下 |
1 | function isEqual(obj1, obj2) { |
split() 和 join()
1 | '1-2-3'.split('-') // [1,2,3] |
数组的 pop push unshift shift
- 功能是什么?
- 返回值是什么?
- 是否会对原数组造成影响?
1 | const arr = [10,20,30,40] |
纯函数
- 不改变源数组(没有副作用)
- 返回一个数组
1 | // arr1.concat(arr2) 拼接两个数组,不影响源数组,返回新数组 |
你是否真的会用数组
数组 slice 和 splice 的区别
- 功能区别(slice-切片,splice-剪接)
1 | const arr = [10,20,30,40] |
[10,20,30].map(parseInt)
- map 的参数和返回值
- parseInt 的参数和返回值
- parseInt(*string*, *radix*) 解析一个字符串并返回指定基数的十进制整数,
radix
是2-36之间的整数,表示被解析字符串的基数
- parseInt(*string*, *radix*) 解析一个字符串并返回指定基数的十进制整数,
1 | [10,20,30].map(parseInt) // [10, NaN, NaN] |
ajax 请求 get 和 post 的区别
- get 一般用于查询操作,post 一般用于提交操作
- get 参数拼接在 url 上,post 放在请求体内(数据体积可以更大)
- 安全性:post 易于防止 CSRF
再学闭包
函数 call 和 apply 的区别
1 | // 传参不同,call 参数分开传,apply 传一个数组 |
事件代理(委托)是什么
闭包是什么,有什么特性?有什么负面影响?
跳转 [闭包](# 闭包)
闭包影响:变量会常驻内存,得不到释放。闭包不要乱用
回顾 DOM 操作和优化
如何阻止事件冒泡和默认行为?
1 | event.stopPropagation() |
如何减少 DOM 操作?
1 | // DOM 查询结果做缓存 |
jsonp 本职是 ajax 吗?
解释 jsonp 的原理,为何它不是真正的 ajax
- 浏览器的同源策略(服务端没有同源策略)和跨域
- jsonp 原理
jsonp 是使用 script 标签来进行通信。没有使用 xhr 请求。
document load 和 ready 的区别
== 和 === 的不同
跳转 [链接](# == 运算符)
- 日常使用中 除了 == null 之外,其他都一律使用 ===
常见的正则表达式
关于作用域和自由变量的场景题
1 | // question 1 |
1 | // question 2 |
判断字符串以字母开头,后面字母数字下划线,长度 6-30
1 | const reg = /^[a-zA-Z]\w{5,29}$/ |
如何获取最大值
手写字符串 trim 方法,保证浏览器兼容性
1 | String.prototype.trim = function(){ |
如何获取多个数字中的最大值
1 | function max() { |
如何用 JS 实现继承
- class 继承
- protorype 继承
解析 url 参数
如何捕获 JS 程序中的异常?
1 | try{ |
1 | window.onerror = function(message,source,lineNom,colNom,error){ |
什么是 JSON
- json 是一种数据格式,本职是一段字符串
- json 格式和 js 对象结构一致,对 JS 语言更友好
- window.JSON 是一个全局对象:JSON.stringify JSON.parse
获取当前页面 url 参数
数组去重有几种方式
将 url 参数解析为 JS 对象
1 | // 传统方法 |
1 | // 新方法 |
手写数组 flatern,考虑多层级
flatern 可以理解为,拍平,扁平化(v.)
1 | flat([1,2,[1,2,3],4,5]) |
1 | function flat(arr) { |
数组去重
1 | // 传统方式 |
1 | // 使用 Set(无序,不能重复) |
是否用过 requestAnimationFrame
手写深拷贝
[跳转链接](# 深拷贝)
- Object.assign 不是深拷贝
1 | function deepClone(obj = {}) { |
RAF requestAnimationFrame
- 要想动画流畅,更新频率要 60帧/s,即16.67ms 更新一次视图
- setTimeout 要手动控制频率,而 RAF 浏览器会自动控制
- 后台标签或隐藏 iframe 中,RAF 会暂停,而 setTimeout 依然执行
前端性能如何优化?一般从哪几个方面考虑?
- 原则:多使用内存、缓存、减少计算、减少网路请求
- 方向:加载页面,页面渲染,页面操作流畅度
完