重学前端-模块一Javascript 1-9讲

关于类型的细节

关于Javascript的类型,各种文档介绍的已经很全面了,也是前端开发人员最熟悉的概念之一,但如果对下面的几个问题还有犹豫,说明对于类型这部分知识点,还是有遗漏部分的。

为什么有的编程规范要求用 void 0 代替 undefined?

字符串有最大长度吗?

String有最大长度2^53-1,但是这个所谓的最大长度并不是字符数。
String的意义并非“字符串”,而是字符串的UTF16编码,字符串操作charAt, charCodeAt, length等方法针对的都是UTF16编码,所以字符串的最大长度,实际上是受字符串的编码长度影响的。
JavaScript 中的字符串是永远无法变更的,一旦字符串构造出来,无法用任何方式改变字符串的内容,所以字符串具有值类型的特征。

0.1 + 0.2 ≠ 0.3 ?

Javascript的Number类型表示通常意义上的“数字”。大致对应数学中的有理数,但是计算机有精度限制。
avaScript 中的 Number 类型基本符合 IEEE 754-2008 规定的双精度浮点数规则。(Javascript并未定义不同类型的数字数据类型,而是始终将数字存储为双精度浮点值)
根据双精度浮点数的定义,Number 类型中有效的整数范围是 -0x1fffffffffffff 至 0x1fffffffffffff,所以 Number 无法精确表示此范围外的整数。
同样根据浮点数的定义,非整数的 Number 类型无法用 ===== 也不行) 来比较。

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

对于计算机而言,两个数字在相加时是以二进制形式进行的,在呈现结果时才转换成十进制。所以在计算0.1+0.2时,会先把两个数字转换为二进制数字,转二进制的时候如果尾数的52位不能完全满足,只会达到要求的精度。

// 0.1 转化为二进制
0.0 0011 0011 0011 0011...(0011无限循环)
// 0.2 转化为二进制
0.0011 0011 0011 0011 0011...(0011无限循环)
//由于双精度表示法的尾数只有52位,0.1和0.2转换后的值为
e = -4; m =1.1001100110011001100110011001100110011001100110011010 (52)
e = -3; m =1.1001100110011001100110011001100110011001100110011010 (52)

两个二进制相加的结果为:

//相加时如果指数不一致,需要对齐,一般情况下是向右移,因为最右边的即使溢出了,损失的精度远远小于左边溢出。
  (e = -3; m = 0.1100110011001100110011001100110011001100110011001101)
  + (e = -3; m = 1.1001100110011001100110011001100110011001100110011010)

=  (e = -3; m = 10.0110011001100110011001100110011001100110011001100111)
=  (e = -2; m = 1.0011001100110011001100110011001100110011001100110100)
= 0.010011001100110011001100110011001100110011001100110100
= 0.30000000000000004  //(十进制)

浮点数运算的精度问题导致等式左右的结果并不是严格相等,而是相差了个微小的值0.300000000000000040.3
用Javascript提供的最小精度值比较可得到结果为true

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

ES6 新加入的 Symbol 是个什么东西?

Symbol 是 ES6 中引入的新类型,它是一切非字符串的对象 key 的集合,在 ES6 规范中,整个对象系统被用 Symbol 重塑。Symbol 可以创建一个独一无二的值(但并不是字符串)。
Symbol 可以具有字符串类型的描述,但是即使描述相同,Symbol 也不相等。
创建Symbol的方式是使用全局的Symbol函数。

var mySymbol = Symbol("my symbol");

为什么给对象添加的方法能用在基本类型上?

在Javascript中,对象的定义是“属性的集合”,属性分为数据属性和访问器属性,二者都是key-value结构,key可以是字符串或Symbol类型。
Javascript的基本类型,都在对象类型中有一个“亲戚”,分别是Number,String,Boolean,Symbol,所以3new Number(3)是完全不同的值,一个是Number类型,一个时对象类型。
Javascript的.运算符提供了装箱操作,会根据基础类型构造一个临时的对象,使得我们能在基础类型上调用对应对象的方法。
所谓装箱转换,就是把基本类型转换为对应的对象,它是类型转换中相当重要的种类。

Javascript对象

对 JavaScript 来说,属性并非只是简单的名称和值,JavaScript 用一组特征(attribute)来描述属性(property)。
数据属性:
它比较接近于其它语言的属性概念。数据属性具有四个特征。

  • value:就是属性的值。
  • writable:决定属性能否被赋值。
  • enumerable:决定 for in 能否枚举该属性
  • configurable:决定该属性能否被删除或者改变特征值。在大多数情况下,我们只关心数据属性的值即可。第
    访问器(getter/setter)属性,它也有四个特征:
  • getter:函数或 undefined,在取属性值时被调用
  • setter:函数或 undefined,在设置属性值时被调用
  • enumerable:决定 for in 能否枚举该属性
  • configurable:决定该属性能否被删除或者改变特征值。
    Javascript的对象分为几类:
  • 宿主对象(host Objects):由 JavaScript 宿主环境提供的对象,它们的行为完全由宿主环境决定。(如window对象)
    • 内置对象(Built-in Objects):由 JavaScript 语言提供的对象。
    • 固有对象(Intrinsic Objects ):由标准规定,随着 JavaScript 运行时创建而自动创建的对象实例。
    • 原生对象(Native Objects):可以由用户通过 Array、RegExp 等内置构造器或者特殊语法创建的对象。
    • 普通对象(Ordinary Objects):由{}语法、Object 构造器或者 class 关键字定义类创建的对象,它能够被原型继承。

Javascript执行

异步执行的顺序:

  • 首先我们分析有多少个宏任务;
  • 在每个宏任务中,分析有多少个微任务;
  • 根据调用次序,确定宏任务中的微任务执行次序;
  • 根据宏任务的触发规则和调用次序,确定宏任务的执行次序;
  • 确定整个顺序。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章