
2025-01-16 日报 Day68

今日的鸡汤
衡量一个人成功的标志,不是看他登到顶峰的高度,而是看他跌到谷底的反弹力。
今日学习内容
1、JS 红皮书 P233-235 第八章:对象、类与面向对象编程
今日笔记
1、属性枚举顺序: for-in 循环、Object.keys()、Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()以及 Object.assign()在属性枚举顺序方面有很大区别。for-in 循环和 Object.keys()的枚举顺序是不确定的,取决于 JavaScript 引擎,可能因浏览器而异。
Object.getOwnPropertyNames()、Object.getOwnPropertySymbols()和 Object.assign()的枚举顺序是确定性的。先以升序枚举数值键,然后以插入顺序枚举字符串和符号键。在对象字面量中定义的键以它们逗号分隔的顺序插入。
1 | let k1 = Symbol('k1'), |
2、对象迭代: ECMAScript 2017 新增了两个静态方法,用于将对象内容转换为序列化的——更重要的是可迭代的——格式。这两个静态方法Object.values()和 Object.entries()接收一个对象,返回它们内容的数组。Object.values()返回对象值的数组,Object.entries()返回键/值对的数组。
1 | const o = { |
注意,非字符串属性会被转换为字符串输出。另外,这两个方法执行对象的浅复制:
1 | const o = { |
在这个例子中,Person.prototype 被设置为等于一个通过对象字面量创建的新对象。最终结果是一样的,只有一个问题:这样重写之后,Person.prototype 的 constructor 属性就不指向 Person了。在创建函数时,也会创建它的 prototype 对象,同时会自动给这个原型的 constructor 属性赋值。而上面的写法完全重写了默认的 prototype 对象,因此其 constructor 属性也指向了完全不同的新对象(Object 构造函数),不再指向原来的构造函数。虽然 instanceof 操作符还能可靠地返回值,但我们不能再依靠 constructor 属性来识别类型了,如下面的例子所示:
1 | let friend = new Person(); |
这里,instanceof仍然对Object和Person都返回true。但constructor属性现在等于Object而不是 Person 了。如果 constructor 的值很重要,则可以像下面这样在重写原型对象时专门设置一下它的值:
1 | function Person() { |
但要注意,以这种方式恢复 constructor 属性会创建一个[[Enumerable]]为 true 的属性。而原生 constructor 属性默认是不可枚举的。因此,如果你使用的是兼容 ECMAScript 的 JavaScript 引擎,那可能会改为使用 Object.defineProperty()方法来定义 constructor 属性:
1 | function Person() {} |