FileReader 对象允许 Web 应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,

使用 FileBlob 对象指定要读取的文件或数据。其中 File 对象可以是来自用户在一个<input>元素上选择文件后返回的 FileList 对象,

也可以来自拖放操作生成的 DataTransfer 对象,还可以是来自在一个 HTMLCanvasElement 上执行 mozGetAsFile()方法后返回结果.

1
2
3
<input type="file" />
<br />
<img src="" alt="" />
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var fileInput = document.querySelector("input[type=file]");
var viewImg = document.querySelector("img");
fileInput.addEventListener(
"change",
function () {
//console.log(this.files[0]);
var file = this.files[0];
var reader = new FileReader();
reader.addEventListener(
"load",
function () {
console.log(reader.result);
viewImg.src = reader.result;
},
false
);
reader.readAsDataURL(file);
},
false
);
阅读全文 »

最近在写一个移动端项目,在 Android 设备是播放音乐没有问题,但是在苹果设备上音乐无法播放,查阅资料才知道 safari 默认在没有用户交互的情况下是不允许自动播放音乐的.
所以想到了用 touchstart 事件进行交互

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
(function () {
var audio = document.querySelector("#audio");
function PlayAudio() {
audio.load(); // iOS 9 需要 load 一下, 否则直接 play 无效
audio.play(); // iOS 7/8 需要 play 一下
}
audio.addEventListener(
"play",
function () {
// 当 audio 能够播放后, 移除这个事件
window.removeEventListener("touchstart", PlayAudio, false);
},
false
);
window.addEventListener("touchstart", PlayAudio, false);
})();

JavaScript 没有严格意义上,区分堆与栈,所有可以理解为 JavaScript 所有的数据都是存放在堆内存中,但是大部分时候我们还是需要借助堆栈来理解。

堆与栈

栈由操作系统自动分配释放 ,用于存放函数的参数值、局部变量等,栈数据结构的一个特点就是后进先出。
堆由开发人员分配和释放, 若开发人员不释放,程序结束时由 OS 回收,分配方式类似于链表,堆数据结构类似于 JSON 对象中的 key-value。

基本数据类型和引用数据类型

JavaScript 中的数据类型分为:基本数据类型与引用数据类型
基本数据类型都是存放在栈内存中
引用数据类型都是存放在堆内存中,javascript 是不允许直接访问堆内存中的数据,所以如果我们要访问引用数据类型的时候,采用的是按引用访问,就是在变量对象中存放了一个指向对象的地址,要访问堆内存中的对象,就要通过这个引用地址来访问
所以,在堆 JavaScript 变量进行拷贝时,基本数据类型相当于复制了一份数据,而引入数据类型只是复制了一个地址,其引用的对象依然没有发生变化

阅读全文 »

JavaScript 中的异常处理可以用来避免浏览器向用户报告错误信息,也可以向调用者报告错误信息。

try/catch/finally

try 语句允许我们定义在执行时进行错误测试的代码块。
catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
finally 语句在 try 和 catch 之后无论有无异常都会执行。
注意: catch 和 finally 语句都是可选的,但你在使用 try 语句时必须至少使用一个。

1
2
3
4
5
6
7
8
9
try {
tryCode - 尝试执行代码块
}
catch(err) {
catchCode - 捕获错误的代码块
}
finally {
finallyCode - 无论 try / catch 结果如何都会执行的代码块
}

throw

阅读全文 »

XMLHttpRequest

XMLHttpRequest(XHR)对象用于在页面已加载后从服务器接收数据,可以在不重新加载页面的情况下更新网页。
所有现代浏览器 (IE7+、Firefox、Chrome、Safari 以及 Opera) 都内建了 XMLHttpRequest 对象。

Ajax

JQuery 的 Ajax 是对原生 XHR 的封装,支持 JSONP。

缺点:

阅读全文 »

window.performance 允许网页访问某些函数来测量网页和 Web 应用程序的性能。

window.performance.timing (PerformanceTiming)

