JavaScript 类型

最后更新于:2022-04-01 22:25:25

{% raw %} ## JavaScript 类型 强烈建议你去使用编译器. 如果使用 JSDoc, 那么尽量具体地, 准确地根据它的规则来书写类型说明. 目前支持两种[JS2](http://wiki.ecmascript.org/doku.php?id=spec:spec)和 JS1.x 类型规范. ### JavaScript 类型语言 JS2 提议中包含了一种描述 JavaScript 类型的规范语法, 这里我们在 JSDoc 中采用其来描述函数参数和返回值的类型. JSDoc 的类型语言, 按照 JS2 规范, 也进行了适当改变, 但编译器仍然支持旧语法. | 名称 | 语法 | 描述 | 弃用语法 | | --- | --- | --- | --- | | 普通类型 | `{boolean}`, `{Window}`, `{goog.ui.Menu}` | 普通类型的描述方法. | | | 复杂类型 | `{Array.}` 字符串数组. `{Object.}` 键为字符串, 值为整数的对象类型. | 参数化类型, 即指定了该类型中包含的一系列”类型参数”. 类似于 Java 中的泛型. | | | 联合类型 | `{(number|boolean)}` 一个整数或者布尔值. | 表示其值可能是 A 类型, 也可能是 B 类型 | `{(number,boolean)}`, `{number|boolean}`, `{(number||boolean)}` | | 记录类型 | `{{myNum: number, myObject}}` 由现有类型组成的类型. | 表示包含指定成员及类型的值. 这个例子中, `myNum` 为 `number` 类型, `myObject` 为任意类型. 注意大括号为类型语法的一部分. 比如, `Array.<{length}>`, 表示一具有 `length` 属性的 `Array` 对象. | | | 可为空类型 | `{?number}`一个整型数或者为 NULL | 表示一个值可能是 A 类型或者 `null`.默认, 每个对象都是可为空的. 注意: 函数类型不可为空. | `{number?}` | | 非空类型 | `{!Object}`一个对象, 但绝不会是 `null` 值. | 说明一个值是类型 A 且肯定不是 null.默认情况下, 所有值类型 (boolean, number, string, 和 undefined) 不可为空. | `{Object!}` | | 函数类型 | `{function(string, boolean)}`具有两个参数 ( string 和 boolean) 的函数类型, 返回值未知. | 说明一个函数. | | | 函数返回类型 | `{function(): number}`函数返回一个整数. | 说明函数的返回类型. | | | 函数的 `this` 类型 | `{function(this:goog.ui.Menu, string)}`函数只带一个参数 (string), 并且在上下文 goog.ui.Menu 中执行. | 说明函数类型的上下文类型. | | | 可变参数 | `{function(string, ...[number]): number}`带一个参数 (字符类型) 的函数类型, 并且函数的参数个数可变, 但参数类型必须为 number. | 说明函数的可变长参数. | | | 可变长的参数 (使用 `@param` 标记) | `@param {...number} var_args`函数参数个数可变. | 使用标记, 说明函数具有不定长参数. | | | 函数的 [缺省参数](http://docs.kissyui.com/docs/html/styleguide/google/optional) | `{function(?string=, number=)}` 函数带一个可空且可选的字符串型参数, 一个可选整型参数. `=` 语法只针对 `function` 类型有效. | 说明函数的可选参数. | | | 函数 [可选参数](http://docs.kissyui.com/docs/html/styleguide/google/optional) (使用 `@param` 标记) | `@param {number=} opt_argument` `number`类型的可选参数. | 使用标记, 说明函数具有可选参数. | | | 所有类型 | `{*}` | 表示变量可以是任何类型. | | ### JavaScript中的类型 #### `number` ``` 1 1.0 -5 1e5 Math.PI ``` #### `Number` [数值对象](http://bq69.com/blog/articles/script/868/google-javascript-style-guide.html#Wrapper_objects_for_primitive_types) ``` new Number(true) ``` #### `string` 字符串值 ``` 'Hello' "World" String(42) ``` #### `String` [字符串对象](http://bq69.com/blog/articles/script/868/google-javascript-style-guide.html#Wrapper_objects_for_primitive_types) ``` new String('Hello') new String(42) ``` #### `boolean` 布尔值 ``` true false Boolean(0) ``` #### `Boolean` [布尔对象](http://bq69.com/blog/articles/script/868/google-javascript-style-guide.html#Wrapper_objects_for_primitive_types) ``` new Boolean(true) ``` #### `RegExp` ``` new RegExp('hello') /world/g ``` #### `Date` ``` new Date new Date() ``` #### `null` ``` null ``` #### `undefined` ``` undefined ``` #### `void` 没有返回值 ``` function f() { return; } ``` #### `Array` 类型不明确的数组 ``` ['foo', 0.3, null] [] ``` #### `Array.` ``` [11, 22, 33] ``` #### `Array.>` ``` Array.> ``` #### `Object` ``` {} {foo: 'abc', bar: 123, baz: null} ``` #### `Object.` ``` {'foo': 'bar'} ``` #### `Object.` 键为整数, 值为字符串的对象. 注意, JavaScript 中, 键总是被转换成字符串, 所以 `obj['1'] == obj[1]`. 也所以, 键在 for…in 循环中是字符串类型. 但在编译器中会明确根据键的类型来查找对象. ``` var obj = {}; obj[1] = 'bar'; ``` #### `Function` [函数对象](http://bq69.com/blog/articles/script/868/google-javascript-style-guide.html#Wrapper_objects_for_primitive_types) ``` function(x, y) { return x * y; } ``` #### `function(number, number): number` 函数值 ``` function(x, y) { return x * y; } ``` #### `SomeClass` ``` /** @constructor */ function SomeClass() {} new SomeClass(); ``` #### `SomeInterface` ``` /** @interface */ function SomeInterface() {} SomeInterface.prototype.draw = function() {}; ``` #### `project.MyClass` ``` /** @constructor */ project.MyClass = function () {} new project.MyClass() ``` #### `project.MyEnum` 枚举 ``` /** @enum {string} */ project.MyEnum = { BLUE: '#0000dd', RED: '#dd0000' }; ``` #### `Element` DOM 中的元素 ``` document.createElement('div') ``` #### `Node` DOM 中的节点. ``` document.body.firstChild ``` #### `HTMLInputElement` DOM 中, 特定类型的元素. ``` htmlDocument.getElementsByTagName('input')[0] ``` ### 可空 vs. 可选 参数和属性 JavaScript 是一种弱类型语言, 明白可选, 非空和未定义参数或属性之间的细微差别还是很重要的. 对象类型(引用类型)默认非空. 注意: 函数类型默认不能为空. 除了字符串, 整型, 布尔, undefined 和 null 外, 对象可以是任何类型. ``` /** * Some class, initialized with a value. * @param {Object} value Some value. * @constructor */ function MyClass(value) { /** * Some value. * @type {Object} * @private */ this.myValue_ = value; } ``` 告诉编译器 `myValue_` 属性为一对象或 null. 如果 `myValue_` 永远都不会为 null, 就应该如下声明: ``` /** * Some class, initialized with a non-null value. * @param {!Object} value Some value. * @constructor */ function MyClass(value) { /** * Some value. * @type {!Object} * @private */ this.myValue_ = value; } ``` 这样, 当编译器在代码中碰到 `MyClass` 为 null 时, 就会给出警告. 函数的可选参数可能在运行时没有定义, 所以如果他们又被赋给类属性, 需要声明成: ``` /** * Some class, initialized with an optional value. * @param {Object=} opt_value Some value (optional). * @constructor */ function MyClass(opt_value) { /** * Some value. * @type {Object|undefined} * @private */ this.myValue_ = opt_value; } ``` 这告诉编译器 `myValue_` 可能是一个对象, 或 null, 或 undefined. 注意: 可选参数 `opt_value` 被声明成 `{Object=}`, 而不是 `{Object|undefined}`. 这是因为可选参数可能是 undefined. 虽然直接写 undefined 也并无害处, 但鉴于可阅读性还是写成上述的样子. 最后, 属性的非空和可选并不矛盾, 属性既可是非空, 也可是可选的. 下面的四种声明各不相同: ``` /** * Takes four arguments, two of which are nullable, and two of which are * optional. * @param {!Object} nonNull Mandatory (must not be undefined), must not be null. * @param {Object} mayBeNull Mandatory (must not be undefined), may be null. * @param {!Object=} opt_nonNull Optional (may be undefined), but if present, * must not be null! * @param {Object=} opt_mayBeNull Optional (may be undefined), may be null. */ function strangeButTrue(nonNull, mayBeNull, opt_nonNull, opt_mayBeNull) { // ... }; ``` {% endraw %}
';