犀牛书笔记(第6章 对象)
JS中,任何不是字符串、数值、符号或true、false、null、undefined的值都是对象。其中字串、数值和布尔值不是对象但是行为类似于不可修改的对象。对象的属性名可以是任意字符串包括空串(或任意符号symbol),但不能包含两个同名的属性。值可以是任何js值,或者是get、set函数。
JS的自有属性:非从原型对象上继承的属性。
除了名字和值,每个属性还有3个属性特性:writable(是否可以设置值)/enumerable(是否可以在for/in循环中遍历到该属性)/configurable(是否可以删除属性,是否可以修改属性的特性).
创建对象:
对象字面量创建:对象字面量是一个表达式,每次求值都会创建一个新的不一样的对象。
new操作符创建:后续章节再学习。
原型:通过字面量创建的对象,跟使用new Object()对象创建的对象,其原型相同,都是Object.prototype.

对于数组和日期,也有类似的逻辑:

几乎所有对象都有原型(__proto__),但只有少数对象有prototype属性,正是这些有prototype属性的对象,为所有其他对象提供了原型。
Object.create(): 创建一个新对象,使用其第一个参数来作为该新对象的原型。传入null可以创建一个没有原型的新对象。Object.create()的一个用途是防止对象被某个三方库函数意外修改。(不要把对象传给库函数,而是传入一个继承自它的对象。如果函数读取这个对象的属性,可以读到继承的值;如果设置这个对象的属性,不会影响原始对象。-》really???读到属性相关章节再来回顾了。)
查询和设置属性:
Js是关联数组:静态类型语言中(如C、C++、Java),对象只有固定数量的属性,且这些属性的名字必须事先定义。Js是动态类型语言,可以为任意对象创建任意数量的属性。不过在使用.操作符访问属性时,属性名是通过标识符来表示的,无法动态指定或者进行操作。通过方括号访问属性的时候,属性名是一个字符串,可以修改和指定。不过在ES6及之后,使用Map类更恰当了。
继承:

为对象o赋值的时候,如果o有一个名为x的自有(非继承)属性,这次赋值会修改已有x属性的值;如果没有,则会在o上创建一个名为x的新属性;如果o上有一个继承的x, 那么这个继承的属性会被新创建的属性x隐藏。如果o继承了一个名为x的只读属性则不允许赋值。
查询属性时会用到原型链,而设置属性时不影响原型链是一个重要的JavaScript特性。属性赋值要么失败要么在原始对象上创建/设置,这个规则有一个例外。如果o继承了属性x, 而x是一个通过设置方法定义的访问器属性,那么会调用该设置方法而不是在o上创建新的x。

删除属性:
delete操作符只删除自有属性,不删除继承属性。
delete不会删除configurable特性为false的属性。严格模式下删除这样的对象属性会导致TypeError.
测试属性:
in: 对自由属性和继承属性都成立。in 和 属性 !== undefined 有一个区别:let x = {a: undefined}, ‘a’ in x 返回true, 但!==undefined返回false.
hasOwnProperty(): 只在存在该自有属性的时候返回true。
propertyIsEnumerable(): 传入的是自有属性且enumerable特性为true, 方法返回true。
枚举属性:

枚举对象自有属性的顺序:

扩展对象:
Object.assign()接收两个或多个对象作为其参数。它会修改并返回第一个参数,第一个参数是target,第二个及以后参数是source。会把每个source里的可枚举自有属性复制到target里。按照参数列表顺序逐个处理source, 第一个source的属性会覆盖tafget的同名属性,第二个source的属性会覆盖第一个source的同名属性,etc.
序列化对象:
JSON.stringify()/ JSON.parse()
可以序列化、恢复的值包括,对象、数组、字符串、有限数值、true、false、null.
NaN和Infinity/-Infinity会被序列化为null. Date会被序列化为ISO格式的日期字符串。函数、RegExp、Error以及undefined值不能被序列化或恢复。
JSON.stringify()只序列化对象的可枚举自有属性。如果属性值无法序列化,该属性会从输出字符串中删除。
对象方法:
toString(): 略
toLocalString(): Date和Number定义了自己的toLocalString, 用于本地化日期时间和数值。数组的toLocalString是调用每个元素的toLocalString。
valueOf(): 把对象转为非字符串原始值。如果在需要原始值的上下文中使用了对象,js会自动调用这个对象的valueOf方法。
toJSON(): 供JSON.stringify()调用。
对象字面量扩展语法:
简写属性:let o = {x, y}; 相当于let o = { x: x, y:y}
计算属性名:
const PROPERTY_NAME = "p1";
function compute() {
return "p" + 2;
}
let p = {
[PROPERTY_NAME]: 1,
[compute()]: 2
}
symbol属性名:
symbol类型除了作为属性名,做不了其他事。创造符号使用Symbol()工厂函数(它不是构造函数,因为symbol是原始值,不能用new调用)。
扩展操作符:… 对象字面量里有效的特殊语法


简写方法:对象字面量允许在定义方法时只写方法名加括号
let s = {
area() { return ...;},
a: 0
}
属性的getter和setter:
除了数据属性,对象还可以有访问器属性,getter和setter。如果一个属性既有getter也有setter, 则该属性是一个可读写属性。如果只有getter, 只读,如果只有setter, 只写(读取始终是undefined )。访问器属性的方法名就是属性名,加前缀get/set.