js 各种数据类型的运算

本来只是一个基础的数据类型比较,后面发现涉及的东西还挺多,越扯越长。。。

一、基础知识:

来源:
阮一峰的博客-数据的比较
阮一峰的博客-数据类型的转换
我自己画的图们:
在这里插入图片描述

1 JS的基本(原始)数据类型:

Undefined、Null、Boolean、Number、String。要比较相等性之前,不能将 null 和 undefined 转换成其他任何值,但要记住 null == undefined 会返回 true 。(详见javascript高级程序设计);undefined 是 Undefined 类型; null 是 Null 类型,undefined 派生于 null; Undefined、Null、Boolean 作为 JavaScript 的5个基本数据类型的3个,因此 null 和 defined 当然既不等于 false 也不等于 true,数据类型都不一样。 只是 undefined 用于表示未定义的变量, null 用于表示空对象指针,null 着重于表示对象。 因此 typeof undefined 输出结果为 Undefined 类型,typeof null 输出结果为 Object 类型。

2 运算的规则:

所有的运算,都是对原始类型的值做的,如果运算子不是原始类型,则需要先转换数据类型

二、扫盲-数据类型的转换:

2.1 强制转换

强制转换主要指使用Number()、String()和Boolean()三个函数,手动将各种类型的值,分别转换成数字、字符串或者布尔值。

2.1.1 Number():
2.1.1.1 Number() && 原始数据类型

Number函数将字符串转为数值,要比parseInt函数严格很多。基本上,只要有一个字符无法转成数值,整个字符串就会被转为NaN。另外,parseInt和Number函数都会自动过滤一个字符串前导和后缀的空格。(这个关注undefined 和 null 的转化就可以了);

	// 数值:转换后还是原来的值
	Number(324) // 324
	// 字符串:如果可以被解析为数值,则转换为相应的数值
	Number('324') // 324
	// 字符串:如果不可以被解析为数值,返回 NaN
	Number('324abc') // NaN
	// 空字符串转为0
	Number('') // 0
	// 布尔值:true 转成 1,false 转成 0
	Number(true) // 1
	Number(false) // 0
	// undefined:转成 NaN
	Number(undefined) // NaN
	// null:转成0
	Number(null) // 0
2.1.1.2 Number() && 对象数据类型

简单的规则是,Number方法的参数是对象时,将返回NaN,除非是包含单个数值的数组。

之所以会这样,是因为Number背后的转换规则比较复杂。
第一步,调用对象自身的valueOf方法。如果返回原始类型的值,则直接对该值使用Number函数,不再进行后续步骤。
第二步,如果valueOf方法返回的还是对象,则改为调用对象自身的toString方法。如果toString方法返回原始类型的值,则对该值使用Number函数,不再进行后续步骤。
第三步,如果toString方法返回的是对象(不是原始类型的值),就报错。
默认情况下,对象的valueOf方法返回对象本身,所以一般总是会调用toString方法,而toString方法返回对象的类型字符串(比如[object Object])。

Number({a: 1}) // NaN
Number([1, 2, 3]) // NaN
Number([5]) // 5
2.1.2 String():

String函数可以将任意类型的值转化成字符串,转换规则如下。

2.1.2.1 String()&&原始类型值
	String(123) // "123" 数值:转为相应的字符串。
	String('abc') // "abc" 字符串:转换后还是原来的值。
	String(true) // "true" 布尔值:true转为字符串"true",false转为字符串"false"。
	String(undefined) // "undefined" undefined:转为字符串"undefined"。
	String(null) // "null" null:转为字符串"null"。
2.1.2.2 String()&&对象

String方法的参数如果是对象,返回一个类型字符串;如果是数组,返回该数组的字符串形式。

