美文网首页
说说javascript中的类型转换

说说javascript中的类型转换

作者: 拾起落叶好过冬 | 来源:发表于2017-12-04 12:36 被阅读15次

javascript中的类型转换已经是老生常谈的问题了,是基础中的基础,也是面试当中最爱问的问题,但一不注意还是会进坑。我也是在这里花了点时间想搞清楚js中类型转换的一些原理,做些笔记,只有明白了js在类型转换中做了什么,才能看清本质。

javascript中的数据类型

javascript中的类型可分为原始数据类型(number,string,boolean,null,undefined)和对象引用类型(object,array,function),这里先不考虑ES6中的symbol类型。

下面强制转换的结果是什么?

console.log(Number({}));  //NaN
console.log(Number(['2']));  //2
console.log(Number([]));  //0
console.log(Number(true));  //1
console.log(Number(function(){return 0;}));  //NaN
console.log(String([1,2]));  //1,2
console.log(String({a:12,b:true})); //[object Object]
console.log(String(function(){return 0;}));  //function(){return 0;}

可以试着总结一下规律

  • 转数值类型

    1. 对象、函数转成NaN (Not a Number)
    2. 空数组转为0,数组里只有一个数据并且这个数据能转成数字,则转成对应的数字,其它都转成NaN
    3. true转换为1,false转换为0
  • 转字符串类型

    1. 数组的结果为把所有中括号去掉,外面加个引号(真正的原理是调用了数组的join(',')方法)
    2. 对象的结果为'[object Object]'(日期除外)
    3. 函数的结果为在函数整体外面加个引号
  • 对象转布尔值都为true

浅析转换的原理

在学习javascript中说一切都是对象,这么说是有根据的,不论是原始值类型还是引用类型,每一种都对应一个包装对象(null和undefined这两种特殊值除外)

  • number —— Number
  • string —— String
  • boolean —— Boolean
  • object —— Object
  • function —— Function
    注意右侧的包装类型首字母为大写。在定义一个类型的变量时,其实本质就是定义了某一种类型的对象,既然是对象,就可以调用对象中的方法。
    javascript的对象都有 valueOftoString 这两个方法,对象转换的本质就是内部调用这两个函数以达到转换类型的目的。

试试看valueOf和toString都输出什么

var num=12;
var str='Tom';
var bool=true;
var arr=[12,45,['red','green']];
var fn=function(){return 1};
var obj={a:12};
            
console.log(num.toString(),num.valueOf());  //12 12
console.log(str.toString(),str.valueOf());  //Tom Tom
console.log(bool.toString(),bool.valueOf());//true true
console.log(arr.toString(),arr.valueOf());  //12,45,red,green (3) [12, 45, Array(2)]
console.log(fn.toString(),fn.valueOf());    //function (){return 1} ƒ (){return 1}
console.log(obj.toString(),obj.valueOf());  //[object Object] {a: 12}

总结一下规律

  • 数字
    • valueOf 返回本身
    • toString 转成字符串
  • 字符串
    • valueOf 返回本身
    • toString 返回本身
  • 布尔值
    • valueOf 返回本身
    • toString 转成字符串
  • 数组
    • valueOf 返回本身
    • toString 转成字符串,调用join方法
  • 函数
    • valueOf 返回本身
    • toString 转成字符串,外面加引号
  • 对象
    • valueOf 返回本身
    • toString [object Object]

上面说在进行类型转换时会由javascript调用valueOf 和 toString,并不是简单的猜测,为了证实这一点,我们可以用代码检验一下。

var arr=[1,2,3];

arr.valueOf=function(){
    alert('没有骗你,真的调用了valueOf');
    return [1,2,3];
};
arr.toString=function(){
    alert('没有骗你,真的调用了toString');
    return '1,2,3';
};
console.log(Number(arr));
console.log(String(arr));

以上代码定义了一个数组类型arr,并由我们自己重写了arr上的valueOf和toString的方法,当然,这仅仅是做个小实验,把这段代码放在chrome中运行,会发现确实弹出了提示。

看来javascript在类型转换的一瞬间,确实调用了valueOf或是toString。

转换为数值类型

当一个对象最终目标是要转换为数值类型时,javascript会自动调用valueOf方法,若结果就是原始类型的值,则始用Number()转换一下,并返回结果。
可以用代码模拟实验一下:

var arr=[1];

arr.valueOf=function(){
    alert('调用了valueOf');
    return Number([1]); //返回1
};
arr.toString=function(){
    alert('调用了toString');
    return '1';
};

