Skip to content

Commit 9e637f0

Browse files
committed
update
1 parent 215f5f0 commit 9e637f0

File tree

8 files changed

+387
-0
lines changed

8 files changed

+387
-0
lines changed

README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,22 @@ https://github.com/webVueBlog/Leetcode
1313

1414
欢迎大家前来讨论,如果觉得对你的学习有一定的帮助,欢迎点个Star (此仓库每天都会准时更新)
1515

16+
## 😘 阶段十三(347)
17+
18+
<details open>
19+
<summary>展开查看</summary>
20+
21+
- 341.[作用域链增强](./阶段十三/作用域链增强.js)
22+
- 342.[变量声明](./阶段十三/变量声明.js)
23+
- 343.[垃圾回收](./阶段十三/垃圾回收.js)
24+
- 344.[标记清理](./阶段十三/标记清理.js)
25+
- 345.[引用计数](./阶段十三/引用计数.js)
26+
- 346.[性能](./阶段十三/性能.js)
27+
- 347.[内存管理](./阶段十三/内存管理.js)
28+
29+
</details>
30+
31+
1632
## 🥰 阶段十二(340)
1733

1834
<details open>

阶段十三/作用域链增强.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
3+
虽然执行上下文主要有全局上下文和函数上下文两种(eval()调用内部存在第三种上下文),但有其他方式来增强作用域链。
4+
5+
在作用域链前端临时添加一个上下文
6+
7+
通常在两种情况下会出现这个现象
8+
9+
try/catch 语句的 catch 块 : 会创建一个新的变量对象,这个变量对象会包含要抛出的错误对象的声明。
10+
11+
with 语句: 会向作用域链前端添加指定的对象
12+
13+
都会在作用域链前端添加一个变量对象。
14+
15+
function buildUrl() {
16+
let qs = "?debug=true";
17+
with(location){
18+
let url = href + qs;
19+
}
20+
return url;
21+
}
22+
23+
with 语句将 location 对象作为上下文
24+
25+
*/

阶段十三/内存管理.js

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
/**
2+
3+
将内存占用量保持在一个较小的值可以让页面性能更好。
4+
5+
优化内存占用的最佳手段就是保证在执行代码时只保存必要的数据。如果数据不再必要,那么把它设置为 null,从而释放其引用。
6+
7+
这也可以叫作解除引用
8+
9+
最适合全局变量和全局对象的属性。局部变量在超出作用域后会被自动解除引用
10+
11+
12+
function createPerson(name){
13+
let localPerson = new Object();
14+
localPerson.name = name;
15+
return localPerson;
16+
}
17+
let globalPerson = createPerson("Nicholas");
18+
// 解除 globalPerson 对值的引用
19+
globalPerson = null;
20+
21+
22+
1. 通过 const 和 let 声明提升性能
23+
2. 隐藏类和删除操作
24+
25+
运行期间,V8 会将创建的对象与隐藏类关联起来,以跟踪它们的属性特征。能够共享相同隐藏类的对象性能会更好,V8 会针对这种情况进行优化,但不一定总能够做到。
26+
27+
function Article() {
28+
this.title = 'Inauguration Ceremony Features Kazoo Band';
29+
}
30+
let a1 = new Article();
31+
let a2 = new Article();
32+
33+
V8 会在后台配置,让这两个类实例共享相同的隐藏类,因为这两个实例共享同一个构造函数和原型。
34+
35+
36+
解决方案就是避免 JavaScript 的“先创建再补充”(ready-fire-aim)式的动态属性赋值,并在构造函数中一次性声明所有属性
37+
38+
function Article(opt_author) {
39+
this.title = 'Inauguration Ceremony Features Kazoo Band';
40+
this.author = opt_author;
41+
}
42+
let a1 = new Article();
43+
let a2 = new Article('Jake');
44+
45+
46+
47+
function Article() {
48+
this.title = 'Inauguration Ceremony Features Kazoo Band';
49+
this.author = 'Jake';
50+
}
51+
let a1 = new Article();
52+
let a2 = new Article();
53+
a1.author = null;
54+
55+
56+
3. 内存泄漏
57+
58+
意外声明全局变量是最常见但也最容易修复的内存泄漏问题
59+
60+
在 window 对象上创建的属性,只要 window 本身不被清理就不会消失。
61+
62+
function setName() {
63+
name = 'Jake';
64+
}
65+
66+
定时器也可能会悄悄地导致内存泄漏。
67+
68+
let name = 'Jake';
69+
setInterval(() => {
70+
console.log(name);
71+
}, 100);
72+
73+
只要定时器一直运行,回调函数中引用的 name 就会一直占用内存。
74+
75+
76+
使用 JavaScript 闭包很容易在不知不觉间造成内存泄漏。
77+
78+
let outer = function() {
79+
let name = 'Jake';
80+
return function() {
81+
return name;
82+
};
83+
};
84+
85+
86+
4. 静态分配与对象池
87+
88+
89+
注意 静态分配是优化的一种极端形式。如果你的应用程序被垃圾回收严重地拖了后腿,可以利用它提升性能。但这种情况并不多见。大多数情况下,这都属于过早优化,因此不用考虑。
90+
91+
对象更替的速度很快,从而会更频繁地安排垃圾回收。
92+
93+
一个策略是使用对象池。
94+
95+
由于没发生对象初始化,垃圾回收探测就不会发现有对象更替,因此垃圾回收程序就不会那么频繁地运行。
96+
97+
// vectorPool 是已有的对象池
98+
let v1 = vectorPool.allocate();
99+
let v2 = vectorPool.allocate();
100+
let v3 = vectorPool.allocate();
101+
v1.x = 10;
102+
v1.y = 5;
103+
v2.x = -3;
104+
v2.y = -6;
105+
addVector(v1, v2, v3);
106+
console.log([v3.x, v3.y]); // [7, -1]
107+
vectorPool.free(v1);
108+
vectorPool.free(v2);
109+
vectorPool.free(v3);
110+
// 如果对象有属性引用了其他对象
111+
// 则这里也需要把这些属性设置为 null
112+
v1 = null;
113+
v2 = null;
114+
v3 = null;
115+
116+
117+
*/

