Skip to content

Latest commit

 

History

History
517 lines (420 loc) · 8.25 KB

强制类型转换.md

File metadata and controls

517 lines (420 loc) · 8.25 KB

强制类型转换

// 知其然并且知其所以然 // 开发中合理运用

分类

显式强制类型转换-明显 隐式强制类型转换-某些操作的副作用

var a = 42;
var b = a + "";
var c = String(a);

ToString

null;
undefined;
true;
9999;
1.07 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000;
{a: 1}
[1, 2, 3, 4];

JSON 字符串化

JSON.stringify(42);
JSON.stringify("42");
JSON.stringify(null);
JSON.stringify(true);
JSON.stringify(undefined);
JSON.stringify(function() {});
JSON.stringify([1, undefined, function() {}, null, true]);
JSON.stringify({ a: 2, b: function() {}, c: undefined, d: null, e: true });
var o = {};
var a = {
    b: 42,
    c: o,
    d: function() {}
};
o.e = a;
JSON.stringify(a);
a.toJSON = function() {
    return { b: this.b };
};
// JSON.stringify(..)可以传递一个可选参数 replacer,可以是数组和函数
//指定对象序列化过程中哪些属性应该被处理,哪些应该被排除
var a = {
    b: 42,
    c: "42",
    d: [1, 2, 3],
    e: {
        f: 1
    }
};
JSON.stringify(a, ["b", "c"]);
JSON.stringify(a, function(k, v) {
    if (k !== "c") return v;
});
// JSON.stringify(..)还有可以传递一个可选参数 space,指定缩进格式
var a = {
    b: 42,
    c: "42",
    d: [1, 2, 3]
};
JSON.stringify(a, null, 3);
JSON.stringify(a, null, "--------");

(1)字符串、数字、布尔值和null的JSON.stringify(..)规则与Tostring基本相同 (2)如果传递给JSON.stringify(..)的对象中定义了toJSON()方法,那么该方法会在字符串化之前调用,以便将对象转换为安全的JSON值

ToNumber

true
false
undefined
null
//字符串基本遵循数字常量相关规则
//处理失败转为NaN
对象 => 基本类型 => 非数字强制转化为数字
valueOf()
toString()
var a = {
    valueOf:function(){
        return '42'
    }
}
var b ={
    toString:function(){
        return "40"
    }
}
-------
""
[]
['123']
['123','456']
[123]
[123,456]
['abc','def']
var c= [4,2]
c.toString=function(){
    return "222"
}

ToBoolean

1、可以被强制类型转换为 false 的值 2、其他(被强制类型转换为 true 的值)

//假值
undefined
null
false
+0-0  NaN
""
//假值对象
document.all
//真值
"false"
"0"
"''"
[]
{}
function(){}
...

显式强制类型转换

字符串和数字之间的显式转换
String
Number
toString  (涉及隐式转化:42 -> 封装对象 -> toString)
一元运算符+\-
var a = 42;
var b = String(a);
var c = "3.14";
var d = Number(c);
var a = 42;
var b = a.toString();
var c = "3.14";
var d = +c;
1、日期显式转换为数字
var d = new Date()
+d
// var time = new Date('2019-12-12').getTime()
// var time = Date.now()

2~运算符(字位反转)
~x 相当于 -(x+1)
只使用于32位整数
// 在-(x+1)中唯一能够得到0(或者严格说是-0)的值是-1
indexOf
var a="hello word"
if(a.indexOf('lo') >=0 ){

}
if(a.indexOf('lo') !=-1 ){

}
if(~a.indexOf('lo')){

}
3~~字位截除
显式解析数字字符串

parseInt针对的是字符串值,非字符参数首先会被强制转换为字符串(隐式)

var a="42";
var b="42px"
Number(a) //42
parseInt(a)//42
Number(b)//NaN
parseInt(b)//42
区别:

!!!坑 1、向 parseInt(...)中传递数字以及其他类型的参数,避免; 2、es5 之前,如果第一个字符是 x 或者 X=>十六进制;如果是 0 转为八进制; 3、parseInt(1/0,19)

parseInt(0.000008);
parseInt(0.0000008);
parseInt(false, 16);
parseInt(parseInt, 16);

parseInt("0x10");
parseInt("103", 2);
显式转化为布尔值

Boolean() ! !! if(!!...){...} !!.. ? .. : ..

var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;

隐式强制类型转化

字符串和数字之前

+

var a = "42";
var b = "0";
var c = 42;
var d = 0;

a + b;
c + d;

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

a + b;

简单来说:如果+的其中一个操作数是字符串,则执行字符串拼接,否则执行数字加法