以上代码运行后弹出了“调用了valueOf”并返回结果1(注意,toString方法没有执行),证实了猜测。一开始总结规律时,数组里只有一个数据并且这个数据能转成数字,则转成对应的数字,上面代码只有一个元素的数组arr=[1],因此能够正确转为数值1。

如果valueOf返回的结果仍然是个对象,那怎么办呢?这时,javascript会继续调用对象上的toString方法,再看看能否转为原始值,如果确实可以,就使用Number()转换一下并返回结果。

再做个小实验:

var arr=[1];

arr.valueOf=function(){
    alert('调用了valueOf');
    return [1]; //这里返回不是原始值了,是个Array
};
arr.toString=function(){
    alert('调用了toString');
    return Number([1]); //返回1
};

console.log(Number(arr));

再次运行以上代码,会发现先调用了valueOf,由于valueOf返回的结果是个对象(Array),并不是原始值,所以javascript又调用了toString再尝试一次,toString的结果是原始值,则返回转换后的正确结果1。

这时可能有个更极端的想法,如果valueOf和toString都没有返回原始值,那该怎么办呢?那么javascript也无能为力了,只有报错,输出错误消息。

眼见为实,再试一下:

var arr=[1];

arr.valueOf=function(){
    alert('调用了valueOf');
    return [1]; //这里返回不是原始值了,是个Array
};
arr.toString=function(){
    alert('调用了toString');
    return [1]; //还是返回Array,我看你怎么办
};

console.log(Number(arr));

再次运行以上代码,可以看到在chrome的控制台输出一行红色的错误:Uncaught TypeError: Cannot convert object to primitive value
大概意思是:“我不能把对象转换为原始值”。
其实,这种情况极为少见,在这里只不过是我们自己“制造”了个错误,来验证javascript内部的转换逻辑。说到这,就把javascript内部类型转换的基本思路说通了。

转换为字符串类型

转换字符串类型和转换数值类似,区别只是先调用toString,再调用valueOf,仅此而已。

原理最后总结

对象转数值

  1. 调用对象的valueOf方法。如果返回原始类型的值,再使用Number函数,不再进行后续步骤
  2. 如果valueOf方法返回的还是对象,则调用toString方法
  3. 如果toString方法返回原始类型的值,则对该值使用Number方法,不再进行后续步骤
  4. 如果toString方法后返回的是还是对象,就报错(一般不会出现)

对象转字符串

  1. 调用对象的toString方法。如果返回原始类型的值,再使用String函数,不再进行后续步骤
  2. 如果toString方法返回的还是对象,再调用对象的valueOf方法
  3. 如果valueOf方法返回原始类型的值,则对该值使用String函数,不再进行以下步骤
  4. 如果valueOf方法返回的是还是对象,就报错(一般不会出现)

搞清楚了原理以做出笔记,和大家共同学习进步。

相关文章

  • 必考知识点-JavaScript类型转换(讲原理)

    一、类型转换先说类型 类型转换指将一种类型转换为另一种类型,那我们首先来说说JavaScript中的类型。 1.1...

  • 说说javascript中的类型转换

    javascript中的类型转换已经是老生常谈的问题了,是基础中的基础,也是面试当中最爱问的问题,但一不注意还是会...

  • JS中的类型转换

    JavaScript 中的类型转换 JavaScript 基本数据类型 JavaScript 中的一共有 8 中内...

  • 类型转换

    在JavaScript中,共有两种类型转换:隐式类型转换,显示类型转换。 “字符串”转换为“数字” 在JavaSc...

  • 前端常见面试题(十三)@郝晨光

    列举三种强制类型转换和两种隐式类型转换 JavaScript是一门弱类型语言,在JavaScript中声明变量不需...

  • JS-你不知道的类型转换用法

    JavaScript是一种弱类型语言,因此它可以将各种类型转换。常见的类型转换大家可能都已经很熟悉了,今天来说说那...

  • JavaScript中的类型转换

    ECMAScript6 中新加入了一种类型(Symbol),暂且搁置,之后再说,今天主要说一说ES5 中的几种数据...

  • 【JavaScript中的类型转换】

    字符串转换为数字的方法 字符串转换为数字的方法可以分为两种,一个是显式转换,一种是隐式转换。 显式转换是通过函数的...

  • JavaScript中==的类型转换

    写在前面 如果本文对您有所帮助,就请点个关注吧! 1. 首先,要记住null == undefined始终为tru...

  • ToBoolean 转换布尔值

    JavaScript中,抽象值操作ToBoolean用于将数据类型强制转换为布尔类型 以下数据值在强制类型转换为b...

网友评论

      本文标题:说说javascript中的类型转换

      本文链接:https://www.haomeiwen.com/subject/njytixtx.html