js中的数据类型(基本数据类型+引用数据类型)

122 阅读7分钟

js中的数据类型

栈:基本数据类型

值存储在栈中,两个变量互相赋值时,并不会互相影响

  • Undefined 未定义
  • Null 空指针
  • Boolean 布尔
  • Number 数字
  • String 字符串

堆:引用数据类型

变量的值存储在堆中,变量引用存放在栈中,赋值时是将栈中的地址复制给另一个变量,两个变量就指向了同一地址会相互影响

对象

  • 普通对象 {}
  • 数组对象 []
  • 正则对象 /.../
  • math数学函数对象
  • data日期对象

函数

函数实际上是对象,函数名实际上也是一个指向函数对象的指针。每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。

普通对象

创建对象

// 构造函数
let person = new Object();
person.name = "Nicholas";
person.age = 29;
console.log(person instanceof Object); // true
//字面量
let person = {
  name : "Nicholas",
  age ; 29
}
console.log(person instanceof Object); // true

访问对象属性

obj.name='lisa' obj['name']='lisa' 对象的键名唯一且为数字或字符串格式,重复声明时后面的属性会自动将前面的进行覆盖 如果属性名为数字则不能通过.语法进行获取属性值

销毁一个对象

  • obj==null
  • delete obj.name //删除对象中的属性
  • obj.name=''//将对象中的name属性置空

数组

数组是特殊的对象,属性名为默认生成的数字,从0开始递增 自带属性值length代表数组的长度

数组与对象的区别

数组表示有序数据的集合,而对象表示无序数据的集合。(最核心的差别) 数组和对象的另一个区别是,数组的数据没有”名称”(name),对象的数据有”名称”(name)。

数组创建

// 构造函数
let colors = new Array();
console.log(colors instanceof Array);  // true
// 数组字面量
let colors = ["red","blue","green"];
console.log(colors instanceof Array);  // true

null/undefined

undefined 代表的含义是未定义,null 代表的含义是空对象。

null

意料之中,一般是开始我们不知道值,先手动设置null,后期再进行赋值操作 null表示一个变量被人为的设置为空对象,而不是原始状态,即该处不应该有值。

undefined

意料之外,创建一个变量没有赋值,默认值是undefined undefined表示一个变量自然的、最原始的状态值,就是此处应该有一个值,但是还没有定义。存在就是为了明确null的使用。

总结

所以,在实际使用过程中,为了保证变量所代表的语义,不要对一个变量显式的赋值 undefined,当需要释放一个对象时,直接赋值为 null 即可。 值类型的“虚无”用undefined,引用类型的“虚无”,用null。

Symbol

是一种基本数据类型,表示独一无二的值,调用以后进行缓存,即赋值给一个变量.解决可能存在的命名重复的问题(如一个表中会有多个名字相同的情况,名字为key值) 特点:唯一性,隐藏性(for···in 和 object.keys() 不能访问) var 变量=symbol(参数) var s1=Symbol('abc'); var s2=Symbol('abc'); s2和s1是两个独立的变量 如果属性是变量时,变量名需要使用[]扩起来(属性名正常情况下是字符串) 注:symbol类型的数据不能被for in 和 object.keys进行访问使用场景一: 使用场景一:(不可遍历性) 作为对象属性名来使用,把一些不需要对外操作或访问的属性使用symbol来定义,因为symbol不能通过for in等方式进行枚举。 使用场景二:(唯一性) 利用其唯一特性来定义常量(常量声明需要赋值),避免重名的可能性 场景三:(唯一性) var target={} object.assign(target,t1,t2) object.assign的作用为,将第二个参数及之后的参数对象的属性合并到第一个参数上,重复的属性会产生覆盖symbol的作用就是,在做属性的合并时,并不会产生覆盖效果

BigInt