返回一个 Object,提供了在加载和使用当前页面期间发生的各种事件的性能计时信息。(均为一个无符号 long 型的毫秒数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
PerformanceTiming.navigationStart // 表示从同一个浏览器上下文的上一个文档卸载(unload)结束时的 UNIX 时间戳。如果没有上一个文档,这个值会和 PerformanceTiming.fetchStart 相同
PerformanceTiming.unloadEventStart // 表示 unload 事件抛出时的 UNIX 时间戳。如果没有上一个文档,或者上一个文档或所需的重定向之一不是同一来源, 这个值会返回 0
PerformanceTiming.unloadEventEnd // 表示 unload 事件处理完成时的 UNIX 时间戳。如果没有上一个文档,或者上一个文档或所需的重定向之一不是同一来源,这个值会返回 0
PerformanceTiming.redirectStart // 表示第一个 HTTP 重定向开始时的 UNIX 时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回 0.
PerformanceTiming.redirectEnd // 表示最后一个 HTTP 重定向完成时(也就是说是 HTTP 响应的最后一个比特直接被收到的时间)的 UNIX 时间戳。如果没有重定向,或者重定向中的一个不同源,这个值会返回 0
PerformanceTiming.fetchStart // 表示浏览器准备好使用 HTTP 请求来获取(fetch)文档的 UNIX 时间戳。这个时间点会在检查任何应用缓存之前
PerformanceTiming.domainLookupStart // 表示域名查询开始的 UNIX 时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 PerformanceTiming.fetchStart 一致
PerformanceTiming.domainLookupEnd // 表示域名查询结束的 UNIX 时间戳。如果使用了持续连接(persistent connection),或者这个信息存储到了缓存或者本地资源上,这个值将和 PerformanceTiming.fetchStart 一致
PerformanceTiming.connectStart // 返回 HTTP 请求开始向服务器发送时的 Unix 毫秒时间戳。如果使用持久连接(persistent connection),则返回值等同于 fetchStart 属性的值
PerformanceTiming.connectEnd // 返回浏览器与服务器之间的连接建立时的 Unix 毫秒时间戳。如果建立的是持久连接,则返回值等同于 fetchStart 属性的值。连接建立指的是所有握手和认证过程全部结束
PerformanceTiming.secureConnectionStart // 返回浏览器与服务器开始安全链接的握手时的 Unix 毫秒时间戳。如果当前网页不要求安全连接,则返回 0
PerformanceTiming.requestStart // 返回浏览器向服务器发出 HTTP 请求时(或开始读取本地缓存时)的 Unix 毫秒时间戳
PerformanceTiming.responseStart // 返回浏览器从服务器收到(或从本地缓存读取)第一个字节时的 Unix 毫秒时间戳。如果传输层在开始请求之后失败并且连接被重开,该属性将会被数制成新的请求的相对应的发起时间
PerformanceTiming.responseEnd // 返回浏览器从服务器收到(或从本地缓存读取,或从本地资源读取)最后一个字节时(如果在此之前 HTTP 连接已经关闭,则返回关闭时)的 Unix 毫秒时间戳
PerformanceTiming.domLoading // 返回当前网页 DOM 结构开始解析时(即 Document.readyState 属性变为“loading”、相应的 readystatechange 事件触发时)的 Unix 毫秒时间戳
PerformanceTiming.domInteractive // 返回当前网页 DOM 结构结束解析、开始加载内嵌资源时(即 Document.readyState 属性变为“interactive”、相应的 readystatechange 事件触发时)的 Unix 毫秒时间戳
PerformanceTiming.domContentLoadedEventStart // 返回当解析器发送 DOMContentLoaded 事件,即所有需要被执行的脚本已经被解析时的 Unix 毫秒时间戳
PerformanceTiming.domContentLoadedEventEnd // 返回当所有需要立即执行的脚本已经被执行(不论执行顺序)时的 Unix 毫秒时间戳
PerformanceTiming.domComplete 返回当前文档解析完成,即 Document.readyState 变为 'complete'且相对应的 readystatechange 被触发时的 Unix 毫秒时间戳
PerformanceTiming.loadEventStart // 返回该文档下,load 事件被发送时的 Unix 毫秒时间戳。如果这个事件还未被发送,它的值将会是 0
PerformanceTiming.loadEventEnd // 返回当 load 事件结束,即加载事件完成时的 Unix 毫秒时间戳。如果这个事件还未被发送,或者尚未完成,它的值将会是 0

常用计算:
DNS 查询耗时 :domainLookupEnd - domainLookupStart
TCP 链接耗时 :connectEnd - connectStart
request 请求耗时 :responseEnd - responseStart
解析 dom 树耗时 : domComplete - domInteractive
白屏时间 :responseStart - navigationStart
domready 时间(用户可操作时间节点) :domContentLoadedEventEnd - navigationStart
onload 时间(总下载时间) :loadEventEnd - navigationStart

阅读全文 »

hash

所有文件哈希值相同,只要改变内容跟之前的不一致,所有哈希值都改变,没有做到缓存意义

hash 是跟整个项目的构建相关,构建生成的文件 hash 值都是一样的,所以 hash 计算是跟整个项目的构建相关,同一次构建过程中生成的 hash 都是一样的,只要项目里有文件更改,整个项目构建的 hash 值都会更改。
如果出口是 hash,那么一旦针对项目中任何一个文件的修改,都会构建整个项目,重新获取 hash 值,缓存的目的将失效。

chunkhash

同一个模块,就算将 js 和 css 分离,其哈希值也是相同的,修改一处,js 和 css 哈希值都会变,同 hash,没有做到缓存意义

阅读全文 »

router

router 是 VueRouter 的一个对象,通过 Vue.use(VueRouter)VueRouter 构造函数得到一个 router 的实例对象,这个对象中是一个全局的对象,他包含了所有的路由包含了许多关键的对象和属性。

1
举例:history 对象

$router.push({path:'home'}); 本质是向 history 栈中添加一个路由,在我们看来是 切换路由,但本质是在添加一个 history 记录
方法:

1
$router.replace({ path: "home" }); //替换路由,没有历史记录
阅读全文 »

  1. removeCache.js
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
const fs = require("fs");
const child_process = require("child_process");

/*
*@functionName: deleteFolder
*@params1: 删除的文件路径
*@description: 删除项目中的缓存文件
*/
const deleteFolder = async function (path) {
var files = [];
if (fs.existsSync(path)) {
files = fs.readdirSync(path);
files.forEach(function (file, index) {
var curPath = path + "/" + file;
if (fs.statSync(curPath).isDirectory()) {
// recurse
deleteFolder(curPath);
} else {
// delete file
fs.unlinkSync(curPath);
}
});
await fs.rmdirSync(path);
}
};
deleteFolder("./node_modules/.cache/compression-webpack-plugin");
  1. package.json
1
2
3
4
5
{
"script": {
"rmcatch": "node ./removeCache.js"
}
}

一道面试题引发的思考

面试题

1
2
3
4
5
6
7
8
9
10
11
12
// 输入数据
const input = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]]],
10
];

// 输出数据
expect = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14];

// 附加条件 最好不要超过五行

学霸答案

1
2
3
4
5
6
7
8
9
10
const ary = [
[1, 2, 2],
[3, 4, 5, 5],
[6, 7, 8, 9, [11, 12, [12, 13, [14]]]],
10
];
console.log(
"ary",
[...new Set(ary.flat(Infinity))].sort((a, b) => a - b)
);
阅读全文 »