这里的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类型来代替。
酷客网相关文章:
评论前必须登录!
注册