JavaScript 的类型和值

JavaScript 的类型和值

1. 类型

1.1 七种内置类型

  • 空值(null)
  • 未定义(undefined)
  • 布尔值(boolean)
  • 字符串(string)
  • 数字(number)
  • 对象(object)
  • 符号(symbol)

符号(symbol)常作唯一标识,属于es6(ECMAScript2015)新增内容

对象类型 object之外其他的都是基本类型

1.2 typeof 运算符

注意:上述’七种类型’使用类型检测运算符typeof 得到的结果却不一定是他们本身~

观察以下代码:

typeof undefined === 'undefined' // true 
typeof 123 === 'number' // true
typeof '123' === 'string' // true
...
typeof null === 'null' // false
typeof null === 'object' // true 

正常来讲 typeof 可以正确获取类型。但是 null 无法获取到 null,而是 'object'。这是 JavaScript 的一个 bug,可能以后也不会修复了…

1.3 值和类型

你们会发现,JavaScript 中的变量是没有类型的,不能使用 String str = ‘123’ 来定义一个变量。在 js 中,只有值存在类型,对于一个变量,可以拥有任何类型。所以上述的 typeof 测试的并不是变量是什么类型,而是测试变量所拥有的值

1.3.1 undefined 和 undeclared

变量在无值时为 undefined,变量不存在时(在作用域未声明)为 undeclared

观察以下代码:

var hhh = 'a'
var xixixi 

typeof hhh === 'string' // true
hhh // 'a'

typeof xixixi = 'undefined' // true
xixixi // undefined

typeof hahaha === 'undefined' // true
hahaha //  ReferenceError: hahaha is  not defined

注意:undeclared 在浏览器里输出为 ReferenceError: xx is not defined,容易误解为 undefined,实际上应该输出为 xx is not found 或者 xx is not declared,同时 typeof 处理 undeclared 是输出 ‘undefined’ 的,这是不合理的,期待输出’undeclared’。

2. 值

2.1 数组

和其他强类型语言不同,在 JavaScript 中,数组可以容纳任何类型的值,可以是字符串、数字、对象(object),甚至是其他数组(多维数组就是通过这种方式来实现的)

var a = [ 1, "2", [3] ];
a.length; // 3
a[0] === 1; // true
a[2][0] === 3; // true

给数组设定值的时候无需预先设置大小,可以使用字面量的形式申明一个数组

var arr = []
arr[0] = 0
arr[2] = 2
arr[1] // undefined
arr.length = 3 // 虽然 arr[1] 为定义,但是数组长度 = 最大索引 - 1 

a[1] 的值为 undefined,但这与将其显式赋值为 undefined(a[1] = undefined)还是有所区别

使用 delete 运算符可以将元素从数组中删除,但是删除后,数组的 length 属性并不会发生变化。

如果字符串键值能够被强制类型转换为十进制数字的话,它就会被当作数字索引来处理。

在数组中加入 字符串键值 / 属性 并不是非常推荐。

var a = [ ];

a["13"] = 42;

a.length; // 14

类数组

类数组对象:是指在 JavaScript 中有一些对象可能并不是真正的数组,但它们可以表现得跟数组一样。比如说 arguments 对象或者 jQuery 选择元素集合等。它们可以通过 index 来访问元素,并且有 length 属性,但是缺少数组所拥有的其他方法,例如 push, pop,slice 等。

常见的类数组对象有:

  • JavaScript的arguments对象
  • DOM方法的返回结果,如 document.getElementsByTagName 或 document.childNodes
  • 字符串

类数组到数组的转换方法有:

  1. Array.prototype.slice.call()

    使用Array.prototype.slice.call()方法能将具有length属性的对象转成数组。

var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
var arr = Array.prototype.slice.call(arrayLike); // ['name', 'age', 'sex']
  1. Array.from()
    Array.from() 方法从一个类似数组或可迭代对象中创建一个新的,浅拷贝的数组实例。
let arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 };
let arr = Array.from(arrayLike); // ["name", "age", "sex"]
  1. 扩展运算符 “…”
    扩展运算符可以将某些数据结构转为用逗号分隔的参数序列。
let arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
let arr = [...arrayLike];  // ["name", "age", "sex"]

如果类数组没有 length 属性或者成员不是按照顺序排序的,上述方法可能不能很好的进行转换。在这种情况下,可能需要借助其他方法,例如添加元素到空数组中。

var array = Array.prototype.concat.apply([], arguments);

2.2 字符串

字符串和数组其实是有的类似的。

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

