直接访问原型的现代方法

Object.create(proto, [descriptors]) (ES5)

一、Object.create(proto, [descriptors])—— 利用给定的proto作为[[Prototype]]和可选的属性描述来创建一个空对象。
二、Object.create有一个可选的第二参数:属性描述器。我们可以在此处为新对象提供额外的属性,就像这样:

  1. let animal = {
  2. eats: true
  3. };
  4. let rabbit = Object.create(animal, {
  5. jumps: {
  6. value: true
  7. }
  8. });
  9. alert(rabbit.jumps); // true

创建对象

一、该方法主要用于创建一个新对象,并为其设置原型,用(上述)属性描述符来定义对象的原型属性。

  1. var parent = {hi: 'Hello'};
  2. var o = Object.create(parent, {
  3. prop: {
  4. value: 1
  5. }
  6. });
  7. o.hi; // 'Hello'
  8. // 获得它的原型
  9. Object.getPrototypeOf(parent) === Object.prototype; // true 说明parent的原型是Object.prototype
  10. Object.getPrototypeOf(o); // {hi: "Hello"} // 说明o的原型是{hi: "Hello"}
  11. o.hasOwnProperty('hi'); // false 说明hi是原型上的
  12. o.hasOwnProperty('prop'); // true 说明prop是原型上的自身上的属性。

创建空白对象

一、我们可以用它来创建一个完全空白的对象,这样的事情在ES3中可是做不到的。

  1. var o = Object.create(null);
  2. typeof o.toString(); // 'undefined'

克隆对象

一、Object.create提供了一种简单的方式来浅拷贝一个对象的所有描述符:

  1. let clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));

1、此调用可以对obj进行真正准确地拷贝,包括所有的属性:可枚举和不可枚举的,数据属性和 setters/getters —— 包括所有内容,并带有正确的[[Prototype]]。

Object.getPrototypeOf(obj)

一、返回对象obj的[[Prototype]](与proto的 getter 相同)。

Object.setPrototypeOf(obj, proto)

将对象obj的[[Prototype]]设置为proto(与proto的 setter 相同)。

Object.keys,values,entries

一、对于普通对象,下列这些方法是可用的:

  • Object.keys(obj):返回一个包含该对象所有的键的数组。
  • Object.values(obj): 返回一个包含该对象所有的值的数组。
  • Object.entries(obj):返回一个包含该对象所有 [key, value] 键值对的数组。

二、但是注意区别(比如说跟 map 的区别):

Map Object
调用语法 map.keys() Object.keys(obj),而不是obj.keys()
返回值 可迭代项 “真正的”数组

1、第一个区别是,对于对象我们使用的调用语法是Object.keys(obj),而不是obj.keys()。
(1)为什么会这样?主要原因是灵活性。
① 在 JavaScript 中,对象是所有复杂结构的基础。
② 因此,我们可能有一个自己创建的对象,比如data,并实现了它自己的data.values()方法。同时,我们依然可以对它调用Object.values(data)方法。
2、第二个区别是Object.*方法返回的是“真正的”数组对象,而不只是一个可迭代项。这主要是历史原因。
举个例子:

  1. let user = {
  2. name: "John",
  3. age: 30
  4. };
  5. // 将下面的值console.log()出来
  6. Object.keys(user) // ["name", "age"]
  7. Object.values(user) // ["John", 30]
  8. Object.entries(user) // [ ["name","John"], ["age",30] ]

【示例1】使用Object.values来遍历属性值

  1. let user = {
  2. name: "John",
  3. age: 30
  4. };
  5. // 遍历所有的值
  6. for (let value of Object.values(user)) {
  7. alert(value); // John, then 30
  8. }

