Javascript知识整理——强制类型转换

值类型转换

将值从一种类型转换为另一种类型通常称为类型转换,这是显式的情况;隐式的情况称为强制类型转换

类型转换发生在静态类型语言的编译阶段,而强制类型转换则发生在动态类型语言的运行时

ToString

字符串化规则
  • null转换为"null"
  • undefined转换为"undefined"
  • true转换为"true"
  • 数字的字符串化则遵循通用规则(极大和极小数字使用指数形式)
  • 对于普通对象来说,除非自行定义,否则toString()返回内部属性[[Class]]的值,若有自己的toString()方法,则会调用该方法返回其他值
  • 对数组来说,toString经过重新定义,将所有单元字符串化后再用“,”链接起来
  • JSON.stringify()在将JSON对象序列化时也用到了ToString
    JSON字符串化与toString()的效果基本相同,只不过序列化的结果总是字符串:
     JSON.stringify(42); // "42"
     JSON.stringify("42")//""42""
     JSON.stringify(null)//"null"
     JSON.stringify(true)//"true"
    
  • 所有安全的JSON值都可以用JSON.stringify()字符串化,安全的JSON指能够呈现为有效JSON格式的值
    undefined,function,symbol和包括循环引用的对象都不符合JSON结构标准,无法处理他们
    JSON.stringify()在对象中遇到undefined,function和symbol时会自动将其忽略,在数组中则会返回null。对包含循环引用的对象执行JSON.strigify()会出错
JSON.stringify(undefined); //undefined
JSON.stringify(function(){}); //undefined
JSON.stringify(
    [1,undefined,function(){},4]
);                          //"[1,null,null,4]"
  • 如果对含有非法JSON值的对象做字符串化,或者对象中的某些值无法被序列化时,就需要定义toJSON()方法来返回一个安全的JSON值(这个值会再通过JSON.stringfy()序列化)

ToNumber

转化规则
  • true转换为1
  • false转换为0
  • undefined转换为NaN
  • null转化为0
  • 对象(包括数组)首先转换为相应的基本类型值,如果返回的是非数字的基本类型值,在根据上述规则进行强制转换为数字
    为了把值转换为相应的基本类型值,会先检查该对象是否有valueOf()方法,没有就使用toString后的返回值,如果valueOf()和toString()均不返回基本类型值,会产生TypeError错误。
var c = [4,2];
console.log(Number(c)); //undefined

var a = {
    valueOf: function () {
        return "42"
    },
    toString: function () {
        return "41"
    }

}
var b = {
    toString: function () {
        return "41"
    }
}
// console.log(Number(b)) //41
console.log(Number(a))    //42 (valueOf优先调用)

ToBoolean

假值
  • undefined
  • null
  • false
  • +0,-0和NaN
  • ""
    以上均为假值,假值列表意外的值都应该是真值(未明确定义)。
假值对象

假值对象时指在常规Javascript语法基础上自己创建了一些外来的值,强制类型转换为false。(如document.all)
而封装了假值的对象,并非假值对象,强制类型转换时仍视作一个对象来看,转为true

var a = new Boolean(false);
var b = new Number(0);
var c = new String("");
console.log(Boolean(a));    //true
console.log(Boolean(b));    //true
console.log(Boolean(c));    //true
真值

假值以外的值
表示假值的字符串强制类型转化仍视为非空字符串看待,转化为true

var a = "false"
var b = "0";
var c = "''";
var d = Boolean(a&&b&&c);
d;              //true

显式强制类型转换

显式强制类型转化是那些显而易见的类型转换

字符串和数字之间的显式转换
  • 除String()和Number()外,还有其他方法可以实现字符串和数字之间的显式转换
var a = 42;
var b = a.toString();
//toString()对a不适用,Javascript引擎自动为42创建一个封装对象,然后调用该对象的toString()方法
var c = "3.14"
var d = +c;
b;          //"42"
d;          //3.14
  • 日期显式转换为数字
    var timestamp = +new Date()
  • 暂不研究~运算符
显式解析数字字符串
  • 解析允许字符串中含有非数字字符,解析按从左到右的顺序,如果遇到非数字字符就停止,而转换不允许出现非数字字符,否则失败返回NaN
var a = "42"
var b = "42px"
Number(a);      //42
parstInt(a);    //42
Number(b);      //NaN
parseInt(b);    //42
  • 解析非字符串
    parseInt()先将参数强制类型转换为字符串再进行解析。
parseInt(1/0,19);  //18
//转换为字符串后parse("Infinity",19)
//第一个字符是“I”,以19为基数时值为18,第二个字符不是一个有效的数字字符,解析到此为止。(19为基数时,有效范围为0-9,a-i)
显示转换为布尔值
  • 显示强制类型转换为布尔值最常用的方法是!!,因为第二个!会把结果反转为原值
var a = "0";
var b = [];
var c = {};

