在Js中, 强制类型转化分为两种情况: 一种是引用类型转化基本类型, 如数组转化成数字;一种是两种不同基本类型之间的转化,如字符串转化为数字。你不能将基本类型转化成引用类型,比如,不可能把数字转化为数组。 基本类型之间的转化相对容易,引用类型转化为基本类型则要复杂的多,转化又分为两种情况,转化为字符号或转化为数值

  当引用类型转化为字符串的时候,JS会先调用引用类型的toString 方法,看它能不能返回基本类型,如果能,则使用该基本类型,如果不能,则再调用引用类型的valueOf()方法,如果valueOf方法能返回基本数据类型则使用该基本数据类型 ,如果不能,就会抛出TypeError错误。你可能还记得 字符串 "[object object]"

var arr = [5, 5];
console.log(arr + ''); // "5, 5" 调用数组的toString()方法

  当引用类型转化为数值的时候,JS则先调用引用类型的valueOf()方法,同样是看它能不能返回基本类型,如果能就用,如果不能,则继续调用toString()方法,如果toString()方法也不能返回基本类型,则抛出TypeError错误。

console.log(+ new Date());  // 时间毫米数1513860979488, 数值类型

  知道了转化规则,我们就可以利用它来转化我们自定义的对象,但有的时候,转化并没有我们上面看到的那么简单,看下面的代码

var Money = function(val, sym) {
this.currentSysmbol = sym;
this.cents = val;
}
var dollar = new Money(100, '$'); console.log(+dollar); // NaN
console.log("Total" + dollar); // '[object, object]'

  得到的结果并没有什么意义,我们来给它提供toString, valueOf()方法

Money.prototype.toString = function() {
return this.currencySymbol + (this.cents / 100).toFixed(2);
}
Money.prototype.valueOf = function() {
return this.cents
}
console.log(+dollar); // number 100
console.log("" + dollar); // string 100

  这时你会发现一个问题:  " " +dollar, 按理说,它应该调用toString 方法,返回$1.00, 但它却返回了100, 证明它这里调用的是valueOf()方法,而不是toStirng()方法,这和我们的规则出现了不一致。 但是当我们把dollar 用数组包起来的时候,它返回调用的是toString()方法

console.log("" + [dollar])  // $1.00

  这时要看一下js的标准,

  

  转化成基本类型的抽象方法ToPrimitive 接受一个必选的参数(input argument) ,就是一个引用类型object和一个可选的参数(PreferredType), 然后把引用类型转化成基本类型。如果一个引用类型能够返回不止一个基本类型时,它就可能需要PreferredType 来决定返回哪一个。这个方法是怎么把引用类型转化成基本类型的?

  

  转化成基本类型,就是标准中所说的return a default value, 需要调用引用类型内置的方法,然后给它传递可选的参数(hint PreferredType). 如果再深入挖掘标准, 你会发现所说的方法,就是toString()和valueOf(), 返回字符串或数值, 到底是返回哪种基本类型取决于传入的可选参数hint PreferredType. 如果hint参数没有传递的话,它默认返回数值number。请下面的标准

  

  这也就解释了("" + dollar)为什么没有调用我们定义的toString()方法,而是调用valueOf()方法了, 因为我们没有提供hint PreferredType参数,默认返回了数值。基本操作符并不能直接用来计算引用类型,它只能计算基本类型, 当计算引用类型的时候,它进行强制类型转化,而这种转化到底转化成哪种基本类型,是js自己做决定。那我们能不能提供一个hint Preferred 参数,把决定权拿回到我们手里。很不幸,js并不没有提供这样的机制,也就是说,我们不能提供一个hint 参数给我们自己定义的对象

  但是当我们把dollar用数组括起来,它却调用了我们自定义的toString()方法. "" + [dollar] 返回 $1.00, 这又怎么解释呢? 这涉及了Js的内置对象。

  

    对于内置对象的来说, 它必须返回一个基本类型。我们把dollar用数组包括起来,但由于涉及到加号操作,所以[dollar] 要转化成基本类型,根据规则,它调用的valueOf()方法,但是数组的valueOf方法返回数组本身,不是基本类型。所以再调用数组的toString()方法,数组的toString()方法就是数组的每一项都调用toString()方法,然后再拼接起来,形成一个大的字符串,所以这里调用的是dollar 对象的toString()方法。

  我们可以模拟一个ToPrimitive的方法 

var ToPrimitive = function(obj) {
var funct, functions, val, _i, _length; functions = ['valueOf', 'toString']; if(typeof obj === 'object') {
// js 对Date日期对象作了区别处理, 先调用toString, 再调用toValue
if (obj instanceof Date) {
functions = ['toString', "valueOf"];
}
for(_i = 0, _length=functions.length; _i < _length; _i++){
funct = functions[_i];
// valueof 或 toString 方法都是函数时才调用
if (typeof obj[funct] === 'function') {
val = obj[funct]();
if (typeof val === 'string' || typeof val === 'number' || typeof val === 'boolean') {
return val;
}
}
}
// 如果两个方法都不能转化成基本数据类型,则抛出错误
throw new Error('DefualtValue is ambuiguos')
}
return obj; // 如果传递进来的参数不是引用类型,则返回
}

  现在我们已经明白了js的类型转化,再做一个复杂的例子加深一下印象, 下面这行代码输出多少

console.log(++[[]][+[]]+[+[]])

  1, 先计算数组内的元素+[], 前面的加号肯定是要数组转化成基本类型,数组转化成基本类型,只能调用它的toString()方法,空数组转化为空字符串'', +'' 表示对空字符串转化为数字,它这里调用的是Number()函数,所为转为化0, 现在变成了

