广告
返回顶部
首页 > 资讯 > 前端开发 > VUE >JavaScript原始值与包装对象介绍
  • 570
分享到

JavaScript原始值与包装对象介绍

2024-04-02 19:04:59 570人浏览 安东尼
摘要

这篇文章主要介绍“javascript原始值与包装对象介绍”,在日常操作中,相信很多人在JavaScript原始值与包装对象介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”

这篇文章主要介绍“javascript原始值与包装对象介绍”,在日常操作中,相信很多人在JavaScript原始值与包装对象介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript原始值与包装对象介绍”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

前言

随着 JavaScript 越来越流行,越来越多地开发者开始接触并使用 JavaScript。

同时我也发现,有不少开发者对于 JavaScript 最基本的原始值和包装对象都没有很清晰的理解。

那么本篇文章,就由渣皮来给大家详细介绍一下它们。

话不多说,Let's Go!

正文

原始类型 (Primitive types)

原始类型也被称为“基本类型”。

目前在 JavaScript 中有以下几种原始类型:

  • string(字符串)

  • number(数字)

  • boolean(布尔)

  • null(空)

  • undefined(未定义)

  • bigint(大整数,es6)

  • symbol(标志?ES6)

如下:

typeof 'chenpipi';  // "string" typeof 12345;       // "number" typeof true;        // "boolean" typeof null;        // "object" typeof undefined;   // "undefined" typeof 12345n;      // "bigint" typeof Symbol();    // "symbol"

特别注意

typeof null 虽然返回 "object",但是这不代表 null 就是对象,这其实是 JavaScript 的一个 Bug,且从  JavaScript 诞生以来便如此。

在 JavaScript 最初的实现中,JavaScript 中的值是由一个表示类型的标签和实际数据值表示的。对象的类型标签是 0。由于 null  代表的是空指针(大多数平台下值为 0x00),因此,null 的类型标签是 0,typeof null 也因此返回 "object"。

The history of “typeof null”:https://2ality.com/2013/10/typeof-null.html

原始值 (Primitive values)

原始值也就是原始类型的值(数据)。

A primitive value is data that is not an object and has no methods.

原始值是一种没有任何方法的非对象数据。

也就是说,string、number 和 boolean 等原始类型的值本身是没有任何属性和方法的。

这个时候嗅觉敏锐的小伙伴是不是已经察觉到有什么不对劲了?

是孜然!我加了孜然!(手动狗头并划掉)

这里有一个非常有意思的点,但是在讨论这个问题之前,先让我们认识下包装对象。

包装对象 (Wrapper objects)

除了 null 和 undefined 外的原始类型都有其相应的包装对象:

  • String(字符串)

  • Number(数字)

  • Boolean(布尔)

  • BigInt(大整数,ES6)

  • Symbol(标志?ES6)

对象 (Object)

对象是引用类型。

首先,包装对象本身是一个对象,也是函数。

String instanceof Object;   // true String instanceof Function; // true

构造函数 (Constructor)

实例 (Instance)

其中 String、Number 和 Boolean 均支持使用 new 运算符来创建对应的包装对象实例。

例如 String 的声明(节选):

interface StrinGConstructor {   new(value?: any): String;   (value?: any): string;   readonly prototype: String; } declare var String: StringConstructor;

使用 new 运算符得到的数据是对象(Object):

// 字符串 typeof 'pp';                      // "string" typeof new String('pp');          // "object" new String() instanceof Object;   // true // 数字 typeof 123;                       // "number" typeof new Number(123);           // "object" new Number() instanceof Object;   // true // 布尔 typeof true;                      // "boolean" typeof new Boolean(true);         // "object" new Boolean() instanceof Object;  // true

我们可以调用包装对象实例的 valueOf() 函数来获取其原始值:

