js类型转换比较

js比较

基本转换

你不知道的javascript中卷4.2

ToNumber

  • ToNumber 其中 true转换为1,false转换为0。undefined转换为NaN,null转换为0
    为了将值转换为相应的基本类型值,抽象操作ToPrimitive 会首先(通过内部操作DefaultValue)检查该值是否有valueOf() 方法。如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有,就使用toString()的返回值(如果存在)来进行强制转换

如果valueOf()和toString()均不返回基本类型值,会产生TypeError错误。

从ES5开始,使用Object.create(null)创建的对象[[Prototype]]的属性为null,并且没有valueOf(),toString()方法,因此无法进行强制类型转换。

ToBoolean

  1. 假值
    1.1. 可以被强制类型转换为false的值
    1.2 其他(被强制类型转换为true的值)
    以下这些是假值: undefined,null,‘’, +0/-0和NaN,false
    加值的布尔强制类型转换结果为false。
    理论上所有假值意外的值都是真值
  2. 假值对象
    var a = new Boolean(false);
    var b = new Number(0);
    var c = new String('');
    // 以上是封装了假值的对象,均为true
    
    document.all,是一个类数组对象,包含来所有元素,之前为true,现在为false
  3. 真值
    真值就是假值列表以外的值
var a = 'false';
var b = '0';
var c = "''";
var d = Boolean(a && b && c)
d; // true

var a = [];
var b = {};
var c = function () {};
var d = Boolean(a&& b&& c);
d; // true

特殊的函数

  • Function 重写了 toString()
  • Date 重写了 toString() 也重写了 valueOf()
  • Array 重写了 toString()

toString()

// Function
let fn = function () {}
console.log(fn == 'function () {}') //true
// 先转为valueOf,再把它转为toString(),
let fn = function    () {}
console.log(fn == 'function () {}') //false

// Array
let arr = [1,2,3,4,5,2,1,5,2,1,5]
console.log(arr == '1,2,3,4,5,2,1,5,2,1,5')//true

// Date
let date = new Date('2020-08-12')
console.log(date == 'Wed Aug 12 2020 08:00:00 GMT+0800 (中国标准时间)')//true

// Object
let obj1 = {},obj2 = {name:'name'}
console.log(obj2 == '[object Object]')//true

valueOf

let fn = function () {}
console.log(fn.valueOf() === fn)//true
let arr = [1,2,3,4,5,2,1,5,2, 1,5]
console.log(arr.valueOf() === arr)//Array也是返回自身

let obj = {}
console.log(obj.valueOf() === obj)//Object也是返回自身

let date = new Date('2020-08-12')
console.log(date.valueOf() === date)//false
let date = new Date('2020-08-12')
console.log(date.valueOf() === 1597190400000 )//true
// 返回的是从 1970 年 1 月 1 日午夜开始计的毫秒数。

宽松相等(loose equals)== 和严格相等(strict equals)===

  • ==允许在相等比较中进行类型转换,而=== 不允许

相等比较操作都性能

  • ==需要强制类型转换(仅仅微秒级差别)百万分之一秒

字符串和数字直接比较

var a = 42;
var b = '42';
a === b; // false
a == b; // true

