JavaScript 类型推断

JavaScript 的七种内置类型:

  • 空值(null)
  • 未定义(undefined)
  • 布尔值(boolean)
  • 数字(number)
  • 字符串(string)
  • 对象(object)
  • 符号(symbol,ES6 新增)

除对象之外,其他均为基本类型,对象可称为引用类型

1. 类型的判断

以下六种类型均有同名的字符串值与之对应:

typeof undefined === "undefined"; // true
typeof true === "boolean"; // true
typeof 42 === "number"; // true
typeof "42" === "string"; // true
typeof { life: 42 } === "object"; // true
typeof Symbol() === "symbol"; // true,// ES6 新加入的类型

1.1 null

通过 typeof 关键字对 null 进行取值,发现结果是 object,这是 JavaScript 一直以来的一个语言上的 BUG,也许
永远不会修复,因为修复会带来更多的问题。

这是因为不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的
二进制表示全部都是 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。

typeof null === "object"; // true

1.2 function

通过 typeof 关键字对 function 进行取值,结果是 function,但是它并不是一个内置类型,实际上是 object 的一个
子类型。概括来说,函数是可调用的对象。具体原因是它有一个内部属性 [[Call]],该属性让其可执行。

另外函数还有属性,其属性 length 就是声明的参数的个数。

typeof function a() {
  /* .. */
} === "function"; // true

1.3 array

通过 typeof 关键字对 function 进行取值,结果是 object,因为数组也是对象。准确的说是 object 的一个子类型,数组的元素是按照下表来索引,length 是元素的的个数。

所以通过 typeof 关键字无法区分出是否是数组。

typeof [1, 2, 3] === "object"; // true

1.4 通过 toString 判断类型

在任何值上调用 Object 原生的 toString() 方法,都会返回一个 [object NativeConstructorName] 格式的字符串。每个类在内部都有一个 [[Class]] 属性,这个属性中就指定了上述字符串中的构造函数名。

对于 Object 对象,直接调用 toString() 就能返回 [object Object] 。而对于其他对象,会直接返回内容的字符串,所以需要通过 call or apply 来改变 toString() 的上下文来返回正确的类型信息。

不过此方法仅支持对内置对象的判断,不能检测非原生构造函数的构造函数名。

Object.prototype.toString.call(""); // [object String]
Object.prototype.toString.call(1); // [object Number]
Object.prototype.toString.call(true); // [object Boolean]
Object.prototype.toString.call(Symbol()); //[object Symbol]
Object.prototype.toString.call(undefined); // [object Undefined]
Object.prototype.toString.call(null); // [object Null]
Object.prototype.toString.call(newFunction()); // [object Function]
Object.prototype.toString.call(newDate()); // [object Date]
Object.prototype.toString.call([]); // [object Array]
Object.prototype.toString.call(newRegExp()); // [object RegExp]
Object.prototype.toString.call(newError()); // [object Error]
Object.prototype.toString.call(document); // [object HTMLDocument]
Object.prototype.toString.call(window); //[object global] window 是全局对象 global 的引用

再通过简单的处理,就可以获得需要的类型:

const type = Object.prototype.toString.call("").slice(8, -1).toLowerCase();

2. 值和类型

JavaScript 中的变量是没有类型的,只有值才有。变量可以随时持有任何类型的值。

2.1 undefined 和 undeclared

undefined(未定义)不同于 undeclared(未声明)。

已在作用域中声明但还没有赋值的变量,是 undefined 的。相反,还没有在作用域中声明 过的变量,是 undeclared 的。

var a;
a; // undefined
b; // ReferenceError: b is not defined

对于 undeclared(或者 not defined)变量,typeof 照样返回 "undefined"。这是因为 typeof 有一个特殊的安全防范机制。

var a;
typeof a; // "undefined"
typeof b; // "undefined"

既然 typeof 有此类的安全防范机制,那么可以利用此机制来检查一些可能不存在的 undeclared 的变量,如下:

// 这样会抛出错误
if (DEBUG) {
  console.log("Debugging is starting");
}

// 这样是安全的
if (typeof DEBUG !== "undefined") {
  console.log("Debugging is starting");
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容