阶段十三/变量声明.js

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/**
2+
3+
ECMAScript 5.1 var
4+
5+
ES6 let 和 const
6+
7+
1. 使用 var 的函数作用域声明
8+
9+
function add(num1, num2) {
10+
var sum = num1 + num2;
11+
return sum;
12+
}
13+
let result = add(10, 20); // 30
14+
console.log(sum); // 报错:sum 在这里不是有效变量
15+
16+
17+
18+
function add(num1, num2) {
19+
sum = num1 + num2;
20+
return sum;
21+
}
22+
let result = add(10, 20); // 30
23+
console.log(sum); // 30
24+
25+
26+
var 声明会被拿到函数或全局作用域的顶部,位于作用域中所有代码之前。这个现象叫作“提升”(hoisting)
27+
28+
var name = "Jake";
29+
// 等价于:
30+
name = 'Jake';
31+
var name;
32+
33+
34+
function fn1() {
35+
var name = 'Jake';
36+
}
37+
// 等价于:
38+
function fn2() {
39+
var name;
40+
name = 'Jake';
41+
}
42+
43+
44+
console.log(name); // undefined
45+
var name = 'Jake';
46+
function() {
47+
console.log(name); // undefined
48+
var name = 'Jake';
49+
}
50+
51+
52+
2. 使用 let 的块级作用域声明
53+
54+
if (true) {
55+
let a;
56+
}
57+
console.log(a); // ReferenceError: a 没有定义
58+
while (true) {
59+
let b;
60+
}
61+
console.log(b); // ReferenceError: b 没有定义
62+
function foo() {
63+
let c;
64+
}
65+
console.log(c); // ReferenceError: c 没有定义
66+
// 这没什么可奇怪的
67+
// var 声明也会导致报错
68+
69+
70+
71+
// 这不是对象字面量,而是一个独立的块
72+
// JavaScript 解释器会根据其中内容识别出它来
73+
{
74+
let d;
75+
}
76+
77+
78+
不能声明两次 会抛出 SyntaxError 。
79+
80+
var a;
81+
var a;
82+
// 不会报错
83+
{
84+
let b;
85+
let b;
86+
}
87+
// SyntaxError: 标识符 b 已经声明过了
88+
89+
“暂时性死区”(temporal dead zone)
90+
91+
3. 使用 const 的常量声明
92+
93+
使用 const 声明的变量必须同时初始化为某个值。
94+
95+
96+
const a; // SyntaxError: 常量声明时没有初始化
97+
const b = 3;
98+
console.log(b); // 3
99+
b = 4; // TypeError: 给常量赋值
100+
101+
102+
if (true) {
103+
const a = 0;
104+
}
105+
console.log(a); // ReferenceError: a 没有定义
106+
107+
108+
while (true) {
109+
const b = 1;
110+
}
111+
console.log(b); // ReferenceError: b 没有定义
112+
function foo() {
113+
const c = 2;
114+
}
115+
console.log(c); // ReferenceError: c 没有定义
116+
{
117+
const d = 3;
118+
}
119+
console.log(d); // ReferenceError: d 没有定义
120+
121+
122+
const o1 = {};
123+
o1 = {}; // TypeError: 给常量赋值
124+
const o2 = {};
125+
o2.name = 'Jake';
126+
console.log(o2.name); // 'Jake'
127+
128+
如果想让整个对象都不能修改,可以使用 Object.freeze()
129+
130+
131+
const o3 = Object.freeze({});
132+
o3.name = 'Jake';
133+
console.log(o3.name); // undefined
134+
135+
4. 标识符查找
136+
137+
var color = 'blue';
138+
function getColor() {
139+
return color;
140+
}
141+
console.log(getColor()); // 'blue'
142+
143+
144+
var color = 'blue';
145+
function getColor() {
146+
let color = 'red';
147+
return color;
148+
}
149+
console.log(getColor()); // 'red'
150+
151+
152+
var color = 'blue';
153+
function getColor() {
154+
let color = 'red';
155+
{
156+
let color = 'green';
157+
return color;
158+
}
159+
}
160+
console.log(getColor()); // 'green'
161+
162+
163+
注意 标识符查找并非没有代价。访问局部变量比访问全局变量要快,因为不用切换作用域。不过,JavaScript 引擎在优化标识符查找上做了很多工作,将来这个差异可能就微不足道了。
164+
165+
*/
166+
167+
const o3 = Object.freeze({ age: 12 });
168+
o3.name = 'Jake';
169+
console.log(o3.name); // undefined
170+
delete o3.age
171+
console.log(o3.age) // 12