// 字符串 let s = new String('pp'); s.valueOf();                // "pp" typeof s.valueOf();         // "string" // 数字 let n = new Number(123); n.valueOf();                // 123 typeof n.valueOf();         // "number" // 布尔 let b = new Boolean(true); b.valueOf();                // true typeof b.valueOf();         // "boolean"

“异类” (Attention)

而 BigInt 和 Symbol 都属于“不完整的类”,不支持 new 运算符。

例如 BigInt 的声明(节选):

interface BigIntConstructor {   (value?: any): bigint;   readonly prototype: BigInt; } declare var BigInt: BigIntConstructor;

可以看到 BigInt 的声明中没有 new 运算符相关函数。

普通函数 (Function)

包装对象也可以作为普通函数来使用。

其中 String()、Number() 和 Boolean() 函数都可以用来对任意类型的数据进行显式类型转换。

另外 Object() 函数也可用于显式类型转换,但本文不再展开。

String

示例代码:

typeof String();    // "string" String();           // "" String('pp');       // "pp" String(123);        // "123" String(true);       // "true" String(false);      // "false" String(null);       // "null" String(undefined);  // "undefined" String([]);         // "" String({});         // "[object Object]"

小贴士 1

当我们使用 String() 函数来转换对象时,JavaScript 会先访问对象上的 toString()  函数,如果没有实现,则会顺着原型链向上查找。

举个栗子:执行 String({ toString() { return 'pp'; } }) 返回的结果是 "pp",并非 "[object  Object]"。

所以 String() 函数并不能够用来判断一个值是否为对象(会翻车)。

小贴士 2

常用的判断对象的方式为 Object.prototype.toString({}) === '[object Object]'。

举个栗子:执行 Object.prototype.toString({ toString() { return 'pp'; } }) 返回的是  "[object Object]"。

Number

示例代码:

typeof Number();    // "number" Number();           // 0 Number('');         // 0 Number('pp');       // NaN Number(123);        // 123 Number(true);       // 1 Number(false);      // 0 Number(null);       // 0 Number(undefined);  // NaN Number([]);         // 0 Number({});         // NaN

小贴士

对于 Number() 函数来说,可能最实用的转换就是将 true 和 false 转换为 1 和 0 吧。

Boolean

示例代码:

typeof Boolean();   // "boolean" Boolean();          // false Boolean('');        // false Boolean('pp');      // true Boolean(0);         // false Boolean(1);         // true Boolean(null);      // false Boolean(undefined); // false Boolean([]);        // true Boolean({});        // true

小贴士

某些情况下,我们会在数据中使用 0 和 1 来表示真假状态,此时就可以使用 Boolean() 进行状态的判断。

BigInt

BigInt() 函数用于将整数转换为大整数。

该函数接受一个整数作为参数,传入参数若为浮点数或任何非数字类型数据都会报错。

示例代码:

BigInt(123);        // 123n BigInt(123n);       // 123n typeof 123n;        // "bigint" typeof BigInt(123); // "bigint"

BigInt & Number

需要注意的是,BigInt 和 Number 是不严格相等(宽松相等)的。

示例代码:

123n === 123; // false 123n == 123;  // true

Symbol

Symbol() 函数用于创建一个 symbol 类型的值。

该函数接受一个字符串作为描述符(参数),如果传入其他类型的值则会被转换为字符串(除了 undefined)。

注意,每一个 symbol 值都是独一无二的,即使它们的描述符都是一样的。

且 symbol 类型的数据只能通过 Symbol() 函数来创建。

示例代码:

// 后面的返回值是 Devtools 模拟出来的,并非实际值 Symbol('pp');                   // Symbol(pp) Symbol(123);                    // Symbol(123) Symbol(null);                   // Symbol(null) Symbol({});                     // Symbol([object Object])  // 类型 typeof Symbol('pp');            // "symbol" Symbol('pp') === Symbol('pp');  // false  // 描述符 Symbol('pp').description;       // "pp" Symbol(123).description;        // "123" Symbol({}).description;         // "[object Object]" Symbol().description;           // undefined Symbol(undefined).description;  // undefined