String方法背后的转换规则,与Number方法基本相同,只是互换了valueOf方法和toString方法的执行顺序
先调用对象自身的toString方法。如果返回原始类型的值,则对该值使用String函数,不再进行以下步骤。
如果toString方法返回的是对象,再调用原对象的valueOf方法。如果valueOf方法返回原始类型的值,则对该值使用String函数,不再进行以下步骤。
如果valueOf方法返回的是对象,就报错。

String({a: 1}) // "[object Object]"
String([1, 2, 3]) // "1,2,3"
2.1.3 Boolean():

Boolean()函数可以将任意类型的值转为布尔值。它的转换规则相对简单:除了以下五个值(undefined、null、0(包含-0和+0)、NaN、’’(空字符串))的转换结果为false,其他的值全部为true。当然,true和false这两个布尔值不会发生变化。

注意,所有对象(包括空对象)的转换结果都是true,甚至连false对应的布尔对象new Boolean(false)也是true(详见《原始类型值的包装对象》一章)。所有对象的布尔值都是true,这是因为 JavaScript 语言设计的时候,出于性能的考虑,如果对象需要计算才能得到布尔值,对于obj1 && obj2这样的场景,可能会需要较多的计算。为了保证性能,就统一规定,对象的布尔值为true。

	Boolean(undefined) // false
	Boolean(null) // false
	Boolean(0) // false
	Boolean(NaN) // false
	Boolean('') // false
	Boolean(true) // true
	Boolean(false) // false
2.2 自动转换

自动转换,它是以强制转换为基础的。遇到以下三种情况时,JavaScript 会自动转换数据类型,即转换是自动完成的,用户不可见

2.2.1. 第一种情况,不同类型的数据互相运算。
2.2.1.1 算数运算符:加、减、乘、除、余数、指数、自增、自减、数值、负数值。

重点关注:
1、加法运算符(+ 什么时候遇到了字符串,什么时候就会转成字符串)
运算子是基础数据类型:
加法运算符是在运行时决定,到底是执行相加,还是执行连接。也就是说,运算子的不同,导致了不同的语法行为,这种现象称为 “重载”(overload)。

'3' + 4 + 5 // "345"
3 + 4 + '5' // "75"

运算子是对象:
如果运算子是对象,必须先转成原始类型的值,然后再相加。( 先valueof()再tostring() )这里有一个特例,如果运算子是一个Date对象的实例,那么会优先执行toString方法。

var obj = new Date();
obj.valueOf = function () { return 1 };
obj.toString = function () { return 'hello' };

obj + 2 // "hello2"

2、余数运算符(运算结果的正负号由第一个运算子的正负号决定。为了得到负数的正确余数值,可以先使用绝对值函数。Math.abs() )
3、自增、自减运算符:自增和自减运算符,是一元运算符,只需要一个运算子。它们的作用是将运算子首先转为数值,然后加上1或者减去1。它们会修改原始变量。这种效应叫做运算的副作用(side effect)。自增和自减运算符是仅有的两个具有副作用的运算符,其他运算符都不会改变变量的值。
自增和自减运算符有一个需要注意的地方,就是放在变量之后,会先返回变量操作前的值,再进行自增/自减操作;放在变量之前,会先进行自增/自减操作,再返回变量操作后的值。

var x = 1;
var y = 1;
x++ // 1
++y // 2

4、数值、负数值运算符
数值运算符的作用在于可以将任何值转为数值(与Number函数的作用相同)。
5、指数运算符
指数运算符(**)完成指数运算,前一个运算子是底数,后一个运算子是指数。
注意,指数运算符是右结合,而不是左结合。即多个指数运算符连用时,先进行最右边的计算。

2 ** 4 // 16
2 ** 3 ** 2 // 512 // 相当于 2 ** (3 ** 2)

6、赋值运算符

// 等同于 x = x + y与算术运算符的结合
x += y
// 等同于 x = x >> y  与位运算符的结合
x >>= y
2.2.1.2 比较运算符:非相等运算符、严格相等运算符、严格不相等运算符、相等运算符、不相等运算符

重点关注:8个比较运算符

