美文网首页
阮一峰JS教程读后感(六)标准库-Object、属性描述对象

阮一峰JS教程读后感(六)标准库-Object、属性描述对象

作者: 前端艾希 | 来源:发表于2019-06-24 19:14 被阅读0次

一、Object对象

JavaScript 原生提供Object对象(注意起首的O是大写),本章介绍该对象原生的各种方法。

JavaScript 的所有其他对象都继承自Object对象,即那些对象都是Object的实例。

1. Object对象的作用

  1. 判断一个变量是否为对象,因为Object()会将传入的参数包装为一个对象,如果变量没有发生变化那么就说明该变量为对象,如果发生变化就说明该变量不是对象。
function isObject(value) {
  return value === Object(value);
}

isObject([]) // true
isObject(true) // false
  1. 可以被当做构造函数使用,如果接受的参数为一个对象,那么直接返回该对象,如果接收到的是一个原始类型的值,那么就返回一个包装对象。
var o1 = {a: 1};
var o2 = new Object(o1);
o1 === o2 // true

var obj = new Object(123);
obj instanceof Number // true

2. Object.keys 和 Object.getOwnPropertyNames的区别

Object.getOwnPropertyNames 可返回对象的不可枚举对象,而Object.keys只能返回可枚举对象,所以Object.keys可以用来统计对象的属性。

var a = ['Hello', 'World'];

Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]

Object.keys(a).length  // 2 统计对象的属性个数

3. 使用Object.prototype.toString构造更准确的变量类型判断函数

var type = function (o){
  var s = Object.prototype.toString.call(o);
  return s.match(/\[object (.*?)\]/)[1].toLowerCase();
};

type({}); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regex"
type(new Date()); // "date"

4. Object的静态方法

除了上面介绍的方法外,Object还有不少其他的静态方法

(1)对象属性模型的相关方法

  • Object.getOwnPropertyDescriptor():获取某个属性的描述对象。
  • Object.defineProperty():通过描述对象,定义某个属性。
  • Object.defineProperties():通过描述对象,定义多个属性。

(2)控制对象状态的方法

  • Object.preventExtensions():防止对象扩展。
  • Object.isExtensible():判断对象是否可扩展。
  • Object.seal():禁止对象配置。
  • Object.isSealed():判断一个对象是否可配置。
  • Object.freeze():冻结一个对象。
  • Object.isFrozen():判断一个对象是否被冻结。

(3)原型链相关方法

  • Object.create():该方法可以指定原型对象和属性,返回一个新的对象。
  • Object.getPrototypeOf():获取对象的Prototype对象。

5. Object的实例方法

除了静态方法,还有不少方法定义在Object.prototype对象。它们称为实例方法,所有Object的实例对象都继承了这些方法。
Object实例对象的方法,主要有以下六个。

  • Object.prototype.valueOf():返回当前对象对应的值。
  • Object.prototype.toString():返回当前对象对应的字符串形式。
  • Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。
  • Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
  • Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型。
  • Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。

6. 如果一个对象静态方法和实例方法重名了会产生什么后果?

本题和访问对象的方法的顺序有关,首先检查对象自身有没有该方法,然后去对象的原型中去找,如果都没有找到就会顺着原型链一直往上找。

a = new Object()
b = new Object()

b.toString = function() { console.log('update') }

a.toString  //"[object Object]"
b.toString  //update

二、属性描述对象

JavaScript 提供了一个内部数据结构,用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息。

举个例子:

var a = { name: 'zhangsan' }
//声明一个对象如a,但其实 name的属性对应的值并不是一个简单的字符串,而是一个对象
a = {
    name: {
        value: 'zhangsan'    // 值
        writable: false,     // 是否可写
        enumerable: true,    // 是否可遍历
        configurable: false, // 是否可配置
        get: undefined,      // 取值函数
        set: undefined       // 存值函数
    }
}
// name属性后面的对象称之为描述对象,保存该属性的元信息。

1. 如何去查看一个对象的某个属性的描述对象

通过Object.getOwnPropertyDescriptor()方法可以获取属性描述对象。它的第一个参数是目标对象,第二个参数是一个字符串,对应目标对象的某个属性名。

var obj = { p: 'a' };

Object.getOwnPropertyDescriptor(obj, 'p')
// Object { value: "a",
//   writable: true,
//   enumerable: true,
//   configurable: true
// }

2. 如何修改属性描述对象

Object.defineProperty()方法允许通过属性描述对象,定义或修改一个属性,然后返回修改后的对象,它的用法如下。

var obj = Object.defineProperty({}, 'p', {
  value: 123,
  writable: false,
  enumerable: true,
  configurable: false
});

obj.p // 123

obj.p = 246;
obj.p // 123

3. 如何拷贝一个对象

需要注意的是用 in 循环对象时可能会把不属于该对象本身的属性遍历了,所以需要注意使用 hasOwnProperty来验证该属性是否属于该对象,然后如果使用赋值语句对属性的值进行拷贝,那么也只能拷贝值而不能拷贝其描述对象,如何解决这个问题,请看示例代码:

var extend = function (to, from) {
  for (var property in from) {
    if (!from.hasOwnProperty(property)) continue;
    Object.defineProperty(
      to,
      property,
      Object.getOwnPropertyDescriptor(from, property)
    );
  }
  return to;
}

extend({}, { get a(){ return 1 } })

相关文章

网友评论

      本文标题:阮一峰JS教程读后感(六)标准库-Object、属性描述对象

      本文链接:https://www.haomeiwen.com/subject/gmqaqctx.html