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<arguments.length;i++){
        if(arguments[i]){
            sum += arguments[i];
        }
    }
}
var a = true;
var b = false;
onlyOne(b,a);       //true
onlyOne(b,a,b,b);   //true
onlyOne(b,a,b,b,a)  //false
隐式强制类型转换为布尔值
  • 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中卷》的知识整理

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容