> 大于运算符
< 小于运算符
<= 小于或等于运算符
>= 大于或等于运算符
== 相等运算符
=== 严格相等运算符
!= 不相等运算符
!== 严格不相等运算符

表:
在这里插入图片描述
这八个比较运算符分成两类:相等比较非相等比较
一、非相等的比较:
1、两个运算子都是字符串:
按照字典顺序比较(实际上是比较 Unicode 码点);否则,将两个运算子都转成数值,再比较数值的大小。
2、非字符串的比较
(1)如果两个运算子都是原始类型的值,则是先转成数值再比较。(这里需要注意与NaN的比较。任何值(包括NaN本身)与NaN比较,返回的都是false。)
(2)如果运算子是对象,会转为原始类型的值,再进行比较。

//如果两个运算子都是原始类型的值,则是先转成数值再比较
5 > '4' // true
// 等同于 5 > Number('4')
// 即 5 > 4

//如果运算子是对象,会转为原始类型的值,再进行比较。
var x = [2];
x > '11' // true
// 等同于 [2].valueOf().toString() > '11'
// 即 '2' > '11'

x.valueOf = function () { return '1' };
x > '11' // false
// 等同于 [2].valueOf() > '11'
// 即 '1' > '11'

二、严格相等运算符
简单说,它们的区别是相等运算符(==)比较两个值是否相等,严格相等运算符(===)比较它们是否为“同一个值”。如果两个值不是同一类型,严格相等运算符(===)直接返回false,而相等运算符(==)会将它们转换成同一个类型,再用严格相等运算符进行比较。
严格相等运算符的算法
(1)不同类型的值 - 如果两个值的类型不同,直接返回false。
(2)同一类的原始类型值(数值、字符串、布尔值)比较时,值相同就返回true,值不同就返回false。

NaN === NaN  // false
+0 === -0 // true

(3)复合类型值
两个复合类型(对象、数组、函数)的数据比较时,不是比较它们的值是否相等,而是比较它们是否指向同一个地址。
复合类型的值,严格相等运算比较的是,它们是否引用同一个内存地址,而运算符两边的空对象、空数组、空函数的值,都存放在不同的内存地址,结果当然是false
注意,对于两个对象的比较,严格相等运算符比较的是地址,而大于或小于运算符比较的是值。

{} === {} // false
[] === [] // false
(function () {} === function () {}) // false

var v1 = {};
var v2 = v1;
v1 === v2 // true

var obj1 = {};
var obj2 = {};
obj1 > obj2 // false
obj1 < obj2 // false
obj1 === obj2 // false
//上面的三个比较,前两个比较的是值,最后一个比较的是地址,所以都返回false。

(4)undefined 和 null
undefined和null与自身严格相等。(由于变量声明后默认值是undefined,因此两个只声明未赋值的变量是相等的。)

undefined === undefined // true
null === null // true

三、严格不相等运算符
严格相等运算符有一个对应的“严格不相等运算符”(!==),它的算法就是先求严格相等运算符的结果,然后返回相反值。

1 !== '1' // true
// 等同于
!(1 === '1')

四、相等运算符
相等运算符用来比较相同类型的数据时,与严格相等运算符完全一样
比较不同类型的数据时,相等运算符会先将数据进行类型转换,然后再用严格相等运算符比较。下面分成四种情况,讨论不同类型的值互相比较的规则。
(1)原始类型值
原始类型的值会转换成数值再进行比较。
(2)对象与原始类型值比较
对象(这里指广义的对象,包括数组和函数)与原始类型的值比较时,对象转换成原始类型的值,再进行比较。

// 对象与数值比较时,对象转为数值
[1] == 1 // true
// 等同于 Number([1]) == 1

// 对象与字符串比较时,对象转为字符串
[1] == '1' // true
// 等同于 String([1]) == '1'
[1, 2] == '1,2' // true
// 等同于 String([1, 2]) == '1,2'

