资讯专栏INFORMATION COLUMN

你不知道的JavaScript :值

0x584a / 2761人阅读

摘要:你不知道的系列第二章值值数组里面的数组可以容纳任何类型的值。数字中,没有真正意义上的整数,目前只有数字类型。较小的数值二进制浮点数最大的问题从数学的角度来说,此处应该是,但是二进制浮点数中与并不是十分准确,他们相加等于,所以结果为。

你不知道的JavaScript系列---第二章:值

2.1 数组

JavaScript里面的数组可以容纳任何类型的值。

"稀疏"数组(含有空白或空缺单元的数组)

var a = []
a[0] = 1
a[2] = [3]
a[1] // undefined
a.length // 3

其中,a[1]隐式赋值为undefined

索引
数组通过数字进行索引,但JavaScript中的数组也是对象,也可以通过字符串键值进行索引(但不计算在数组长度内)

var a = []
a[0] = 1
a["foobar"] = 2

a.length // 1
a["foobar"] // 2
a.foobar // 2

当字符串键值可以强制性转换为十进制数字的话,它就会被当做数字索引处理

var a = []
a["12"] = 1
a.length // 13

当然我们不建议这么做(在数组中加入字符串键值/属性),通常要存放字符串键值/属性,尽量使用对象,数组存放数字索引值

类数组
即一系列通过数字索引的值,如:es6之前的arguments对象(类数组),可以通过工具函数将它转换为真正的数组

function foo () {
    var arr = Array.prototype.slice.call(arguments)
    arr.push("amm")
    console.log(arr)
}
foo("foo","bar") // ["foo","bar","amm"]

ES6中的Array.from(...)也可以实现同样功能

...
var arr = Array.from(arguments)
...

2.2 字符串

字符串经常被当成字符数组,但它与数组又有极大的不同,我感觉连类数组也算不上,只是看上去相似而已。
例如下面两个值

var a = "foo"
var b = ["f","o","o"]

但是它们两的确很相似,都有length属性,indexOf(...)以及concat(...)方法

a.length // 3
b.length // 3
a.indexOf("o") // 1
b.indexOf("o") // 1
var c = a.concat("bar") // foobar
var d = b.concat(["b","a","r"]) // ["f","o","o","b","a","r"]
a === c // false
b === d // false
a // foo
b // ["f","o","o"]

但是它们又有很多不同

a[1] = "O"
b[1] = "0"
a // foo
b // ["f","O","o"]

在JavaScript中,字符串是不可变的数组可变,并且a[1]并不是合法语法(老版本IE不支持),正确的应该是a.charAt(1)
字符串不可变是指字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串,而数组的成员函数都是在其原始值上进行操作。

var c = a.toUpperCase()
a === c // fasle
a // foo
c // FOO

b.push("!")
b // ["f","o","o", "!"]
2.3 数字

JavaScript中,没有真正意义上的整数,目前只有数字类型(number)

2.3.1 较小的数值

二进制浮点数最大的问题:

0.1 + 0.2 === 0.3 // false

从数学的角度来说,此处应该是true,但是二进制浮点数中0.1与0.2并不是十分准确,他们相加等于0.30000000000000004,所以结果为false。
那么我们如何来判断0.1 + 0.2 和 0.3 是否相等呢?
最常见的方法是设置一个机器误差,对于JavaScript中的数字来说,这个值通常是2^-52.
ES6开始,该值定义在Number.EPSILON中,在指定误差范围内,比较两个数是否相等:

function numbersCloseEnoughEqual(n1, n2) {
    return Math.abs( n1 - n2 ) < Number.EPSILON
}
const a = 0.1 + 0.2
const b = 0.3
numbersCloseEnoughEqual(a, b) // true
numbersCloseEnoughEqual(0.0000001, 0.0000002)
2.3.2 特殊数值

JavaScript中有几个特殊的值,需要开发者特别注意和小心使用。

不是数字的数字
NaN:not a number(不是一个数字:无效数值、失败数值、坏数值)

const a = 2 / "foo" // NaN
typeOf a === number // true

在这里NaN是指执行数学运算没有成功,这是失败后返回的结果
也许你会认为,判断一个数字是否是NaN,只需要将它与NaN作比较就行,如:

2 / "foo" === NaN //false

NaN是一个特殊值,它与自身不相等,唯一一个非自反(x === x 不成立)的值。而
NaN != NaNtrue
那么我们可以使用工具函数Number.isNaN(...)来判断一个值是否是NaN。

零值
JavaScript中有一个常规的0和一个-0

var a = 0 / -1 // -0
var b = 0 * -3 // -0

加减法不会得到-0
那么如何区分他们呢?

