JS 强制类型转化
在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 强制类型转化的更多相关文章
- Python03 字符串类型、强制类型转化、列表、元组、字典、集合
1 字符串类型 在python中字符串类型用str表示,字符串的连接用 + 1.1 创建字符串对象 ·创建一个字符串对象有两种方式,一种方式是直接用字符串进行赋值,另外一种是利用str类实例化对象:具 ...
- c++四种强制类型转化
c++ 数据类型转换: static_cast dynamic_cast reinterpret_cast const_cast C++ 类型转换(C风格的强制转换): (1)将浮点型数据赋值给整型变 ...
- Delphi强制类型转化和类型约定
强制类型转换时一种技术,通过它能够使编译器把一种类型的变量当做另一种类型. 由于Pascal有定义新类型的功能,因此编译器在调用一个函数时候对形参和实参类型匹配的检查是非常严格的.因此为了能够通过编译 ...
- C++之强制类型转化
在C++语言中新增了四个关键字static_cast.const_cast.reinterpret_cast和dynamic_cast.这四个关键字都是用于强制类型转换的.我们逐一来介绍这四个关键字. ...
- Asp.net 面向接口可扩展框架之类型转化基础服务
新框架正在逐步完善,可喜可贺的是基础服务部分初具模样了,给大家分享一下 由于基础服务涉及面太广,也没开发完,这篇只介绍其中的类型转化部分,命名为类型转化基础服务,其实就是基础服务模块的类型转化子模块 ...
- PHP之类型转化
类型转化的判别 PHP在变量定义中不需要(或者不支持)明确的类型定义:变量类型是根据使用该变量的上下文所决定的, 也就是说,如果把一个string值付给变量$var,$var就成了一个string,如 ...
- C++四种类型转化
2018-08-02 (星期四)C++类型转换:static_cast提供编译时期静态类型检测: static_cast <type-id> (expression) 1)完成 ...
- static_cast, dynamic_cast, const_cast 三种类型转化的区别
强制转化四种类型可能很多人都常常忽略就象我一样,但是有时还是比较有用的.不了解的建议看看,一些机制我也不是十分了解,只是将一些用法写出来让大家看看. ...
- js把其他类型转化成字符串
js把其他类型转化成字符串 一.总结 一句话总结:类型转换中的强制类型转换分为类型转换函数和类型名强制.js后一种和其它语言不同,是类型类的构造方法.String() 二.js把其他类型转化成字符串 ...
随机推荐
- mongo索引命令
http://blog.csdn.net/salmonellavaccine/article/details/53907535 1. 创建/重建索引 MongoDB全新创建索引使用ensureInde ...
- Asp.net MVC 利用(aspose+pdfobject.js) 实现在线预览word、excel、ppt、pdf文件
在线预览word.excel.ppt利用aspose动态生成html 主要代码 private bool OfficeDocumentToHtml(string sourceDoc, string s ...
- SQL开窗函数
[SQL]四种排序开窗函数 一 .简单了解什么是开窗函数 什么是开窗函数,开窗函数有什么作用,特征是什么? 所谓开窗函数就是定义一个行为列,简单讲,就是在你查询的结果上,直接多出一列值(可以是聚合 ...
- java 基础04 重写
- Go+Python双剑合璧
目的 Python调用Go的方法,Python有很多功能强悍又使用简洁的库.而新生军Go的多核心利用率也是非常强悍的.当然这是明面上的优点.反正你有很多理由想要让Python能够调用Go的方法. 实验 ...
- 使用 OpenSSL 创建私有 CA:3 用户证书
OpenSSL 创建私有 CA 三部曲:使用 OpenSSL 创建私有 CA:1 根证书使用 OpenSSL 创建私有 CA:2 中间证书使用 OpenSSL 创建私有 CA:3 用户证书 在前文&l ...
- .net Core 调用微信Jsapi接口,H5解析二维码
项目里需要用到扫描二维码,自己实现,不会. 找到了两种解决方案: 通过reqrcode.js,这是一个前端解析二维码内容的js库.如果二维码比较清晰,用这种效果也不错 调用微信扫一扫功能,这种效果很好 ...
- Innodb日志与事务
1.Innodb日志: 错误日志:记录出错信息,也记录一些警告信息或者正确的信息. 查询日志:记录所有对数据库请求的信息,不论这些请求是否得到了正确的执行. 慢查询日志:设置一个阈值,将运行时间超过该 ...
- ElasticSearch聚合
前言 说完了ES的索引与检索,接着再介绍一个ES高级功能API – 聚合(Aggregations),聚合功能为ES注入了统计分析的血统,使用户在面对大数据提取统计指标时变得游刃有余.同样的工作,你在 ...
- flex实现三栏等分布局
前言 在实际开发中,我们经常会想要实现的一种布局方式就是三栏等分布局,那么我们如何来解决这个问题呢? 解决 方法一:flex 外层容器也就是ul设置display:flex,对项目也就是li设置fle ...