龙空技术网

js的类型-有哪些你不知道的细节

菜鸟美食分享家 114

前言:

目前小伙伴们对“js不属于基本类型的是”大体比较关切,兄弟们都想要了解一些“js不属于基本类型的是”的相关资讯。那么小编在网摘上网罗了一些对于“js不属于基本类型的是””的相关资讯,希望看官们能喜欢,我们快快来了解一下吧!

先看几个问题:

为什么有的编程规范要求用 void 0 代替 undefined?字符串有最大长度吗?0.1 + 0.2 为什么不等于 3?ES6 新加入的 Symbol 是什么?为什么给对象添加的方法能用在基本类型上?

类型

JavaScript 语言的每一个值都属于某一种数据类型。JavaScript 规定了 7 种语言类型:

UndefinedNullBooleanNumberStringObjectSymbol

undefined、null

问题一:为什么有的编程规范要求使用void 0 代替 undefined?

Undefined 类型表示未定义,只有一个值即 undefined。任何变量在赋值前都是 Undefined 类型,值为 undefined。

一般我们可以用全局变量 undefined(即名为 undefined 的这个变量)来表示这个值,或者使用 void 运算,来把任意一个表达式变成 undefined 值

但因为 JavaScript 中 undefined 是一个变量,而非一个关键字,所以为了避免无意中被篡改,建议使用 void 来获取 undefined.

Undefined 跟 null 有一定的表意差别。null 表示定义了但为空。所以在实际编程中,我们不会把变量赋值为 undefined,这样可以保证所有值为 undefined 的变量,都是从未赋值的自然状态。

Null 类型也只有一个值就是 null,他的语义表示是空值,与 undefined 不同,null 是 JavaScript 关键字,故在任何代码中,都可以放心使用 null 关键字来获取 null 值

Boolean

Boolean 类型有两个值,true 和 false,用于表示逻辑意义上的真和假。

String

String 用于表示文本数据。String 有最大长度是 2^53 - 1。

String 的意义并非“字符串”,而是字符串的 UTF16 编码,我们字符串的操作charAt、charCodeAt、length等方法针对的都是 UTF16 编码。所以,字符串的最大长度,实际上是是受字符串的编码长度影响的.

Number

JavaScript 中的 Number 类型有(2^64 - 2^53 + 3)个值。

JavaScript 中的 Number 类型基本符合 IEEE 754-2008 规定的双精度浮点数规则,但 JavaScript 为了表达几个额外的语言场景(如不让除以 0 出错,而引入了无穷大的概念),规定了几种例外的情况:

NaN,占用了 9007199254740990,这原本是符合 IEEE 规则的数字;Infinity, 无穷大;-Infinity,负无穷大;

值得注意的是,JavaScript 中有+0 和-0,在加法类运算中它们没有区别,但除法的场合需要特别留意。区分+0 和-0 的方式:检测 1/x 是 Infinity 还是-Infinity

根据双精度浮点数的定义,Number 类型中有效的整数范围是 -0x1fffffffffffff 至 0x1fffffffffffff,所以 Number 无法精确表示此范围外的整数。

为什么在 JavaScript 中,0.1 + 0.2 !== 0.3?

console.log(0.1 + 0.2 === 0.3) // false

根据浮点数的定义,非整数的 Number 类型无法用 == (===也不行)来比较

正确的比较方法是使用 JavaScript 提供的最小精度值:

const abs = Math.abs(0.1 + 0.2 - 0.3)

console.log(abs <= Number.EPSILON ) // true

检查等式左右两边差的绝对值是否属于最小精度,才是比较浮点数的正确方法。

Symbol

ES6 引入的新类型,它是一切非字符串的对象 key 的集合。

// 创建Symbol类型变量

var mySymbol = Symbol('my symbol')

Object

Object 是 JavaScript 中最复杂的类型,也是 JavaScript 的核心机制之一。

在 JavaScript 中,对象的定义是“属性的集合”。属性分为数据属性和访问器属性,二者都是 key-value 结构,key 可以是字符串或者 Symbol 类型。

