TypeScript Object类型

这里的Object指的是Object类型,而不是JavaScript内置的“Object()”构造函数。请朋友们一定要注意区分这两者,Object类型表示一种类型,而“Object()”构造函数则表示一个值。因为“Object()”构造函数是一个值,因此它也有自己的类型。但要注意的是,“Object()”构造函数的类型不是Object类型

为了更好地理解Object类型,让我们先了解一下“Object()”构造函数。

JavaScript提供了内置的“Object()”构造函数来创建一个对象。示例如下:

const obj = new Object();

在实际代码中,使用“Object()”构造函数来创建对象的方式并不常用。在创建对象时,我们通常会选择使用更简洁的对象字面量。

虽然不常使用“Object()”构造函数来创建对象,但是“Object()”构造函数提供了一些非常常用的静态方法,例如“Object.assign()”方法和“Object.create()”方法等。

接下来,让我们深入分析一下TypeScript源码中对“Object()”构造函数的类型定义。下面仅摘取一部分着重关注的类型定义:

interface ObjectConstructor {

   readonly prototype: Object;

   // 省略了其他成员
}

declare var Object: ObjectConstructor;

由该定义能够直观地了解到“Object()”构造函数的类型是ObjectConstructor类型而不是Object类型,它们是不同的类型。第3行,prototype属性的类型为Object类型。

构造函数的prototype属性值决定了实例对象的原型。此外,“Object.prototype”是一个特殊的对象,它是JavaScript中的公共原型对象。也就是说,如果程序中没有刻意地修改一个对象的原型,那么该对象的原型链上就会有“Object.prototype”对象,因此也会继承“Object.prototype”对象上的属性和方法。

现在,我们可以正式地引出Object类型。Object类型是特殊对象“Object.prototype”的类型,该类型的主要作用是描述JavaScript中几乎所有对象都共享(通过原型继承)的属性和方法。

Object类型的具体定义如下所示(取自TypeScript源码):

interface Object {
   /**
    * The initial value of Object.prototype.constructor
    * is the standard built-in Object constructor.
    */
   constructor: Function;

   /**
    * Returns a string representation of an object.
    */
   toString(): string;

   /**
    * Returns a date converted to a string using the
    * current locale.
    */
   toLocaleString(): string;

   /**
    * Returns the primitive value of the specified object.
    */
   valueOf(): Object;

   /**
    * Determines whether an object has a property with
    * the specified name.
    * @param v A property name.
    */
   hasOwnProperty(v: PropertyKey): boolean;

   /**
    * Determines whether an object exists in another
    * object's prototype chain.
    */
   isPrototypeOf(v: Object): boolean;

   /**
    * Determines whether a specified property is enumerable.
    * @param v A property name.
    */
   propertyIsEnumerable(v: PropertyKey): boolean;
}

通过该类型定义能够了解到,Object类型里定义的方法都是通用的对象方法,如“valueOf()”方法。

类型兼容性

Object类型有一个特点,那就是除了undefined值和null值外,其他任何值都可以赋值给Object类型。示例如下:

let obj: Object;

// 正确
obj = { x: 0 };
obj = true;
obj = 'hi';
obj = 1;

// 编译错误
obj = undefined;
obj = null;

对象能够赋值给Object类型是理所当然的,但为什么原始值也同样能够赋值给Object类型呢?实际上,这样设计正是为了遵循JavaScript语言的现有行为。

当在原始值上调用某个方法时,JavaScript会对原始值执行封箱操作,将其转换为对象类型,然后再调用相应方法。Object类型描述了所有对象共享的属性和方法,而JavaScript允许在原始值上直接访问这些方法,因此TypeScript允许将原始值赋值给Object类型。示例如下:

'str'.valueOf();

const str: Object = 'str';
str.valueOf();

常见错误

在使用Object类型时容易出现的一个错误是,将Object类型应用于自定义变量、参数或属性等的类型。示例如下:

const point: Object = { x: 0, y: 0 };

此例中,将常量point的类型定义为Object类型。虽然该代码不会产生任何编译错误,但它是一个明显的使用错误。原因刚刚介绍过,Object类型的用途是描述“Object.prototype”对象的类型,即所有对象共享的属性和方法。

在描述自定义对象类型时有很多更好的选择,完全不需要使用Object类型,例如接下来要介绍的object类型和对象字面量类型等。在TypeScript官方文档中也明确地指出了不应该使用Object类型,而是应该使用object类型来代替。

酷客网相关文章:

赞(0)

评论 抢沙发

评论前必须登录!