原始值不是对象 (Primitive not Object)

有意思的来了~

没有属性和方法 (No properties, no functions)

本文前面有提到:「原始值是一种没有任何方法的非对象数据。」

我们都知道对象(Object)上可以有属性和方法。

但是字符串不是对象,所以你不能给字符串增加属性。

做个小实验:

let a = 'chenpipi'; console.log(a.length);  // 8 // 尝试增加新的属性 a.name = '吴彦祖'; console.log(a.name);    // undefined // 尝试修改已有的属性 typeof a.slice;         // "function" a.slice = null; typeof a.slice;         // "function"

渣皮小剧场

此时一位头铁的小伙伴使用了反驳技能。

渣皮你别在这忽悠人了,我平时写 Bug 哦不写代码的时候明明可以调用到字符串、数字和布尔值上的方法!

比如下面这段代码,能够正常执行并得到符合预期的结果:

// 字符串 let s = 'chenpipi'; s.toUpperCase();      // "CHENPIPI" 'ChenPiPi'.slice(4);  // "PiPi" // 数字 let n = 123; n.toString();         // "123" (123.45).toFixed(2);  // "123.5" // 布尔值 let b = true; b.toString();         // "true" false.toString();     // "false"

无用小知识

有没有发现,数字的字面量后面不能直接调用函数?例如执行 123.toString() 会报 SyntaxError(语法错误)。

这是因为数字(浮点数)本身会用到小数点 .,而调用函数也需要用小数点,这时就出现了歧义(字符串和布尔值就没有这种烦恼)。

对于这种情况,我们可以使用括号 () 将数字包裹起来,如 (123).toString();或者使用两个连续的小数点 .. 来调用函数,如  123..toString()。

 奇了怪了

那么既然字符串不是对象,那么为什么字符串会有属性和方法呢?

转念一想,数字就是数字,数字身上怎么会有方法呢?

这确实不符合逻辑,但是这又与实际相矛盾。

咋回事呢???