阶段十三/垃圾回收.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/**
2+
3+
执行环境负责在代码执行时管理内存。
4+
5+
通过 自动内存管理 实现 内存分配 和 闲置资源回收 。
6+
7+
基本思路很简单:确定哪个变量不会再使用,然后释放它占用的内存。
8+
9+
这个过程是周期性的,即垃圾回收程序每隔一定时间就会自动运行
10+
11+
12+
垃圾回收程序必须跟踪记录哪个变量还会使用,以及哪个变量不会再使用,以便回收内存。如何标记未使用的变量也许有不同的实现方式。
13+
14+
用到过两种主要的标记策略:标记清理和引用计数。
15+
16+
*/

阶段十三/引用计数.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
3+
垃圾回收策略是引用计数(reference counting)
4+
5+
其思路是对每个值都记录它被引用的次数。
6+
7+
声明变量并给它赋一个引用值时,这个值的引用数为 1。如果同一个值又被赋给另一个变量,那么引用数加 1。
8+
9+
如果保存对该值引用的变量被其他值给覆盖了,那么引用数减 1。当一个值的引用数为 0 时,就说明没办法再访问到这个值了,因此可以安全地收回其内存了。垃圾回收程序下次运行的时候就会释放引用数为 0 的值的内存。
10+
11+
12+
循环引用
13+
14+
function problem() {
15+
let objectA = new Object();
16+
let objectB = new Object();
17+
objectA.someOtherObject = objectB;
18+
objectB.anotherObject = objectA;
19+
}
20+
21+
*/

阶段十三/性能.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/**
2+
3+
警告 在某些浏览器中是有可能(但不推荐)主动触发垃圾回收的。在 IE 中,window. CollectGarbage()方法会立即触发垃圾回收。在 Opera 7 及更高版本中,调用 window. opera.collect()也会启动垃圾回收程序。
4+
5+
*/

0 commit comments

Comments
 (0)