function isNegZero(n) {
    n= Number(n)
    return (n === 0) && (1 / n === -Infinity)
}
isNegZero(-0) // true
isNegZero(0 / -2) // true
isNegZero(0) //false

Infinity:无穷数
那么为什么要存在一个-0?有些应用程序中的数据需要以级数形式来表示(如动画帧的移动速度),数字的符号位代表特殊信息(如移动的方向)

2.4 值和引用

对于赋值与参数的传递可以通过对值复制,或者引用复制来完成,取决于具体的语法。
那么在JavaScript中,我们看一个例子:

var a = 2
var b = a // b 是 a 的一个副本
b ++
a // 2 
b // 3

var c = [1, 2, 3]
var d = c // d 是 [1, 2, 3] 的一个引用
d.push(4)
c // [1, 2, 3, 4]
d // [1, 2, 3, 4]

简单值(基本类型)总是用过值复制的方式赋值/传递
复合值————对象和函数,则是通过引用复制的方式来复制/传递


在JavaScript中,引用指向的是值本身而非变量,所以一个引用无法改变另一个引用的指向:

var a = [1,2,3]
var b = a
a // [1,2,3]
b // [1,2,3]

// 然后
b = [4,5,6]
a // [1,2,3]
b // [4,5,6]

b=[4,5,6]并不影响a的指向[1,2,3],除非b指向的是a的指针,但JavaScript中不存在指针,就不存在这个情况!


那么下列情况,你也许也会明白了:

function foo(x){
    x.push(4)
    x // [1,2,3,4]
    
    x = [4,5,6]
    x.push(7)
    x // [4,5,6,7]
}

var a = [1,2,3]

foo(a)

a // [1,2,3,4]

在函数参数传递时,实际上是将a的引用的一个复制品赋值给x,通过复制的引用即x更改数组的值,也会影响到a,所以a被改变为[1,2,3,4],但是将x指向到另一个引用[4,5,6],是不会影响到a的指向的,所以a还是[1,2,3,4]

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/94990.html

相关文章

  • 精读《你不知道javascript(中卷)》

    摘要:强制类型转换本章介绍了的数据类型之间的转换即强制类型转换包括显式和隐式。强制类型转换常常为人诟病但实际上很多时候它们是非常有用的。隐式强制类型转换则没有那么明显是其他操作的副作用。在处理强制类型转换的时候要十分小心尤其是隐式强制类型转换。 前言 《你不知道的 javascript》是一个前端学习必读的系列,让不求甚解的JavaScript开发者迎难而上,深入语言内部,弄清楚JavaSc...

    李世赞 评论0 收藏0
  • 你不知道JavaScript》 (中) 阅读摘要

    摘要:这时候控制台看到的是对象的快照,然而点开看详情的话是这段代码在运行的时候,浏览器可能会认为需要把控制台延迟到后台,这种情况下,等到浏览器控制台输出对象内容时,可能已经运行,因此会在点开的时候显示,这是的异步化造成的。 本书属于基础类书籍,会有比较多的基础知识,所以这里仅记录平常不怎么容易注意到的知识点,不会全记,供大家和自己翻阅; 上中下三本的读书笔记: 《你不知道的JavaScri...

    stackvoid 评论0 收藏0
  • 你不知道javascript》笔记_this

    下一篇:《你不知道的javascript》笔记_对象&原型 写在前面 上一篇博客我们知道词法作用域是由变量书写的位置决定的,那this又是在哪里确定的呢?如何能够精准的判断this的指向?这篇博客会逐条阐述 书中有这样几句话: this是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式当一个函数被调用时...

    cpupro 评论0 收藏0
  • 你不知道JavaScript : 类型

    摘要:你不知道的系列第一章类型类型一中的类型中的变量是不存在类型的,只有具体的值才有类型。 你不知道的JavaScript系列---第一章:类型 类型 一、JavaScript中的类型 JavaScript中的变量是不存在类型的,只有具体的值才有类型。 Js不像其他高级语言,如java等,声明了一个int类型的变量,就必须存放int类型的值,Js中的变量可以存放其允许的所有类型的值,如: ...

    史占广 评论0 收藏0
  • 你不知道JavaScript(二)

    摘要:第三章原生函数有很多原生函数,为基本的数据类型值提供了封装对象,,,等。我们可以通过来查看所有返回的对象的内置属性这个属性无法直接访问。这个符号能有奇妙的功能,可以视为。通常用来把转换为数字,用来将转换为字符串,用来将取整。 第三章 原生函数JS有很多原生函数,为基本的数据类型值提供了封装对象,String,Number,Boolean等。我们可以通过{}.call.toStri...

    macg0406 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<