JS 中的变量
基本类型变量
- number
- string
- boolean
- null
- undefined
- symbol
- bigint
基本数据类型所占空间比较小且大小固定,存储在栈中。
对于基本类型的赋值会重新在栈中开辟一片内存空间,将被赋值的变量的值拷贝一份,两个变量会不影响,修改其中一个的值不会影响另一个
引用类型变量
object、function、array
引用类型所占的空间大小一般较大而且不固定,所以在栈中存储的是其指针,而引用类型的值存储在堆中。
对于引用类型的赋值其实赋值的是指针,所以修改一个变量的属性会影响另一个变量
typeof
返回值为字符串
- 'number'
- 'string'
- 'boolean'
- 'function'
- 'undefined'
- 'object' - object、null、array
- 'symbol'
- 'bigint'
总结
- typeof 对于除 null 之外的基本数据类型都可以返回其正确的类型字符串
- null 会返回 'object'
- 对于除 function 之外的引用类型都返回 'object'
- function 会返回 'function'
typeof 为什么会对 null 返回'object'
JavaScript 在最初设计的时候,其中的值由表示其类型的标签和真正的值组成。
对象的标签是 0,而 null 表示的是空指针,在大多数平台上的值都是 0x00。
因此 null 的标签是 0
所以 typeof null 返回的是 'object'
instanceof
A instanceof B
判断 A 是不是 B 的实例,也就是 A 的原型链上是否有 B 的原型
A 如果不是对象则直接返回 false;B 如果不是函数直接报错
但是需要注意的是它并不能精确的判断其类型;instanceof 默认只有一个全局上下文,加入一个页面中有多个框架,则就会有多个全局上下文,也就会有多个构造函数。如果你将一个数组从一个框架传递给另一个框架的时候,则它和在另一个框架中直接定义的数组并不属于同一个构造函数
针对数组的这个问题,有一个 Array.isArray 的方法,它判断一个变量是不是数组,而且它不会区分全局环境,它判断的是变量的[[Class]]的值,它的值为[object Xxx] Xxx 就是他的类型。对于数组而言就是[object Array]
function myInstanceOf(left, right) {
left = left.__proto__;
let rightProto = right.prototype;
while (true) {
if (left == null) return false;
if (left === rightProto) return true;
left = left.__proto__;
}
}
Object.prototype.toString
对于除数组和函数之外的引用类型,直接调用 toString 返回的就是其[[Class]]属性的值([object Object]),而其他类型的变量调用 toString 则是返回其对应字符串形式。所以我们需要使用 Object.prototype.toString.call 来判断变量的类型
call/apply/bind 如果第一个参数是一个原始值,那么会转换成对于的包装对象
constructor
每个函数都会有一个 prototype 属性(除了箭头函数)表示该函数的原型对象,该对象上有一个 constructor 属性执行该函数本身,所以我们可以通过变量.constructor
来判断变量类型
细节问题
-
null/undefined 是无效的对象,所以不能通过这个属性来判断这两个变量的类型(null 和 undefined 也不能直接调用 toString 方法来返回其字符串表示)
-
变量的 constructor 属性是不稳定的,当开发者重写了 prototype 的时候其 constructor 属性就会改变(所以我们在重写 prototype 之后需要设置正确的 constructor)
网友评论