JS 数据类型理解

183 阅读4分钟

值类型

变量本身含有赋予给它的数值,它的变量本身及保存的数据都存储在栈的内存块当中。 Undefined Null Boolean Number String Symbol(es6新增)

Number

  • Number 类型包含整数和浮点数(浮点数数值必须包含一个小数点,且小数点后面至少有一位数字)两种值。
  • NaN: 非数字类型。特点:① 涉及到的任何关于 NaN 的操作,都会返回 NaN ② NaN 不等于自身
  • isNaN() 函数用于检查其参数是否是非数字值
isNaN(123)  //false
isNaN("hello")  //true

Number 类型最大安全整数是 MAX_SAFE_INTEGER 2^53-1,最大安全值 MAX_VALUE

String

  • Length 属性
  • String(), 适用于所有数据类型(null,undefined 转换为 "null" 和 "undefined")
  • toString(), (null,undefined 没有 toString() 方法,因为它们是原始值,不是对象,没有原型)

Boolean

  • true 或 false
2 > 1; // true
[] == []; // false 不同的地址
[] == ![]; // true 详解见 [JS 中的 == ===]
null == undefined // true
'10' > '3'; // flase
typeof true; // boolean

Undefined

  • 使用 var 声明了变量,但未给变量初始化值,那么这个变量的值就是 undefined

Null

  • null 类型在逻辑上被看做空对象指针

Symbol

  • 原始数据类型 Symbol,表示独一无二的值,通常用于对象的属性名

引用类型

  • 引用类型当然是分配到堆上的对象或者数据变量,根据官方一点的解释就是引用类型的变量只包括对其所表示的数据引用。
  • 对象、数组、函数
  • 无限扩展属性,可能出现内存占用比较大的情况

类型判断

typeof

能区分大部分的基本类型,不能区分 null,不能区分除 function 之外的对象。

typeof 1 // 'number'
typeof '' // 'string'
typeof true // 'boolean'
typeof [] // 'object'
typeof {} // 'object'
typeof null // 'object'
typeof undefined // 'undefined'
typeof function(){} // 'function'

可以用来检测函数

当需要被检测的变量是数组、对象和 null 时,返回的结果都是 object,因为 js 中的数组,本质上还是一个对象,而 null 在 js 中是一个表示为空的特殊的对象。

返回值是字符串

typeof typeof 1 // 'string'
typeof typeof '' // 'string'
typeof typeof true // 'string'

不足

既然数组实例、对象实例和 null 通过 typeof 的检验返回的都是 object,这也就说明 typeof 并不能够完美的帮助我们区分数组、对象和 null,某些情况下会给我们的工作带来不便。

instanceOf

主要用来检测对象类型,是否是某个类型或者某个类型的父类型。

instanceof 运算符用来判断一个构造函数的 prototype 属性所指向的对象是否存在另外一个要检测对象的原型链上。简单来说,就是检测一个对象是否继承于另一个对象。

var a = 1
a instanceof Number // false
a instanceof String // false
null instanceof Object // false

当一个变量是 null 时,判断是否为 Object 的实例,返回为 false,说明 null 虽然是个特殊的对象,但是并不继承自 Object。

无法检测普通类型

虽然 instanceof 能够区分数组、对象和 null,但是它的右边只能够接收一个对象类型,这也就说明,无法用 instanceof 来检测基础类型。

多框架问题

instanceof 判断的变量,必须是在当前页声明,多个框架中有不同类型定义,会导致判断为 false。

代码实现

function instance_of(L, R) {//L 表示左表达式,R 表示右表达式
 var O = R.prototype;// 取 R 的显示原型
 L = L.__proto__;// 取 L 的隐式原型
 while (true) {
   if (L === null)
     return false;
   if (O === L)// 这里重点:当 O 严格等于 L 时,返回 true
     return true;
   L = L.__proto__;
 }
}

通用方法 Object.prototype.toString()

var ary = [1,2,3,4];
function isArray(o){
    return Object.prototype.toString.call(o)=='[object Array]';
}
console.log(isArray(ary));

理解:为什么调用 Object 的原型对象上的 toString() 方法

  • 因为像 Array 这样的对象重写了 toString() 方法,所以直接调用数组对象上面的 toString() 方法调用的是重写后的方法,而不是 Object.prototype 中的 toString() 方法。
console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]
console.log(Object.prototype.toString.call(null)) //[Object Null]

将数组的 toString 方法删除,看看会是什么结果

var arr=[1,2,3];
console.log(Array.prototype.hasOwnProperty("toString"));//true
console.log(arr.toString());//1,2,3
delete Array.prototype.toString;//delete 操作符可以删除实例属性
console.log(Array.prototype.hasOwnProperty("toString"));//false
console.log(arr.toString());//"[object Array]"