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 了解包装类有助于我们理解代码并运用一些隐式地转换简化我们的代码,更为透彻理解引擎的执行。
相关推荐
大圣编程1 小时前
Python中continue语句的用法是什么?
开发语言·前端·python
yuhaiqiang1 小时前
随手 vibecoding 的浏览器插件已经 6000 多次下载,聊聊他的产品设计
前端·后端·面试
之歆2 小时前
Vue商品详情与放大镜组件
前端·javascript·vue.js
再吃一根胡萝卜2 小时前
如何把小米 MiMo 接入 CodeBuddy,打造私有 Agent
前端
负责的蛋挞4 小时前
异步HttpModule的实现方式
java·服务器·前端
黄敬峰4 小时前
🚀 从 Prompt 到 Harness:AI 编程的下半场,我们如何给大模型套上“挽具”?
面试
用户852495071844 小时前
手搓自然语义搜索:从传统匹配到向量化,理解 RAG 的第一步
面试
C语言小火车5 小时前
C++ 快速排序(Quick Sort)深度精讲:分治思想、Lomuto 分区法及三数取中优化,面试手撕必会
c语言·开发语言·c++·面试·排序算法·快速排序
丹宇码农6 小时前
把 HLS 字幕玩出花:zwPlayer 如何让 M3U8 视频支持全文搜索、翻译与码率自适应
前端·javascript·音视频·hls·视频播放器