(一)史上最全的JavaScript变量类型和计算的介绍

本文深入解析JavaScript中的数据类型,区分基本数据类型与引用类型,探讨它们的存储方式及区别,并介绍如何使用typeof和instanceof进行类型检测。同时,文章还讨论了函数参数的传递方式,以及JavaScript中的类型转换规则。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我写这篇文章的原因:
我在复习的时候,阅读很多博客发现很多我没有听过的名称,比如原始类型,对象类型等,搞得我一头雾水。我所了解的数据类型
不就string number之类的,但是我也不是很清楚他们属于哪个阵营吧。但是我知道基本数据类型和引用类型。这原始类型和对象类型是
从哪里冒出来的?
随后我在网上搜索了N篇文章,重要搞清楚这些概念。其实很多名字都是指向一个东西,只是叫法不一样。比如你叫张三,小名狗蛋。
你村里人叫张三是你,叫狗蛋还是你。那么基本数据类型和原始类型其实是一样的。

一,变量分类

在JavaScript六种数据类型分为两大类

基本数据类型(原始类型)
  • 字符串 String
  • 数字 Number
  • 布尔 Boolean
  • 空值 Null
  • 未定义 Undefined
  • 唯一值(ES6) Symbol

首先原始类型(基本数据类型)存储的都是值,是没有函数可以调用的,比如undefined.toString()
在这里插入图片描述
但是你看到这里你会有疑问,为什么"2".toString()可以呢,其实这种情况下,"2"已经不是原始类型了,而是被强制转成了String类型,也就是对象类型,所以可以调用toString函数。
在这里插入图片描述

typeof来检测原始类型
//typeof运算类型  只能区分值类型
console.log(typeof undefined) //undefined
console.log(typeof "abc") //string
console.log(typeof "undefined") //string
console.log(typeof 123) //number
console.log(typeof true) //boolean
console.log(typeof {}) //object
console.log(typeof []) //object
console.log(typeof null) //object  null是引用类型
console.log(typeof console.log) //function

另外对于null来说,很多人认为他是一个对象类型,其实这是错误的,null就是原始类型也就是值类型。你看到网上很多的博客对null的描述都是错误的。typeof null 会输出object 是JS存在的一个bug。在JS的最初版本中使用的是32位系统。为了性能考虑使用低位存储变量信息,000开头代表对象,然而null表示全零。所以将它错误的判断为object。虽然现在的内部类型判断代码已经改变,但是这个bug一直存在。

引用数据类型(对象类型)
  • Object(在JS中除了基本数据类型以外的都是对象,数据是对象,函数是对象,正则表达式是对象)

1.Array
2.Boolean
3.Date
4.Number
5.String
6.RegExp
7.function
上面的都是引用类型,都包含在object中。

instanceof检测引用类型

typeof 对于对象来说,除了函数都会显示 object,所以说 typeof 并不能准确判断变量到底是什么类型
如果我们想判断一个对象的正确类型,这时候可以考虑使用 instanceof,因为内部机制是通过原型链来判断的

//instanceof检测
let a = [1, 2]
console.log(a instanceof Array) //true
console.log(a instanceof Object) //true


let s = "ss"
console.log(s instanceof String) //false
console.log(s instanceof Object) //false

let s1 = new String("Hello")
console.log(s1) //[String: 'Hello']
console.log(s1 instanceof String) //true
console.log(s1 instanceof Object) //true


let t = true
console.log(t instanceof Boolean) //false
console.log(t instanceof Object) //false

let t1 = new Boolean(true)
console.log(t1) //[Boolean: true]
console.log(t1 instanceof Boolean)
console.log(t1 instanceof Object)


let func = function() {

}
console.log(func instanceof Function) //true
console.log(func instanceof Object) //true


let rex = /^[1-9]/
console.log(rex instanceof RegExp) //true
console.log(rex instanceof Object) //true


let date = new Date()
console.log(date instanceof Date) //true
console.log(date instanceof Object) //true

注意上面显示的地方有几个是false,因为那两个的创建方式并不是对象类型的创建方式,是原始类型的创建。
instanceof是不能检测出来原始类型的,所以那里显示的是false。

class PrimitiveString {
  static [Symbol.hasInstance](x) {
    return typeof x === 'string'
  }
}
console.log('hello world' instanceof PrimitiveString) // true

你可能不知道 Symbol.hasInstance 是什么东西,其实就是一个能让我们自定义 instanceof 行为的东西,以上代码等同于 typeof ‘hello world’ === ‘string’,所以结果自然是 true 了。这其实也侧面反映了一个问题, instanceof 也不是百分之百可信的