它们都是类数组,都有 length 属性以及 indexOf(…)(从 ES5开始数组支持此方法)和 concat(…) 方法

JavaScript 中字符串是不可变的,而数组是可变的。并且 a[1] 在 JavaScript 中并非总是合法语法,在老版本的 IE 中就不被允许(现在可以了)。正确的方法应该是 a.charAt(1)

字符串不可变是指字符串的成员函数不会改变其原始值,而是创建并返回一个新的字符串。而数组的成员函数都是在其原始值上进行操作。

示例:

字符串无法使用 Array.prototype.reverse()(因为它是不可变更的)

解决方案:

var str = '123'
var newStr = str
 // 将a的值转换为字符数组
 .split( "" )
 // 将数组中的字符进行倒转
 .reverse()
 // 将数组中的字符拼接回字符串
 .join( "" );
newStr; // '321'

2.3 数字

JavaScript 只有一种数值类型:number(数字),包括“整数”和带小数的十进制数。此处“整数”之所以加引号是因为和其他语言不同,JavaScript 没有真正意义上的整数,这也是js的‘特性’。

2.3.1 语法

  • JavaScript 中的数字常量一般用十进制表示
  • 数字前面的 0 可以省略
  • 小数点后小数部分最后面的 0 也可以省略
  • 特别大和特别小的数字默认用指数格式显示,与 toExponential() 函数的输出结果相同。
var a = 5E10;
a; // 50000000000

a.toExponential(); // "5e+10"

var b = a * a;
b; // 2.5e+21

var c = 1 / a;
c; // 2e-11
  • tofixed(..) 方法可指定小数部分的显示位数
var a = 42.59;
a.toFixed( 0 ); // "43"
a.toFixed( 1 ); // "42.6"
a.toFixed( 2 ); // "42.59"
a.toFixed( 3 ); // "42.590"
a.toFixed( 4 ); // "42.5900"
  • toPrecision(..) 方法用来指定有效数位的显示位数
var a = 42.59;
a.toPrecision( 1 ); // "4e+1"
a.toPrecision( 2 ); // "43"
a.toPrecision( 3 ); // "42.6"
a.toPrecision( 4 ); // "42.59"
a.toPrecision( 5 ); // "42.590"
a.toPrecision( 6 ); // "42.5900"
  • .运算法是有效的数字字符,会被优先识别为数字常量的一部分,然后才是对象的属性访问运算符
42.toFixed( 3 ); // SyntaxError

(42).toFixed( 3 ); // "42.000"
0.42.toFixed( 3 ); // "0.420"
42..toFixed( 3 ); // "42.000"
42 .toFixed(3); // "42.000" 不建议使用
  • 数字常量还可以用其他格式来表示,如二进制、八进制和十六进制
0xf3; // 243的十六进制
0Xf3; // 同上
0363; // 243的八进制
// es6 支持以下的格式
0o363; // 243的八进制
0O363; // 同上
0b11110011; // 243的二进制
0B11110011; // 同

2.3.2 数值边缘与机器精度(machine epsilon)

看以下代码:

它们相加的结果并非刚好等于0.3,而是一个比较接近的数字 0.30000000000000004,所以条件判断结果为 false

0.1 + 0.2 === 0.3; // false

以上结果是 JavaScript 无法完全精确呈现数字导致的~

那么怎么判断 0.1 + 0.2 和 0.3 是否相等呢?

最常见的方法是设置一个误差范围值,通常称为“机器精度”(machine epsilon),对JavaScript 的数字来说,这个值通常是 2^-52 (2.220446049250313e-16)

从 ES6 开始,该值定义在 Number.EPSILON 中,我们可以直接拿来用,也可以为 ES6 之前的版本写 polyfill:

if (!Number.EPSILON) {
 Number.EPSILON = Math.pow(2,-52);
}

可以使用 Number.EPSILON 来比较两个数字是否相等(在指定的误差范围内):

function numbersCloseEnoughToEqual(n1,n2) {
 return Math.abs( n1 - n2 ) < Number.EPSILON; // Math.abs 取绝对值
}
var a = 0.1 + 0.2;
var b = 0.3;
numbersCloseEnoughToEqual( a, b ); // true
numbersCloseEnoughToEqual( 0.0000001, 0.0000002 ); // false

2.3.3 检测整数

if (!Number.isInteger) {
 Number.isInteger = function(num) {
 return typeof num == "number" && num % 1 == 0;
 };
}

你可能感兴趣的:(JS高级,javascript,开发语言,ecmascript)