### 基本类型
string、number、boolean、null、undefined、object,除object外,其他5个均不是对象,即便`typeof null`结果为object。
### 内置对象
String、Number、Boolean、Object、Function、Array、Date、RegExp、Error
`"I am string"`本身不是对象,`"I am string" instanceof String`结果为false。获取长度、访问某个字符等字符串操作必须在String对象上操作,之所以我们能直接使用,是因为js内部帮我们将字符串转换成了String对象,Number同理。
### 内容
obj[xx]中的xx永远是字符串,即便你传入的不是也会被转换成字符串:
```
var obj = {};
obj[true] = "foo";
obj[3] = "bar";
obj[obj] = "baz";
obj["true"]; //foo
obj["3"]; //bar
obj["[object Object]"]; baz
```
你完全可以给数组绑定key value,并且可以通过key访问到value,也就是说你可以把数组当作一般对象使用(因为数组本身就是对象),但这不会影响到数组本身的数据(如果key是一个数字或字符串数字数组就会修改了):
```
var arr = [1, 2, 3];
arr.a = 4;
arr.length; //3
arr.a; //4
arr["3"] = 99;
//[1, 2, 3, 99]
arr.length; //4
arr[3]; //99
```
潜复制:复制基本类型,引用类型仍然在引用
深复制:复制整个对象
```
var obj1 = {};
var obj2 = {};
var obj = {
a: 2,
o1: obj1,
o2: obj2
}
var newObj = Object.assign({}, obj);
newObj.o1 === obj1; //true
newObj.o2 === obj2; //true
```
#### 属性描述
```
var obj = {a: 2};
Object.getOwnPropertyDescriptor(obj, "a");
//{value: 2, writable: true, enumerable: true, configurable: true}
```
你也可以使用Object.defineProperty来添加或修改属性,这个方法一般不会用到,除非修改writable(是否可以修改该属性)、enumerable(是否可以被枚举)、configurable(是否可以配置)。
```
Object.defineProperty(obj, "a", {writable: false});
obj.a = 3;
obj.a; //2
```
```
Object.defineProperty(obj, "a", {configurable: false});
Object.defineProperty(obj, "a", {configurable: true}); //TypeError,不可配,无法再修改了
delete obj.a;
obj.a; //2
//不可配置的obj属性无法被删除
```
```
var obj = {a: 1, b: 2, c: 3}
Object.defineProperty(obj, "b", {enumerable: false});
for(var key in obj) console.log(key); //a, c
```
#### 对象不变性
```
//即便使用const,对于引用类型来说仅仅是地址不变而不是内容
const obj = {a: 2, foo: [1, 2, 3]};
obj.a = 3;
obj.a; //3
obj.foo.push(4);
obj.foo; //[1, 2, 3, 4]
```
如何让a和foo不可变呢?答案是foo始终都是可变的,而a可以做到不可变
1. writable和configurable:
```
var obj = {};
Object.defineProperty(obj, "a", {value: 2, writable: false, configurable: false});
```
2. 禁止扩展 Object.preventExtensions
```
var obj = {a: 2};
Object.preventExtensions(obj);
obj.b = 3;
obj.b; //undefined
```
3. 密封 Object.seal,相当于调用了preventExtensions并且把该对象的所有属性都设置了configurable为false
4. 冻结 Object.freeze,相当于调用了seal并且把该对象的所有属性都设置了writable为false
#### Getter和Setter
使用了Getter或Setter后,js就会忽略该属性的value值以及writable是否为true,取而代之的是全部参考自getter和setter。也就是说,getter和setter会覆盖原本的对象取值和赋值操作。因此,它们两个最好是成对出现的,否则可能会出现意外行为。
```
var obj = {
get a() {return 2}
}
obj.a = 3;
obj.a; //2
```
```
var obj = {
get a() {return this._a]
set a(v) {this._a = v * 2}
}
obj.a = 2;
obj.a; //4
```
#### 存在性
in:属性、原型链都会查找
hasOwnProperty:只会查找属性
二者均检查的是属性key,而不是value
```
4 in [2, 4, 6]; //false
//key是0, 1, 2
//enumerable为false并不影响in和hasOwnProperty的结果,它仅仅是不允许枚举
//Object.keys只会将可枚举的属性push
var obj = {
a: 1,
b: 2
}
Object.defineProperty(obj, 'a', {enumerable: false});
Object.keys(obj); //['b']
Object.getOwnPropertyNames(obj); //['a', 'b']
```
### 遍历
for...in...遍历的是key
for...of...遍历的是value
- 你不知道的JS上
- 第一部分 第三章 函数作用域和块作用域
- 第一部分 第四章 提升
- 第一部分 第五章 闭包
- 第二部分 第一章 关于this
- 第二部分 第二章 this全面解析
- 第二部分 第三章 对象
- 第二部分 第五章 原型
- 第二部分 第六章 行为委托
- 你不知道的JS中
- 第一部分 第二章 值
- 第一部分 第三章 原生函数
- 第一部分 第四章 强制类型转换
- 第一部分 第五章 语法
- 第二部分 第一章 异步
- 第二部分 第三章 Promise
- 第二部分 第四章 生成器
- 第二部分 第五章 性能
- 你不知道的JS下
- 第一部分 总结
- 第二部分 第二章 语法
- 第二部分 第三章 代码组织
- 第二部分 第四章 Promise
- 第二部分 第五章 集合
- 第二部分 第六章 新增API
- 第二部分 第七章 元编程
- 第二部分 第八章 ES6之后