Live Note

Remain optimistic

ES6 中,为了保持兼容性,var 和 function 声明的全局变量依旧是顶层对象的属性

1
2
3
4
var a = 1 //如果在 Node 的 REPL 环境,可以写成 global.a 或者 this.a
window.a //1
let b = 1
window.b //undefined

global 对象

  • 在浏览器对象中,顶层对象是 window,但 Node 和 Web Worker 没有 window。
  • 在浏览器和 Web Worker 中,self 也指向顶层对象,但 Node 没有 self。
  • 在 Node 中,顶层对象是 global,但其他环境都不支持。

以下为两种勉强可以取到顶层对象的方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//方法一
typeof window !== "undefined"
? window
: typeof process === "object" &&
typeof require === "function" &&
typeof global === "object"
? global
: this
//方法二
var getGlobal = function () {
if (typeof self !== "undefined") {
return self
}
if (typeof window !== "undefined") {
return window
}
if (typeof global !== "undefined") {
return global
}
throw new Error("unalbe to locate global object")
}

一旦声明,值不可变

1
2
const PI = 3.14
PI = 3 //TypeError: Assignment to constant variable.

只声明不赋值也会报错。

1
const foo; //SyntaxError: Missing initializer in const declaration

实质为变量指向的内存地址不可变动

const 只能保证这个指针是固定的,不能控制数据结构的变化。

1
2
3
const foo = {}
foo.prop = 123 //Success
foo = {} //TypeError: 'foo' is read-only

对象冻结方法

使用 Object.freeze 函数,冻结对象

1
const foo = Object.freeze({})

冻结属性的函数

1
2
3
4
5
6
7
8
var makeConstant = (obj) => {
Object.freeze(obj)
Object.keys(obj).forEach((key, i) => {
if (typeof obj[key] === "object") {
makeConstant(obj[key])
}
})
}

let 声明的变量在代码块内有效

1
2
3
4
5
6
7
var a [];
for (let i = 0; i < 10; i++) {
a[i] = function() {
console.log(i);
};
}
a[6](); //6

不存在变量提升

var 命令的变量可以在声明之前使用,值为 undefined

暂时性死区

在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。TDZ(temporal dead zone)

1
2
3
4
5
var temp = 123
if (true) {
temp = "abc" //ReferenceError
let temp
}

有些死区是不易发现的

1
2
3
4
5
function bar(x = y, y = 2) {
//y is not defined
return [x, y]
}
let x = x //ReferenceError: x is not defined

不允许重复声明

1
2
3
4
function foo() {
var a
let a
}

某日被书中一段代码误导

1
2
3
4
5
6
7
8
9
10
11
var promise = new Promise(function (resolve, reject) {
resolve("ok")
setTimeout(function () {
throw new Error("test")
}, 0)
})
promise.then(function (value) {
console.log(value)
})
//ok
//Uncaught Error : test

由于前面还有这样一段话

如果 Promise 状态已经变成 Resolved,再抛出错误是无效的。

当时看到这,思索了许久,为什么已经 resolve 了这个 ERROR 还是可以往外抛出呢?
后面发现,settimeout 是一个异步函数,throw 会在下一轮事件循环开始时抛出,所以无论是否 resolve,这个 ERROR 都是会抛出的。

开坑第一篇

从大学开始就想着弄一篇自己的博客,但是一直都断断断续的。
在这个风雨交加的午间,我决定开坑了。
可能以后主要还是用于记笔记之类的吧,偶尔应该也会写点杂七杂八的东西。。