替身使者 (I can't translate this)

答案揭晓~

 暗中操作

以字符串(string)为例,当我们在代码中读取字符串的属性或者方法时, JavaScript 会静默地执行下面的操作:

  1. 鸿蒙官方战略合作共建——HarmonyOS技术社区

  2. 将字符串通过 new String() 的方式来创建一个临时的包装对象实例;

  3. 通过创建的对象来执行我们的代码逻辑(读取属性或执行函数);

  4. 临时对象不再使用,可以被销毁。

如下面的栗子:

let a = 'chenpipi'; console.log(a);   // "chenpipi" // ------------------------------ let b1 = a.length; console.log(b1);  // 8 // 上面的代码相当于: let b2 = (new String(a)).length; console.log(b2);  // 8 // ------------------------------ let c1 = a.toUpperCase(); console.log(c1);  // "CHENPIPI" // 上面的代码相当于: let c2 = (new String(a)).toUpperCase(); console.log(c2);  // "CHENPIPI"

数字(number)和布尔值(boolean)同理,但数字通过 new Number() 来创建临时对象,而布尔值则通过 new Boolean()  来创建。

除了上面的例子,最有力的证明,就是他们的构造函数:

'chenpipi'.constructor === String;  // true (12345).constructor === Number;     // true true.constructor === Boolean;       // true

这一切都是 JavaScript 在暗中完成的,且过程中产生的临时对象都是一次性的(用完就丢)。

原来如此

芜湖,这么一来就说得通了!

这也就能解释为什么我们能够访问字符串上的属性和方法,却不能增加或修改属性。

那是因为我们实际操作的目标其实是 JavaScript 创建的临时对象,而并非字符串本身!

所以我们的增加或修改操作实际上是生效了的,只不过是在临时对象上生效了!

就像这样:

// 代码中: let a = 'chenpipi'; a.name = '吴彦祖'; console.log(a.name);  // undefined  // 相当于: let a = 'chenpipi'; (new String(a)).name = '吴彦祖'; console.log(a.name);  // undefined  // 相当于: let a = 'chenpipi'; let temp = new String(a); temp.name = '吴彦祖'; console.log(a.name);  // undefined

到此,关于“JavaScript原始值与包装对象介绍”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

--结束END--

本文标题: JavaScript原始值与包装对象介绍

本文链接: https://www.lsjlt.com/news/81508.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • JavaScript原始值与包装对象介绍
    这篇文章主要介绍“JavaScript原始值与包装对象介绍”,在日常操作中,相信很多人在JavaScript原始值与包装对象介绍问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”...
    99+
    2022-10-19
  • JavaScript原始值与包装对象的详细介绍
    目录前言正文原始类型 (Primitive types)原始值 (Primitive values)包装对象 (Wrapper objects)对象 (Object)构造函数 (Co...
    99+
    2022-11-12
  • JavaScript原始值与包装对象的示例分析
    这篇文章主要介绍JavaScript原始值与包装对象的示例分析,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!JavaScript有什么特点1、js属于一种解释性脚本语言;2、在绝大多数浏览器的支持下,js可以在多种平...
    99+
    2023-06-15
  • 详解JavaScript对象转原始值
    目录Object.prototype.valueOf()Object.prototype.toString()Symbol.toPrimitive对象转换原始值1. 预期被转换成字符...
    99+
    2022-11-12
  • JavaScript对象转原始值是什么
    这篇文章主要讲解了“JavaScript对象转原始值是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JavaScript对象转原始值是什么”吧!Object.prototype.valu...
    99+
    2023-06-22
  • javascript Number 与 Math对象的介绍
    目录一、javascript 中 Number二、Javascript中Math对象一、javascript 中 Number javascript 中,数值类型属于原始类型。 除了...
    99+
    2022-11-12
  • Python函数对象与闭包介绍
    目录一 函数对象1.1 函数可以被引用1.2 函数可以作为容器类型的元素1.3 函数可以作为参数传入另外一个函数1.4 函数的返回值可以是一个函数二 闭包函数2.1 闭与包2.2 闭...
    99+
    2022-11-10
  • 浅析JavaScript对象转换成原始值
    目录前言三种算法对象转换成布尔值对象转换成字符串对象转换成数值转换时使用的方法toString()valueOf()转换算法偏字符串算法偏数值算法无偏好算法练习题前言 首先抛出几个问...
    99+
    2022-11-13
  • JavaScript闭包原理与使用介绍
    目录1. 认识闭包2. 变量的作用域和生命周期2.1 变量的作用域2.2 变量的生命周期3. 闭包的概念及其作用3.1 闭包的概念3.2 闭包的应用3.2.1 保存私有变量3.2.2...
    99+
    2022-11-13
    JavaScript闭包 JS闭包
  • JavaScript内置对象Math与String详细介绍
    目录Math对象Math获取随机数String对象Math对象 js内置数学对象 不是一个构造函数 所以不需要使用new来调用 而是直接使用里面的属性和方法即可 Math.PI 圆周...
    99+
    2022-11-13
  • JavaScript 引用类型之原始值包装类型String
    目录String 原始值包装类型String 原始值包装类型 操作方法1.字符串编码常规化函数 normalize()方法2.字符串拼接函数concat()3.字符串提取子...
    99+
    2022-11-13
  • JavaScript的面向对象和它的封装、继承、多态简单介绍
    这篇文章主要介绍“JavaScript的面向对象和它的封装、继承、多态简单介绍”,在日常操作中,相信很多人在JavaScript的面向对象和它的封装、继承、多态简单介绍问题上存在疑惑,小编查阅了各式资料,整...
    99+
    2022-10-19
软考高级职称资格查询
推荐阅读
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作