是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。差别在于存储的方式不同。 BigIntNumber之间不能进行混合操作 如果希望使用BigIntNumber执行算术计算,首先需要确定应该在哪个类型中执行该操作。为此,只需通过调用Number()BigInt()来转换操作数:

BigInt(10) + 10n;    // → 20n
// 或者(在同一环境中操作)
10 + Number(10n);    // → 20

数据类型检测(4种...)

typeof(返回具体类型)

检测原理:根据值在计算机中的存储做判断 其中数组、对象、null都会被判断为object,其他判断都正确。 这是浏览器的BUG:所有的值在计算中都以二进制编码储存,浏览器中把前三位000的当作对象,而null的二进制前三位是000,所以被识别为对象,但是他不是对象,他是空对象指针,是基本类型值

instanceof(返回true/false)

检测原理:类的原型只要出现在了实例的原型链上就返回true instanceof只能正确判断引用数据类型,而不能判断基本数据类型。instanceof 运算符可以用来测试一个对象在其原型链中是否存在一个构造函数的 prototype 属性。 arr instanceof Object 不能基于这个语句判断引用数据的具体类型

let arr = [10, 20];

console.log(typeof arr); //=>"object"
console.log(arr instanceof Array); //=>true
console.log(arr instanceof Object); //=>true  不管是数组对象还是正则对象,都是Object的实例,检测结果都是TRUE,所以无法基于这个结果判断是否为普通对象 

constructor

检测原理:实例.constructor 一般都等于 类.prototype.constructor 也就是当前类本身(前提是你的 constructor 并没有被破坏,相比typeof与instanceof该方法在检测对象上没有局限性 console.log(([]).constructor === Array); // true 需要注意,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了

function Fn(){};
Fn.prototype = new Array();
var f = new Fn();
console.log(f.constructor===Fn);    // false
console.log(f.constructor===Array); // true
Object.prototype.toString.call()

原型链上的方法(精准判断数据类型)

检测原理:每一种数据类型的构造函数的原型上都有toString方法,找到Object.prototype上的toString方法,让toString方法执行,并且基于call让方法中的this指向检测的数据值,这样就可以实现数据类型检测了,返回结果为对应类型的字符串标记"[object Type]" 对数组类型进行监测

Object.prototype.toString.call(10)  "[object Number]"
Object.prototype.toString.call(obj).slice(8,-1) === 'Array';
原型链监测:obj.__proto__ === Array.prototype;
es6方法:Array.isArrray(obj)

其他检测方法

// 据类型的检测
Array.isArray() // 数组检测
Number.isNaN()  // 有效数字检测

补充:

typeof NaN; // "number" NaN 指“不是一个数字”(not a number),NaN 是一个“警戒值”,用于指出数字类型中的错误情况,即“执行数学运算没有成功,这是失败后返回的结果”,NaN 是一个特殊值,它和自身不相等,是唯一一个非自反(自反,reflexive,即 x === x 不成立)的值。而 NaN !== NaN 为 true。

封装一个方法进行数据类型检测

隐式类型转化

  • +操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。
  • -、*、\都会转为数字进行运算
  • == 操作符两边的值都尽量转成number
  • <和>比较符 如果两边都是字符串,则比较字母表顺序:其他情况下,转换为数字再比较

补充:

  • 在条件判断类型中,其他类型都会隐试转化为bool类型

数据间的相互转换

其他数据类型转为数字

  • number(undefined) 为 NaN
  • number(null) 为 0(引用类型数据转化为数字先通过string方法将数据转化为字符串再转为数字)
  • number([2]) 为 2 number([2,2,3]) 为 NaN
  • number([]) 为 0 number({}) 为 NaN
  • parseInt()parsefloat()对字符串来说是从左到右依次寻找,直到出现非有效数字时将之前的有效数组返回

其他数据类型转为字符串

.toString {}.toString 结果为[object object](object原形上的方法不是用来转化为字符串的,是用来检测数据类型的) 字符串拼接 alert弹框的内容都要将数据的类型转化为字符串。