a + "" 对比 String(a)

var a = {
    valueOf:function(){
        return 42
    }
    toString:function(){
        return 4
    }
}
a + ""
String(a)

- 都会被转换为数字

var a = "3.14";
var b = a - 0;
var a = [3];
var b = [1];
a - b;
布尔值到数字

+

function onlyOne() {
    var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        if (arguments[i]) {
            sum += arguments[i];
        }
    }
    return sum == 1;
}
var a = true;
var b = false;
onlyOne(b, a);
onlyOne(b, a, b, b, b);
onlyOne(b, b);
onlyOne(b, a, b, b, b, a);
隐式强制类型转换为布尔值

if(...) for(.. ; ..; ..)第二个参数 while(..) 和 do..while(..) ? : || && 左边的操作数

|| 和 &&

注意:返回值

var a = 42;
var b = "abc";
var c = null;

a || b;
a && b;
c || b;
c && b;

|| 和 && 对第一个操作数执行条件判断,如果不是布尔值,就先进行 ToBoolean 强制类型转换,再执行条件判断

对于||来说,如果条件判断结果为 true,就返回第一个操作数,如果为 false 就返回第二个操作数的值

&&则相反,如果条件判断结果为 true 就返回第二个操作数,如果为 false 就返回第一个操作数的值

const a = b || "somthing";
a && b();
符号的强制类型转换
var s1 = Symbol("cool")
String(s1)

var s2 = Symbol("not cool")
s2 + ""
转数字 ×
转布尔值 ✔️

宽松相等和严格相等

== 允许在相等比较中进行强制类型转换 === 不允许

==在比较两个相同类型的值,就仅比较它们是否相等

//特殊情况
NaN == NaN 
+ 0 == -0;

==在比较两个不同类型的值时会发生隐式强制类型转化

字符串与数字之间的相等比较
var a = 42;
var b = "42";
a === b;
a == b;

(1)如果 Type(x)是数字,Type(y)是字符串,则返回 x == ToNumber(y)的结果 (2)如果 Type(x)是字符串,Type(y)是数字,则返回 ToNumber(x) == y 的结果

数字优先

其他类型和布尔类型比较
var a = "42";
var b = true;
a == b;

var x = "42";
var y = false;
x == y;

(1)如果 Type(x)是布尔类型,则返回 ToNumber(x) == y 的结果 (2)如果 Type(y)是布尔类型,则返回 x == ToNumber(y)的结果

null 和 undefined 之间的相等比较
var a = null;
var b;
a == b;
a == null;
b == null;
a == false;//
b == false;
a == "";//
b == "";//
a == 0;//
b == 0;

(1)如果 x 为 null,y 为 undefined,则结果为 true (2)如果 x 为 undefined,y 为 null,则结果为 true 在==中 null 和 undefined 相等(它们也与其自身相等),除此之外其他值都不和它们两个相等

对象与非对象之间的相等比较
var a = 42;
var b = [42];
a == b;

(1)如果 Type(x)是字符串或者数字,Type(y)是对象,则返回 x == ToPrimitive(y)的结果; (2)如果 Type(x)是对象,Type(y)是字符串或者数字,则返回 ToPrimitive(x) == y 的结果。

var a = "abc";
var b = Object(a);
a === b;
a == b;

var a = null;
var b = Object(a);
a == b;

var c;
var d = Object(c);
c == d;

var e = NaN;
var f = Object(e);
e == f;
比较少见的情况
1  "0" == null
2  "0" == undefined
3  "0" == false
4  "0" == NaN
5  "0" == 0
6  "0" == ""

7  false == null
8  false == undefined
9  false == NaN
10 false == 0
11 false == ""
12 false == []
13 false == {}

14 "" == null
15 "" == undefined
16 "" == NaN
17 "" == 0
18 "" == []
19 "" == {}

20 0 == null
21 0 == undefined
22 0 == NaN
23 0 == []
24 0 == {}

[] == ![]
2 == [2]
"" == [null]

·如果两边的值中有 true 或者 false,千万不要使用== ·如果两边的值中有[]、""、0,尽量不要使用==

抽象关系比较

比较双方首先调用 ToPrimitive,如果结果出现非字符串,就根据 ToNumber 规则将双方强制类型转换为数字来比较

var a = [42];
var b = ["43"];
a < b;
b < a;

var a = ["42"];
var b = ["043"];
a < b;

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

var a = { b: 42 };
var a = { b: 43 };
a < b;
a == b;
a > b;
a <= b;
a >= b;

a<=b ----> !(b<a)