三、Object.keys/values/entries 会忽略 symbol 属性
1、就像for..in循环一样,这些方法会忽略使用Symbol(…)作为键的属性。
2、通常这很方便。但是,如果我们也想要 Symbol 类型的键:
① 那么这儿有一个单独的方法Object.getOwnPropertySymbols,它会返回一个只包含 Symbol 类型的键的数组。
② 另外,还有一种方法Reflect.ownKeys(obj),它会返回所有键。
四、所有返回对象属性的方法(如Object.keys及其他,都只返回“自身”的属性,都会忽略继承的属性。
1、它们只会对对象自身进行操作。不考虑继承自原型的属性。
2、如果我们想继承它们,我们可以使用for…in。

转换对象

一、对象缺少数组存在的许多方法,例如map和filter等。
二、如果我们想应用它们,那么我们可以使用Object.entries,然后使用Object.fromEntries:

  1. 使用Object.entries(obj)从obj获取由键/值对组成的数组。
  2. 对该数组使用数组方法,例如map。
  3. 对结果数组使用Object.fromEntries(array)方法,将结果转回成对象。

【示例1】我们有一个带有价格的对象,并想将它们加倍:

  1. let prices = {
  2. banana: 1,
  3. orange: 2,
  4. meat: 4,
  5. };
  6. let doublePrices = Object.fromEntries(
  7. // 转换为数组,之后使用 map 方法,然后通过 fromEntries 再转回到对象
  8. Object.entries(prices).map(([key, value]) => [key, value * 2])
  9. );
  10. alert(doublePrices.meat); // 8

Object.getOwnPropertySymbols(obj)

一、返回一个由自身所有的 symbol 类型的键组成的数组。

Object.getOwnPropertyNames(obj)

一、返回一个由自身所有的字符串键组成的数组。

Reflect.ownKeys(obj)

一、返回一个由自身所有键组成的数组。

Object.prototype.hasOwnProperty(propName) / obj.hasOwnProperty(key)

一、语法

  1. object.hasOwnProperty(proName)
  • 参数object是必选项。一个对象的实例。
  • proName是必选项。一个属性名称的字符串值

二、如果obj拥有名为key的自身的属性(非继承而来的),则返回true。当该属性是从原型链中继承而来或者根本不存在时,返回false
1、此方法无法检查该对象的原型链中是否具有该属性。

| 【示例】```javascript var o = {prop:1}; o.hasOwnProperty(‘prop’); // true o.hasOwnProperty(‘toString’); // false o.hasOwnProperty(‘formString’); // false

  1. |
  2. | --- |
  3. | 【示例】antdInput.Search,点击搜索图标、清除图标、按下回车键时都会触发onSearch事件,这时可以根据事件类型做不同的处理。<br />1、直接打印event.type,都是click。查看控制台发现点击搜索图标的event.type是继承来的<br />2Object.keys()打印出不同类型的自身属性```javascript
  4. console.log(Object.keys(event))
  5. // 点击清空
  6. ["target", "currentTarget"]
  7. // 点击搜索
  8. ["_reactName", "_targetInst", "type", "nativeEvent", "target", "currentTarget", "eventPhase", "bubbles", "cancelable", "timeStamp", "defaultPrevented", "isTrusted", "view", "detail", "screenX", "screenY", "clientX", "clientY", "pageX", "pageY", "ctrlKey", "shiftKey", "altKey", "metaKey", "getModifierState", "button", "buttons", "relatedTarget", "movementX", "movementY", "isDefaultPrevented", "isPropagationStopped"]
  9. // 按下回车
  10. ["_reactName", "_targetInst", "type", "nativeEvent", "target", "currentTarget", "eventPhase", "bubbles", "cancelable", "timeStamp", "defaultPrevented", "isTrusted", "view", "detail", "key", "code", "location", "ctrlKey", "shiftKey", "altKey", "metaKey", "repeat", "locale", "getModifierState", "charCode", "keyCode", "which", "isDefaultPrevented", "isPropagationStopped"]

3、发现点击搜索图标、按下回车键有自身的type属性,所以可以根据这点来满足需求:如果内容为空,则提示```javascript const onSearch = (value, event) => { console.log(‘event:’, event) console.log(‘event.type:’, event.type) console.log(‘event,hasOwnProperty:’, event.hasOwnProperty(‘type’)); console.log(‘event,keys:’, Object.keys(event));

if (!value) { if (event.hasOwnProperty(‘type’)) { message.error(‘请输入类目名称’) } return; } // changeItem(value); }; ``` | | —- |

Object.is()

见比较运算符#Object.is():https://www.yuque.com/tqpuuk/yrrefz/wza8dh#D516R