因为没有强制类型转换,所以a===b`` 为false, 42和“42不相等”a == b`是宽松相等,即如果两个值的类型不同,则对其中之一或两者都进行强制类型转换;

具体转换规则

  1. a是数字,b是字符串,则b转换为数字进行比较
  2. a是字符串,b是数字,则a转换为数字进行比较

其他类型和布尔值之前相等比较

var a = '42';
var b = true;

a == b; // false

具体转换规则

  1. 如果a是布尔类型,则a转换为数字进行和b比较
  2. 如果b是布尔类型,则b转换为数字进行和a比较

以上分析可得,先将b转换为数字,Number(b) 为1,变成
‘42’ === 1 ,两者类型仍然不同,‘42’根据规则被强制类型转换为32,最后变成1 == 42,结果为false;b如果为true,结果仍为false;

var a = '42'
// 不要这样用,条件判断不成立
if (a === true) {
//..
}

// 也不要这样用,条件判断不成立
if (a === true{
}

// 这样的显式用法没问题
if (a){}

// 这样显示用法更好
if (!!a) {}

// 这样显式用法也好
if(Boolean(a)){}

null和undefined直接的相等比较

  1. 如果x为null,y为undefined,结果为true;
  2. 如果x为undefined,y为null,结果为true;
    ==中null和undefined相等(它们也与自身相等,除此之外其他值都不存在这种情况);
var a = null;
var b;

a == b; // true

a == null; // true
b == null; // true

// 以下为false

a == false;
b == false;
a == '';
b == '';
a == 0;
b == 0

对象和非对象之间的相等比较

  1. 如果x是字符串或数字,y是对象,测返回 x == ToPrimitive(y)的结果
  2. 如果y是字符串或数字,x是对象,测返回 ToPrimitive(x) === y的结果
  • 这里只提到了字符串和数字,没有布尔值。原因是布尔值会被强制类型转换为数字
var a = 42;
var b = [42];

a == b; // true

[42]首先调用ToPrimitive抽象操作,返回“42”,变成“42” == 42, 然后变成 42 == 42 ,最后两者相等

var a = 'abc';
var b = Object(a);// 和new String(a)一样

a === b; // false
a == b; // true

a == b 结果为true,因为b通过ToPrimitive进行强制类型转换(也称为“拆封”),并返回标量基本类型“abc”, 与a相等。

但有些值不这样,原因是== 算法中其他优先级更高的规则,例

var a = null;
var b = Object(a); // 和Object()一样
a == b // false

var c = undefined;
var d = Object(c); // 和Object() 一样
c == d; // false

var e = NaN;
var f = Object(e) // 和new Number(e)一样
e == f; // false

因为没有对应的封装对象,所以null和undefined不能够被封装,Object(null)和Object()均返回一个常规对象。
NaN能够被封装为数字封装对象,但NaN == NaN返回false

特殊情况

  1. 自定义返回其他数字
  2. 假值的相等比较
'0' == null    // false
'0' == undefined // false
'0' == false;  // ---true
'0' == NaN; // false
'0' == 0; // true
'0' == "";  // false

false == null    // false
false == undefined // false
false == NaN;  // false
false == 0;  // ------true
false == ''; // ---true
false == []; // ----true
false == {}; // false

0 == null    // false
0 == undefined // false
0 == NaN;  // false
0 == []; // ----true
0 == {}; // false
  • 极端例子
[] == ![]

2 == [2];
'' == [null];

0 == '\n'

// ToNumber强制类型转换为0的有 '', '\n'

安全运用隐式强制类型转换

  • 如果两边的值中有true或者false,千万不要使用==
  • 如果两边的值中有[]’'或者0,尽量不要使用==。

抽象关系比较

var a = [42];
var b = ["43"];
a > b // false

var a = ['42'];
var b = ['043'];
a > b // true

var a = [4,2];
var b = [0, 4, 3];

a > b // true

var a = {b: 42};
var a = {b: 43};
a < b; // false
// a为[object Object], b为[object Object],所以按字母顺序a<b 不成立

a < b; // false
a > b; // false
a == b; // false

a <= b; // true 意思为不大于 a< b false; <= 为翻转,就为true; 
a >= b; // true 意思为不大于
// 为避免这种情况,比较时应该为同一类型

  • 小结
[] + {};   // "[object Object]"
{} + [];   // 0

第一种:数组被强制转换类型转为’’,对象被强制转换类型转为“[object Object]”,空字符串和“[object Object]”相加为“[object Object]”
第二种 ,{}被当作独立的空代码块,不执行任何操作;代码块结尾不需要分号,所以不存在语法上的问题;最后+[],将显式强制转换为0,所以输出0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值