console.log(++[[]][0]+[0])

  2, 加号左边[[]][0], 表示它取的是[[]] 里面的第0个位置的元素,[[]] 表示它是一个二维数组,数组里面包括数组,所以它的第0个位置上的元素还是数组,变成了

console.log(++[]+[0])

  3 , 左边是++[], 还是对数组进行基本类型转化,上面说了 [] 转化为空字符串,++‘’ 则变成了数字1,

console.log(1+[0])

  4, 右侧还是要做类型转化, 数组[0] 调用toString,则变成了字符串‘0’

console.log(1+'0')

  5, 最终的结果就是字符串‘10’

JS 强制类型转化的更多相关文章

  1. Python03 字符串类型、强制类型转化、列表、元组、字典、集合

    1 字符串类型 在python中字符串类型用str表示,字符串的连接用 + 1.1 创建字符串对象 ·创建一个字符串对象有两种方式,一种方式是直接用字符串进行赋值,另外一种是利用str类实例化对象:具 ...

  2. c++四种强制类型转化

    c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast C++ 类型转换(C风格的强制转换): (1)将浮点型数据赋值给整型变 ...

  3. Delphi强制类型转化和类型约定

    强制类型转换时一种技术,通过它能够使编译器把一种类型的变量当做另一种类型. 由于Pascal有定义新类型的功能,因此编译器在调用一个函数时候对形参和实参类型匹配的检查是非常严格的.因此为了能够通过编译 ...

  4. C++之强制类型转化

    在C++语言中新增了四个关键字static_cast.const_cast.reinterpret_cast和dynamic_cast.这四个关键字都是用于强制类型转换的.我们逐一来介绍这四个关键字. ...

  5. Asp.net 面向接口可扩展框架之类型转化基础服务

    新框架正在逐步完善,可喜可贺的是基础服务部分初具模样了,给大家分享一下 由于基础服务涉及面太广,也没开发完,这篇只介绍其中的类型转化部分,命名为类型转化基础服务,其实就是基础服务模块的类型转化子模块 ...

  6. PHP之类型转化

    类型转化的判别 PHP在变量定义中不需要(或者不支持)明确的类型定义:变量类型是根据使用该变量的上下文所决定的, 也就是说,如果把一个string值付给变量$var,$var就成了一个string,如 ...

  7. C++四种类型转化

    2018-08-02 (星期四)C++类型转换:static_cast提供编译时期静态类型检测:    static_cast <type-id> (expression)    1)完成 ...

  8. static_cast, dynamic_cast, const_cast 三种类型转化的区别

    强制转化四种类型可能很多人都常常忽略就象我一样,但是有时还是比较有用的.不了解的建议看看,一些机制我也不是十分了解,只是将一些用法写出来让大家看看.                           ...

  9. js把其他类型转化成字符串

    js把其他类型转化成字符串 一.总结 一句话总结:类型转换中的强制类型转换分为类型转换函数和类型名强制.js后一种和其它语言不同,是类型类的构造方法.String() 二.js把其他类型转化成字符串 ...

随机推荐

  1. C# 中使用log4.net的注意事项

    新建Log4Net.config文件,内容为 <?xml version="1.0" encoding="utf-8" ?> <configu ...

  2. redis底层设计(五)——内部运作机制

    5.1 数据库 5.1.1 数据库的结构: Redis 中的每个数据库,都由一个redis.h/redisDb 结构表示: typedef struct redisDb { // 保存着数据库以整数表 ...

  3. JSOUP如何优秀的下载JPEG等二进制图像

    引言 JSOUP默认是不支持解析JPEG等二进制图像的,解决方法也很简单,只需要加上Jsoup.ignoreContentType(true)这一行代码就可以.关于这一点的原因,来看看官方API说明. ...

  4. 任务调度工具Quartz入门笔记

    一,导包 1)官网下载:http://www.quartz-scheduler.org/downloads/ 2)Maven <dependency> <groupId>org ...

  5. 《Spring Boot 入门及前后端分离项目实践》目录

    开篇词:SpringBoot入门及前后端分离项目实践导读 第02课:快速认识 Spring Boot 技术栈 第03课:开发环境搭建 第04课:快速构建 Spring Boot 应用 第05课:Spr ...

  6. Python-每日习题-0009-time

    题目:暂停一秒输出 程序分析:使用 time 模块的 sleep() 函数. import time for i in range(4): print(str(int(time.time()))[-2 ...

  7. Python学习第五篇——如何访问字典

    # the example_1 aim to tell how to use dctionary,and how to access list or dictionary infos={"f ...

  8. 网工的Linux系统学习历程

    偶遇篇作为一名通过思科CCNP认证的网络工程师,专注于网络技术.但在日常的工作中,难免不接触到服务器,对于大多数服务器来说,鉴于稳定性等因素的考虑,基本使用的都是Linux系统,包括RHEL.Cent ...

  9. Summer sell-off CodeForces - 810B (排序后贪心)

    Summer holidays! Someone is going on trips, someone is visiting grandparents, but someone is trying ...

  10. Mysql MyISAM与InnoDB 表锁行锁以及分库分表优化

    一. 两种存储引擎:MyISAM与InnoDB 区别与作用 1. count运算上的区别: 因为MyISAM缓存有表meta-data(行数等),因此在做COUNT(*)时对于一个结构很好的查询是不需 ...