《重学前端》读后感(05|JavaScript类型:关于类型,有哪些你不知道的细节?)

先看5个问题:
1、为什么有的编程规范要求用void 0 代替 undefined?
2、字符串有最大长度吗?
3、0.1+0.2不是等于0.3么?为什么JavaScript里不是这样的?
4、ES6新加入的Symbol是个什么东西?
5、为什么给对象添加的方法能用在基本类型上?

JavaScript模块会从运行时、文法和执行过程三个角度去剖析JS的知识体系。
运行时类型是代码实际执行过程中我们用到的类型。所有类型数据都会属于7个类型之一。从变量、参数、返回值到表达式中间结果,任何的JavaScript代码运行过程中产生的数据,都具有运行时类型。

类型
JavaScript语言的每一个值都属于某一种数据类型。JavaScript语言规定了7种语言类型。语言类型广泛用于变量、函数参数、表达式、函数返回值等场合。根据最新的语言标准,这7种语言类型是:

1、Undefined
2、Null
3、Boolean
4、String
5、Number
6、Symbol(ES6新加)
7、Object

Undefined、Null

Undefined类型表示未定义,它的类型只有一个值,就是undefined。任何变量赋值是Undefined类型、值为undefined,一般我们可以用全局变量undefined来表达这个值,或者void运算把任一一个表达式变成undefined值。

但是呢,undefined是一个变量,而并非是一个关键字,这也是JavaScript公认的设计失误之一,所以,为了避免无意中被篡改,建议使用void 0来获取undefined值。

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

Null类型也只有一个值null,null是关键字,所以在任何代码中都可以放心用null关键字来获取null的值。

Boolean

Boolean类型有两个值,true和false,表示逻辑意义上的真和假,同时也是两个关键字。

String

String用来表示文本数据。String有最大长度2^53 - 1,有趣的是这个最大长度,并不完全是你理解的字符数。
因为String的意义并非“字符串”,而是字符串的UTF16编码,字符串的操作charAt、charCodeAt、length等方法针对的都是UTF16编码。所以,字符串的最大长度,实际上是受字符串的编码长度影响的。

现行的国际标准,字符是以Unicode的方式表示的,每一个Unicode的码点表示一个字符。
理论上,Unicode的范围是无限的。
UTF是Unicode的编码方式,规定了码点在计算机中的表示方法,
常见的有UTF16和UTF8。
Unicode的码点通常用U+???来表示,其中???是十六进制的码点值。
0-65536(U+0000 - U+FFFF)的码点被称为基本字符区域(BMP)

JavaScript中的字符是用于无法变更的,一旦字符串被构造出来,无法用任何方式改变字符串的内容,所以字符串具有值类型的特征。
JavaScript字符串把每个UTF16单元当作一个字符来处理,所以处理非BMP(超过U+0000 - U+FFFF范围)的字符时,应该格外小心。
JavaScript的这个设计继承自Java,最新的标准中是这样解释的:为了性能和尽可能实现起来简单。因为现实中很少用到BMP之外的字符。

Number

Number类型有18437736874454810627(即:2^64 - 2^53 + 3)个值。
Number类型基本符合IEEE 754-2008规定的双精度浮点规则,但是JavaScript为了表达几个额外的语言场景(比如不让除以0出错,引入无穷大概念),规定了几个例外情况:
1、NaN,占用了9007199254740990,这原本符合IEEE规则的数字。
2、Infinity,无穷大。
3、-Infinity,负无穷大。
另外,值得注意的是,JavaScript有+0和-0之分,加法没有区别,在除法中的场合就要进行特别的区分,“忘记检测除以0,而得到负无穷大”的情况经常会导致错误,而区分+0和-0的方式,正是检测1/x是Infinity还是-Infinity。
根据双精度浮点数的定义,Number中有效的整数范围是-0x1fffffffffffff 至 0x1fffffffffffff,所以Number无法精确表示此范围外的整数。
同样根据浮点数定义,非整数的Number类型无法用==(===也不行)来比较。

  console.log( 0.1 + 0.2 == 0.3);

输出结果是false,说明两边不对等,这是浮点运算的特点,浮点数运算的精度问题导致等式左右的结果并不是严格的相等,而是相差了微小的值。
所以实际上,错误的不是结论,而是比较的方法,JavaScript提供最小精度值的比较方法:

  console.log( Math.abs(0.1 + 0.2 - 0.3) <= Number.EPSILON);

检查等式两边差的绝对值是否小于最小精度,这才是正确的比较浮点数的方法。输出结果为true。

Symbol

Symbol是ES6中引入的新类型,它是一切非字符串对象的key集合,在ES6规范中,整个对象系统被用Symbol重塑。
Symbol具有字符串类型的描述,即使描述相同,Symbol也不相等。
我们创建Symnol的方式是使用全局Symbol函数,例如:

var mySymbol = Symbol("my Symbol")

一些标准中提到的Symbol,可以在全局的Symbol函数属性中找到,例如,可以用Symbol.iterator来自定义for...of在对象上的行为:

var o = new Object
o[Symbol.iterator] = function({
  var v = 0
  return {
    next:function(){
      return { value : v++; done : v > 10}
    }
  } 
})
for(var v of o){
  console.log(v)  // 0 1 2 3 ... 9
}

Object

Object表示对象的意思,是一切有形和无形的物体的总称。在JavaScript中,对象的定义是“属性的集合”。属性分为数据属性和访问器属性,二者都是key-value结构,key可以是字符串或者Symbol类型。
提到对象,就必须提到一个概念——类。JavaScript中的“类”仅仅是运行时对象的一个私有属性,而JavaScript中是无法自定义类型的。
JavaScript中的几个基本类型,在对象类型中有一个“亲戚”,它们是:

  Number
  String
  Boolean
  Symbol

所以我们就必须认识到3与new Number(3)是完全不同的值,它们一个是Number类型,一个是对象类型。
Number、String和Boolean,三个构造器是两用的,当跟new搭配时,它们产生对象,当直接调用的时候,它们表示强制类型转换。
Symbol函数比较特殊,直接用new调用会抛出错误,但它仍然是Symbol的构造器。
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,有效

所以文章开头的问题,答案是:. 运算提供了装箱操作,它会根据基础类型构造一个临时对象,使得我们能在基础类型上调用对应对象的方法。

类型转换

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

最后上一张总结图


侵删
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容