// 对象与布尔值比较时,两边都转为数值
[1] == true // true
// 等同于 Number([1]) == Number(true)
[2] == true // false
// 等同于 Number([2]) == Number(true)

(3)undefined 和 null
undefined和null与其他类型的值比较时,结果都为false,它们互相比较时结果为true。

false == null // false
false == undefined // false
0 == null // false
0 == undefined // false
undefined == null // true

(4)相等运算符的缺点
相等运算符隐藏的类型转换,会带来一些违反直觉的结果。

五、不相等运算符
相等运算符有一个对应的“不相等运算符”(!=),它的算法就是先求相等运算符的结果,然后返回相反值。

2.2.2. 第二种情况,对非布尔值类型的数据求布尔值。
2.2.3. 第三种情况,对非数值类型的值使用一元运算符(即+和-)。

自动转换的规则是这样的:预期什么类型的值,就调用该类型的转换函数。比如,某个位置预期为字符串,就调用String函数进行转换。如果该位置即可以是字符串,也可能是数值,那么默认转为数值。

	123 + 'abc' // "123abc"
	if ('abc') {
	  console.log('hello')
	}  // "hello"
	+ {foo: 'bar'} // NaN
	- [1, 2, 3] // NaN
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
本版中只有一个用于生产环境的文件:BigDecimal-all-last.min.js,大小为26K,如果WEB服务器打开GZIP压缩,可以减小至7K,如需完整版本请移步至:http://download.csdn.net/detail/aquaqu2009/4575230 简单用法: var scale = 20; var e = new BigDecimal("0"); var denominator = new BigDecimal("1"); var eBefore = new BigDecimal("-1"); var iteration = 1; while (!e.equals(eBefore)) { eBefore = e; e = e.add(BigDecimal.prototype.ONE.divide(denominator, scale, BigDecimal.prototype.ROUND_HALF_UP)); denominator = denominator.multiply(new BigDecimal(iteration+'')); ++iteration; } equal(e.toString(), "2.71828182845904523536"); ok(new BigDecimal("1234.5678").isPositive(), "1234.5678 is positive"); ok(new BigDecimal("-1234.5678").isNegative(), "-1234.5678 is negative"); ok(!BigDecimal.prototype.ZERO.isPositive() && !BigDecimal.prototype.ZERO.isNegative(), "BigDecimal.prototype.ZERO is neither positive nor negative"); ok(BigDecimal.prototype.ZERO.isZero(), "BigDecimal.prototype.ZERO is zero"); ok(new BigDecimal("1234.0000").isLessThan(new BigDecimal("1234.5678")) && new BigDecimal("1234.0000").isLessThanOrEqualTo(new BigDecimal("1234.5678")), "1234.0000 is less than 1234.5678"); ok(!new BigDecimal("1234.0000").isGreaterThan(new BigDecimal("1234.5678")) && !new BigDecimal("1234.0000").isGreaterThanOrEqualTo(new BigDecimal("1234.5678")), "1234.0000 is not greater than 1234.5678"); ok(new BigDecimal("1234.5678").isGreaterThan(new BigDecimal("1234.0000")) && new BigDecimal("1234.5678").isGreaterThanOrEqualTo(new BigDecimal("1234.0000")), "1234.5678 is greater than 1234.0000"); ok(!new BigDecimal("1234.5678").isLessThan(new BigDecimal("1234.0000")) && !new BigDecimal("1234.5678").isLessThanOrEqualTo(new BigDecimal("1234.0000")), "1234.5678 is not less than 1234.0000"); ok(new BigDecimal("1234.5678").isLessThanOrEqualTo(new BigDecimal("1234.5678")) && new BigDecimal("1234.5678").isGreaterThanOrEqualTo(new BigDecimal("1234.5678")), "1234.5678 is less than or equal to itself as well as greater than or equal to itself"); 别整个复制粘贴啊,那样是运行不起来的,请粘贴您需要的代码,,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值