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 了解包装类有助于我们理解代码并运用一些隐式地转换简化我们的代码,更为透彻理解引擎的执行。
相关推荐
Myli_ing13 分钟前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风16 分钟前
前端 vue 如何区分开发环境
前端·javascript·vue.js
PandaCave23 分钟前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习
软件小伟25 分钟前
Vue3+element-plus 实现中英文切换(Vue-i18n组件的使用)
前端·javascript·vue.js
醉の虾1 小时前
Vue3 使用v-for 渲染列表数据后更新
前端·javascript·vue.js
张小小大智慧1 小时前
TypeScript 的发展与基本语法
前端·javascript·typescript
hummhumm1 小时前
第 22 章 - Go语言 测试与基准测试
java·大数据·开发语言·前端·python·golang·log4j
asleep7011 小时前
第8章利用CSS制作导航菜单
前端·css
hummhumm1 小时前
第 28 章 - Go语言 Web 开发入门
java·开发语言·前端·python·sql·golang·前端框架
幼儿园的小霸王2 小时前
通过socket设置版本更新提示
前端·vue.js·webpack·typescript·前端框架·anti-design-vue