likes
comments
collection
share

小白的JavaScript包装类探秘:从基础到进阶的理解之旅

作者站长头像
站长
· 阅读数 50

数据类型

在学习包装类之前,我们先复习一下JavaScript中的数据类型,数据类型主要分为原始数据类型引用数据类型

1.原始数据类型

  • Number:表示数值类型,可以是整数或浮点
  • String:表示文本类型,由一串字符组成,用引号包围
  • Boolean:表示逻辑值,仅有两个取值:true 和 false
  • Undefined:表示变量已声明但尚未赋值时的默认状态,或者访问不存在的对象属性时返回的值
  • Null:表示一个特殊的空值或无指向的对象引用
let a = 'hello'     //数字
let b = 123         //字符串
let c = true        //布尔
let d = undefined   //未定义
let e = null        //空值

2.引用数据类型

  • 对象是键值对的集合,可以使用花括号 {} 创建,也可以通过构造函数创建
  • 数组是一个有序的数据集合,允许存储任意数量和类型的元素,使用方括号 [] 创建
  • 函数在JavaScript中也是一种对象,它可以被赋值给变量、作为参数传递
let obj = {}              //对象
let foo = function() {}   //函数
let arr = []              //数组

为什么使用包装类?

在JavaScript中,基本数据类型本身不是对象,但是在某些情况下,它们需要以对象的形式进行操作,为了实现这种操作,JavaScript提供了对应的包装类,为他们提供了一些额外的功能,允许你在基本数据类型上访问对象的属性,调用对象的方法

什么是包装类?

在JavaScript中,包装类是一组特殊的对象,用于在基本数据类型(如数字、布尔值和字符串)与对象之间进行转换和交互。JavaScript提供了三种主要的包装类:NumberStringBoolean

  1. Number:用于数值。例如,new Number(123) 会创建一个 Number 对象,该对象表示数值 123。
  2. String:用于字符串。例如,new String("hello") 会创建一个 String 对象,该对象表示字符串 "hello"。
  3. Boolean:用于布尔值。例如,new Boolean(true) 会创建一个 Boolean 对象,该对象表示布尔值 true

理解包装类

我们来看一个简单的demo

var num = 123
num.name = 'hhh'
console.log(num.name)  //运行结果 undefined

那么问题来了,我们给一个原始数据类型的变量num添加了属性abc,按理来说只有对象才有属性,那么在这里为什么没有报错而显示undefined呢?

这就不得不提到了我们今天的主角包装类

实际上,这段代码在真正执行中是这样一个过程:

var num = new Number(123)
num.name = 'hello'
delete num.name

V8会通过new Number(123),将它进行包装创建一个Number对象,这个就叫包装,可以暂时骗过JavaScript引擎,然后可以给这个临时对象添加name属性,因为这个对象是临时的,所以并不会影响到我们真正的原始数据,众所周知JavaScript是一门动态性的语言,它在执行上下文创建阶段有一个类似于预编译的过程,在这个阶段,引擎会扫描代码并提前处理所有变量声明,在运行时由JavaScript引擎逐行解释执行,所以在预编译的过程中,我们的num的确是具有name属性的,但是JavaScript又有着严格的界定,属性和方法是对象独有的,原始值是不能拥有属性和方法的,所以当JavaScript引擎回过神时,会立刻删除name属性,所以执行结果就是undefined啦!

我们再来看一个demo

var num = 1
num.len = 2
console.log(num.len)

根据上文的介绍,我们能很轻松的get到它的运行结果undefined,那么它的执行过程是什么样的呢?

var num = new Number(1)
num.len = 2
delete num.len
new Number(1).len

这个执行过程就叫做隐式包装类

下面我们来看一个考点

var str = 'abcd'
console.log(str.length)  //执行结果 4

字符串也是原始数据类型,我们可以知道的是它不能具有属性,但是V8会给它做一个隐式包装类,所以我们console.log的其实是new String('abcd').length,我们是可以访问到length的

那如果是这样呢?

var str = 'abcd'
str.length = 2
console.log(str)  //执行结果abcd

为什么改不动呢?这又回到了我们刚刚的规则问题,字符串是不能拥有属性和方法的,所以它在创建临时对象后会删除length的值,所以我们无法修改属性值

最后看一道面试题

var str = 'abc'
str += 1  
var text = typeof (str)  
if (text.length == 6) {  
text.sign = 'typeOf的返回结果可能为String'
}
console.log(text.sign)

我们来逐行分析一下,首先声明了一个变量str,第二行的运行结果为abc1,任何类型的数据在和字符串加和时都会被转换成字符串,因此在第三行类型判断后是'string',第四行代码会被执行为new String('string').lenth,到了第五行V8仍然没反应过来,执行new String('string').lenth = 'typeOf的返回结果可能为String'反应过来后再delete掉,在打印时看到属性又new String(test).lenth但是未赋值,所以执行结果是undefined

结语

最后,尽管JavaScript以其动态性赋予了开发者极大的灵活性,但在享受这份便利的同时,我们也应当充分认识到理解其底层原理的重要性。只有深入洞察这些内在规律,才能在实践中游刃有余,不断攀登技能高峰。希望本文能为你揭开JavaScript包装类的神秘面纱,深入了解了它在JavaScript引擎内部是如何巧妙地处理变量声明,助小伙伴们在今后的编程之旅中乘风破浪,扬帆远航。

转载自:https://juejin.cn/post/7365767783048118323
评论
请登录