javascript 高级程序设计 第四版 学习笔记 1

for in 和 for of的区别

先来看for-in的定义:for-in 语句是一种严格的迭代语句,用于枚举对象中的非符号键属性。

a = [‘a’,’b’,’c’]

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
for (const i in a){
console.log(i)
}

for (const i of a){
console.log(i)
}

o = {
'a':1,
'b':2,
'c':3,
[x]: 'test'
}

for (const i in o){
console.log(i)
}
-----------
0
1
2
a
b
c
a
b
c

而 for-of 针对的是实现了迭代协议的可迭代对象的遍历,也就是说,for-of只能作用于可迭代对象,如果没有实现迭代协议,那么将会引发错误:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
o = {
'a':1,
'b':2,
'c':3,
[x]: 'test'
}

for (const i of o){
console.log(i)
}
-----
for (const i of o){
^

TypeError: o is not iterable

如果实现了迭代器的对象,那么可以正常地输出结果:

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
lass Mimo {
constructor(limit) {
this.count = 1;
this.limit = limit;
}

[Symbol.iterator]() {
let count = 1,
limit = this.limit;
return {
next() {
if (count < limit) {
return { done: false, value: count++ }
}
else {
return { done: true, value: undefined }
}
}
}
}
}

let mimo = new Mimo(3);

for (let i of mimo) {
console.log(i);
}
---------
1
2

变量类型

ECMAScript的变量有两种类型,原始值(primitive value)和引用类型(reference value)。原始值有6种类型:

  • Undefined
  • Null
  • Boolean
  • Number
  • String
  • Symbol

这6种原始值是按值存储的,我们访问的就是它存储在变量中的实际值。

引用类型与原生类型不同,操作引用类型实际是是操作的该对象的引用。原始类型的初始化可以只使用原始字面量形式。如果使用的是new 关键字,则JavaScript 会创建一个Object 类型的实例,但其行为类似原始值。

1
2
3
4
5
6
7
8
9
10
11

let a = "abc";
let b = new String("abc")

a.name = "ABC"
b.name = "ABC"

console.log(a.name)
console.log(b.name)
console.log(typeof a)
console.log(typeof b)

原始值包装类型

之前我们碰到这样一个问题:

为什么1.2.toString() 可以直接转换成”1.2”,而 1.toString不可以转换成”1”,除了编译器识别的问题外,你有没有想过1.2 是原始值类型,为什么原始值类型可以直接调用toString方法呢?

实际上,javascript在处理1.2.toString()的过程中,先对1.2进行了包装,让它变成了包装对象,然后调用了对象的toString()方法,类似于下面的代码:

1
2
let s1 =  1.2;
let s2 = new String(s1);

但是它与引用类型的区别在于对象的生命周期,通过new实例化的引用类型会在实例离开作用域之后被销毁,而包装类型只存在于访问它的那行代码执行期间,这样就意味着不能在运行时给原始值添加属性。

1
2
3
let s1 = "some text";
s1.color = "red";
console.log(s1.color);// undefined.

这里的s1实际上是没有color属性的。

内置单例对象

ECMA-262 对内置对象的定义是“任何由ECMAScript 实现提供、与宿主环境无关,并在ECMAScript程序开始执行时就存在的对象”。这就意味着,开发者不用显式地实例化内置对象,因为它们已经实例化好了。前面我们已经接触了大部分内置对象,包括Object、Array 和String。

Global对象

Global是ECMAScript种最特别的对象,因为代码不会特别的访问它。CMA-262 规定Global对象为一种兜底对象,它所针对的是不属于任何对象的属性和方法。

你的支持我的动力