var d = "";
var e = 0;
var f = null;
var g;

!!a;    //true
!!b;    //true
!!c;    //true

!!d;    //false
!!e;    //false
!!f;    //false
!!g;    //false

隐式强制类型转换

字符串和数字之间的隐式强制类型转换

+运算符既能用于数字加法,也能用于字符串拼接
简单来说,如果+的其中一个操作数是字符串(或者可以隐式转换为字符串)则执行字符串拼接,否则执行数字加法

var a = "42"
var b = "0";
var c = 42;
var d = 0;
a + b ; // "420"
c + d ; // 42

var e = [1,2];//首先对其调用ToPrimitive抽象操作,再调用[[DefaultValue]],以数字作为上下文
var f = [3,4];
e + f ; //"1,23,4"
布尔值到数字的隐式强制类型转换
function onlyOne(){
    var sum = 0;
    for(var i=0;i
隐式强制类型转换为布尔值
  • if(..)语句中的条件判断表达式
  • for(..;..;..)语句中的条件判断表达式
  • while(..)和do..whilee(..)循环中的条件判断表达式
  • ?:中的条件判断表达式
  • 逻辑运算符||和&&左边的操作数(作为条件判断表达式)

以上情况中,非布尔值会被隐式强制类型转化为布尔值,遵循前面介绍过得ToBoolean抽象规则

||和&&

准确来说,应该将它们称为"选择器运算符"
它们的返回值是两个操作数中的一个(且仅一个)

  • ||和&&首先会对第一个操作数执行条件判断,如果其不是布尔值,则先进行ToBoolean强制类型转换,然后再进行条件判断
  • 对||来说,如果条件判断结果为true则返回第一个操作数的值(不一定是布尔值),如果是false直接返回第二个操作数的值
  • 对&&来说,如果条件判断为true就直接返回第二个操作数的值,为false直接返回第一个操作数的值
  • 在if和for中其实会隐式将||和&&的返回结果隐式转换为布尔值从而进行条件判断
a || b
//相当于
a ? a : b

a && b 
//相当于
a ? b : a
符号的强制类型转换
  • ES6允许从符号到字符串的显示强制类型转换,然而隐式强制类型转换会产生错误
  • 符号不能够被强制类型转换为数字(不管显隐),但可以强制类型转换为布尔值

宽松相等和严格相等

正确的解释是:“==允许在相等比较上进行强制类型转换,而===不允许”

抽象相等
  • 如果两个值的类型相同的情况下
    • (1)先注意几个常规的情况:
      • NaN不等于NaN
      • +0等于-0
    • (2)两个对象指向同一个值是则视为相等,不发生强制类型转换
    • 不符合以上情况,就根据同类型直接比较是否相等
  • 如果两个值的类型不同的情况下
    • 字符串和数字之间的相等比较
      • 如果Type(x)是数字,Type(y)是字符串,返回x == ToNumber(y)的结果
      • 反之,返回ToNumber(x) == y的结果,即以数字为基准类型
    • 其他类型和布尔类型之间的相等比较
      • 如果Type(x)是布尔类型,则返回ToNumber(x) == y的结果,若类型不一致
      • 如果Type(y)是布尔值,则返回x == ToNumber(y)的结果,即也是以数字为基准类型
      • 待布尔值转换为数字后,剩下的是数字和非布尔的类型的比较了,此时要进行二次判断,即考虑数字和字符串的比较,null和undefined和情况,以及对象与非对象之间的相等比较,接下讨论这两种情况
    • null和undefined之间的比较
      • 如果x为null,y为undefined,则结果为true
      • 如果x为undefined,y为true,则结果为true
      • 即在==中null和undefined相等,除此之外其他值都不存在这种情况,即null与null和undefined相等,除此之外其他都不相等,反之undefined也一样
    • 对象和非对象之间的相等比较
      • 如果Type(x)是字符串或数字,Type(y)是对象,则返回x == ToPrimitive(y)的结果
      • 如果Type(x)是对象,Type(y)是字符串或数字,则返回ToPromitive(x) == y的结果,即先处理对象为优先,之后再根据返回的简单值进行二次判断,综合以上规则。
    • 比较少见的情况
    false == {};      //false
    "" == 0;          //true
    "" == {};         //false
    0 == {};          //false
    "" == [null];     //true
    
    • 安全运用隐式强制类型转换
      • 如果两边的值中有true或false,千万不要使用==
      • 如果两边的值中有[]、""或者0,尽量不要使用==
抽象关系比较
  • 比较双方首先调用ToPrimitive,如果结果出现非字符串,就根据ToNumber规则将双方强制类型转换为数字来进行比较
  • 如果双方都是字符串,则按字母顺序来进行比较

以上内容来自《你不知道的JS中卷》的知识整理

你可能感兴趣的:(Javascript知识整理——强制类型转换)