JavaScript 中的“类”仅仅是运行时对象的一个私有属性,而 JavaScript 是无法自定义类型的。

JavaScript 中的几个基本类型,都在对象类型中有一个“亲戚”

NumberStringBooleanSymbol 所以 3 !== new Number(3), 3 是一个 Number 类型数据,而 new Number(3)是一个对象类型

Number、String 和 Boolean,三个构造器是两用的,当跟 new 搭配时,它们产生对象,当直接调用时,他们表示强制类型转换。

JavaScript 语言上设计试图模糊对象和基本类型间的关系,所以我们日常代码可以把对象的方法在基本类型上使用,如:

console.log('abc'.charAt(0)); // a

甚至在原型上添加方法,都可以基于基本类型,如下,在 Symbol 原型上添加了 hello 方法,在任何 Symbol 类型变量都可以调用

Symbol.prototype.hello = ()=>console.log('hello')

var a = Symbol('a')

console.log(typeof a); // symbol, a并非对象

a.hello() // hello

所以:为什么给对象添加的方法能用在基本类型上?因为==.运算符==提供了装箱操作,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法。

类型转换

因为 JS 是弱类型语言,所以类型转换发生非常频繁,大部分我们熟悉的运算都会先进行类型转换,然后运算。

StringToNumber

字符串到数字的类型转换,存在一个语法结构,类型转换支持十进制、二进制、八进制和十六进制

var a = '111sdfsf'

Number(a) // NaN

parseInt(a) // 111

parseFloat(a) // 111

var b = '1112'

var numb = +b // 1112

parseInt 会忽略非数字字符,不支持科学计数法。

建议在任何环境下,都传入 parseInt 的第二个参数,明确指定转换的进制数,以免出现错误

而 parseFloat 则直接把源字符串作为十进制来解析,他不会引入任何的其他进制,可以放心使用

NumberToString

var a = 111

var stra = a + ''

装箱操作

每一种基本类型 Number、String、Boolean、Symbol 在对象中都有对应的类,所谓装箱转换,就是把基本类型转换为对应的对象,他是类型转换中一种相当重要的种类

对于全局 Symbol 函数无法使用 new 类调用,但我们可以利用函数的 call 方法来强迫其产生装箱操作。

var symbolTest = Symbol('a')

var symbolObject = (function(){return this;}).call(symbolTest)

console.log(typeof symbolObject) // object

console.log(symbolObject instanceof Symbol) // true

console.log(symbolObject.constructor === Symbol) // true

装箱机制会频繁产生临时对象,在一些对性能要求较高的场景下,我们应该尽量避免对基本类型进行装箱转换

每一类装箱对象皆有私有的 Class 属性,这些属性可以使用 Object.prototype.toString 获取

var symbolObject = Object(Symbol('a'))

console.log(Object.prototype.toString.call(symbolObject)) // [object Symbol]

在 JavaScript 中,没有任何方法可以更改私有的 Class 属性,因此Object.prototype.toString是可以准确识别对象的基本类型的方法,比 instanceof 更加准确

拆箱转换

在JavaScript标准中,规定了ToPrimitive函数,它是对象类型到基本类型的转换(即,拆箱转换)

对象到String和Number的转换都遵循了先拆箱再转换的规则。通过拆箱转换,把对象变为基本类型,再从基本类型转换为对应的String或者Number。

拆箱转换会尝试调用valueOf和toString来获得拆箱后的基本类型。如果valueOf和toString都不存在,或者没有返回基本类型,则会产生类型错误 TypeError

var o = {

valueOf: ()=> {console.log("valueOf"); return {}},

toString: ()=>{console.log('toString'); return {}}

}

o * 2

// valueOf

// toString

// TypeError

上面代码中先执行了valueOf方法,然后执行了toString方法,最后抛出了一个TypeError,说明这个拆箱转换失败了。

喜欢的话,记得关注我的公众号哦!

你的喜欢是我坚持的动力!

标签: #js不属于基本类型的是