JS基础-揭开包装类的神秘面纱,原来js也就这么回事

JavaScript 的数据类型

JavaScript 是一种动态、弱类型的语言。虽然 JavaScript 的类型系统不像静态类型语言那样严格,但它仍然有自己的类型系统,并通过不同的方式管理和操作这些类型。

JavaScript 的数据类型可以分为原始类型(Primitive Types)对象类型(Object Types)

原始类型(基础类型)

  1. String :字符串,例如 "hello"
  2. Number :数字,包括整数和浮点数,例如 423.14
  3. Boolean :布尔值,只有两个值:truefalse
  4. BigInt :用于表示大整数,例如 123n
  5. Symbol :一种唯一且不可变的值,用作对象属性的标识符,例如 Symbol("description")
  6. Undefined:表示变量未定义或未赋值
  7. Null:表示空或不存在的值

对象类型

  • Object:对象是引用类型,用于存储键值对和复杂数据结构。
  • Function:JavaScript 中的函数也是对象,是一种特殊的对象类型。
  • Array:数组是对象的一种,用于存储有序的值列表。
  • 其他对象类型 :如 DateRegExp 等。

原始类型与对象类型的主要区别

  1. 存储方式

    • 原始类型直接存储在栈内存中,访问速度快。
    • 对象类型存储在堆内存中,引用存储在栈内存中。
  2. 可变性

    • 原始类型是不可变的,一旦创建,值就不能改变。
    • 对象类型是可变的,属性和内容可以动态改变。
  3. 传递方式

    • 原始类型按值传递,变量赋值时会创建副本。
    • 对象类型按引用传递,变量赋值时会复制引用,多个变量可以引用同一个对象。

万物皆对象?

大家都知道,JavaScript同时也是一门面向对象的语言,我们尊崇"万物皆对象",咦?那既然如此,基础类型和他们所对应的对象类型又如何区分呢?为了不打起来,JavaScript做出了妥协,为部分基础类型系统中的"值类型"设定对应的包装类 ;然后通过包装类,将"值类型数据"作为对象来处理。

什么鬼东西?

先别急着刀人 我们来看个栗子

js 复制代码
let str ='I love you'
console.log(str.length);

let num = 23
console.log(num.length)

虽然我们经常用到str.length,但有没有想过,为什么str就有,而num就没有呢? 其实呢 是这样的

对于str

  • 原始类型str 是一个原始类型的字符串。

  • 临时包装对象 :当你访问 str.length 时,JavaScript 引擎创建一个临时的 String 对象来包装这个原始字符串。

  • 属性查找 :JavaScript 在这个临时 String 对象的原型链上查找 length 属性。由于 String.prototype 上定义了 length 属性,查找成功。

  • 返回值length 属性的值是字符串的长度,因此返回 10。

  • 丢弃临时对象 :访问完成后,临时的 String 对象被丢弃。

而对于num

  • 原始类型num 是一个原始类型的数字。

  • 临时包装对象 :当你访问 num.length 时,JavaScript 引擎创建一个临时的 Number 对象来包装这个原始数字。

  • 属性查找 :JavaScript 在这个临时 Number 对象的原型链上查找 length 属性。由于 Number.prototype 上没有 length 属性,查找失败。

  • 返回值 :由于临时的 Number 对象没有 length 属性,因此返回 undefined

  • 丢弃临时对象 :访问完成后,临时的 Number 对象被丢弃。

相信大家都理解了吧,那么如果你看了你知道new会发生什么吗这篇文章,相信你可以理解下面的例子

js 复制代码
let str = new String('Hello');
console.log(typeof str);        // 输出 "object"
console.log(str.valueOf());     // 输出 "Hello"

let num = new Number(123.456);
console.log(typeof num);        // 输出 "object"
console.log(num.valueOf());     // 输出 123.456

那么 对于上面的new和我们这段代码又有什么区别呢?

js 复制代码
let num =123
let str='Hello'

当然有

js 复制代码
console.log(str1 == str2); // 输出: true (因为==比较值) 
console.log(str1 === str2); // 输出: false (因为===比较类型和值)

我们可以看见 两者的值都是一样的,但是由于类型不同而第二条输出false,所以说,由new创建的num和str都是和我们直接赋值一样都有一个值的,但是,前者是一个包装类。但是呢,包装类创建的对象占用更多内存,并且性能上相对较慢,因为每次创建对象时都需要分配内存和垃圾回收。基本类型更轻量,性能更高,因为它们直接在栈上操作,而不是在堆上。

最后 我们以一道面试题来结束

js 复制代码
var str = 'abc'
str += 1
console.log(str);
var test = typeof (str)
if (test.length === 6) {
    test.sign = 'typeOf的返回结果可能是String' 
  
}
console.log(test.aign)//undefined 
  • 加号在这里是链接字符串 所以str-->'abc+1'
  • 所以test-->'String'
  • 所以if判断为真执行test.sign='typeOf的返回结果可能是String'
  • 这里引擎会干这么几件事
    • 创建一个String对象并且增加sign属性,new String(test).sign='typeOf的返回结果可能是String'
    • 访问完毕,然后发现test为原始类型,丢弃该String对象。
  • 所以最后的输出引擎找不到该属性而输出undefined 了解包装类有助于我们理解代码并运用一些隐式地转换简化我们的代码,更为透彻理解引擎的执行。
相关推荐
腾讯TNTWeb前端团队6 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
uhakadotcom9 小时前
视频直播与视频点播:基础知识与应用场景
后端·面试·架构
范文杰9 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪9 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪10 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy10 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom11 小时前
快速开始使用 n8n
后端·面试·github
uhakadotcom11 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom11 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom11 小时前
React与Next.js:基础知识及应用场景
前端·面试·github