二,原始类型和对象类型的区别

在JS中,除了原始类型那么其他的都是对象类型。对象类型和原始类型不同的是,原始类型存储的是值,对象类型存储的是地址。当你创建一个对象类型的时候,计算机会在内存中帮我们开辟一个空间存放值,但是我们需要找到这个空间,这个空间就会拥有一个地址。还有就是引用变量就是值引用(改变指针的指向位置),多个变量公用一个内存块,减少空间的浪费。
引用类型
let a=[]

对于常量a来说,假设内存地址是#111,那么在地址#111的位置存放了值[],常量a存放了地址#111。
在看下面的代码

let a=[]
let b=a
b.push(1)
console.log(a)//[1]
console.log(b)//[1]

当我们将变量赋值给另一个变量时,赋值的是原本变量的地址,也就是说当前变量存放的地址也是#111,当我们进行数据修改的时候,就会修改存放在地址#111上的值,也就导致两个变量的值都会发生变化

原始类型
let s = "ad"
let s1 = s
s1 = "aaa"
console.log(s1, s)//aaa ad

看第二行的代码,是把s的值"ad"赋值给s1,赋值完成以后s和s1就没有什么联系,因此修改二者中的任何一个,对另外一个都不会产生影响。

三,函数参数是对象

function test(person) {
  person.age = 26
  person = {
    name: 'fff',
    age: 18
  }

  return person
}
const p1 = {
  name: 'aaa',
  age: 26
}
const p2 = test(p1)
console.log(p1) // { name: 'aaa', age: 26 }
console.log(p2) // { name: 'fff', age: 18 }
  • 首先,函数传参是传递对象指正的副本
  • 到函数内部修改参数的属性这部,当前p1的值也被修改了
  • 但是当我们重新为person分配了一个对象时,就出现了分歧
    请看下图
    在这里插入图片描述
    最后person拥有了一个新的地址,也就和p1没有任何关系了,导致了最终两个变量的值是不相同的

四,类型转换

在JS中类型转换只有三种情况,分别是:
1.转换为布尔值
2.转换为数字
3.转换为字符串
先看下图:
在这里插入图片描述

强制类型转换(下面的情况会产生类型转换)

1.字符串拼接

ler a=1+1 //2
let b=1+"1"//11 

  1. ==运算符(慎用)
console.log(100 == "100") //true
console.log(0 == "") //true
console.log(null == undefined) //true
  1. if语句
    在条件判断的时候,处理undefined,null,false,NaN,"",0,-0其他所有值都会转为true,包括所有对象
var a = true
if (a) {
    console.log("a") //a
}
var b = 100
if (b) {
    console.log("b") //b
}
var c = ""
    //不运行
if (c) {
    console.log("c")
}

4.逻辑运算

//逻辑运算符
console.log(10 && 0) //0
console.log(10 || 0) //10
console.log('' && 'abc') //空值
console.log('' || 'abc') //abc
var a = 100
console.log(!!a) //true  !a=fasle  !!a=true
四则运算符

加法运算符不同于其他几个运算符,它有以下几个特点:

  • 运算中其中一方为字符串,那么就会把另一方也转换为字符串
  • 如果一方不是字符串或者数字,那么会将它转换为数字或者字符串
console.log(1 + "1")//11
console.log(true + true)//2
console.log(4 + [1, 2, 3])//41,2,3

解析:

  • 第一行代码,触发类型3,会将数字1转换为字符串,得到的结果"11"
  • 第二行代码,触发类型1,会将布尔值转换为数字,得到的结果是2
  • 第三行代码,触发类型3,会将数组转换为字符串(通过toString()方法)1,2,3得到的结果是41,2,3.
另外对于加法还需要注意这个表达式"a"++“b”
console.log("a" + +"b") //aNaN

因为+'b’等于NaN,所以结果是"aNaN"

除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转换为数字

console.log(4 * "3")//12
console.log(4 * [])//0
console.log(4 * [1, 2])//NaN
比较运算符

1.如果是对象,就通过toPrimitive转换为对象
2.如果是字符串,就通过unicode字符索引比较

let a = "a"
let b = "b"
console.log(a > b) //false
console.log(b > a) //true

何时使用 = = =何时使用= =

当obj.a= =null的时候用= =其他情况全部用= = =
obj.a= =null 相当于obj.a= = =null || obj.a= == undefined

留下一个小问题:true+true(如果一方不是字符串或者数字,那么会将它转换为数字或者字符串)
的结果为什是2却不是’truetrue’,如果知道的话可以在下方留言告诉我

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值