在 JavaScript 中声明变量不需指定类型,对变量赋值也没有类型检查,同时还允许隐式类型转换。 这些特征说明 JavaScript 属于弱类型的语言。

在强类型的 C++ 中,多数情况下构造函数需要声明为 explicit 来禁止隐式类型转换, 避免误用(见Item 15:资源管理类需要提供对原始资源的访问)。 弱类型的 JavaScript 中没有这一机制,比如下面的代码:

// 弹出对话框中输入1
var a = prompt('input a number'); var b = a + 1; console.log(b); // 控制台输出 11

目前 JavaScript 还无法阻止 a 被隐式转换为字符串。 本文便来总结一下 JavaScript 的类型转换行为,以及隐式类型转换的规则。

转换为字符串

转换为字符串是应用程序中的常见操作,几乎所有语言都提供了将任何类型转换为字符串的通用接口。 比如Java和C#的toString方法、C++的函数std::to_string,当然还有JavaScript的toString方法。

多数的JavaScript宿主环境(比如Node.js和Chrome)都提供了全局函数toString; 与此同时Object.prototype也定义了toString方法,使得所有对象都拥有转换为字符串的能力。

比如一个Number转换为String

var n = 1;
n.toString(); // '1'

toString接受一个参数指定进制,默认为10. 可以利用这个参数生成包括字母和数字的随机字符串:

Math.random().toString(36).substr(2);

random生成一个0到1的随机数,36进制的字符集为[0-9a-z](36个),substr用来截掉起始的"0."。 另外Object.prototype.toString可以用来检测JavaScript对象的类型:

var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math] // Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null] // 自定义类型
toString.call(new MyClass); // [object Object]

转换为数字

字符串转换为数字也是常见需求,通常用来从用户输入或文件来获得一个Number。 在C++中可以用atoicinscanf等函数,在JavaScript中可以直接用parseIntparseFloat。 例如:

var iNum1 = parseInt("12345red");	//返回 12345
var iNum1 = parseInt("0xA"); //返回 10
var iNum1 = parseInt("56.9"); //返回 56
var iNum1 = parseInt("red"); //返回 NaN
var fNum4 = parseFloat("11.22.33"); //返回 11.22

注意NaN是JavaScript中唯一一个不等于自己的值。(NaN == NaN) === false! 如果遇到非法字符,parseIntparseFloat会忽略之后的所有内容。

parseFloat只接受十进制数字的字符串,而parseInt还提供了第二个参数(可选)用来指定字符串表示数字的进制:

var iNum1 = parseInt("10", 2);	//返回 2
var iNum2 = parseInt("10", 8); //返回 8
var iNum3 = parseInt("10", 10); //返回 10

上述例子来自 w3school.com.cn: http://www.w3school.com.cn/js/pro_js_typeconversion.asp

强制类型转换

强制类型转换在C++中有两种方式:用括号将类型声明在变量之前;或者调用构造函数。 在JavaScript中没有类型关键字(只有一个var来声明变量),因而只能调用构造函数:

Boolean(0)		          // => false - 零
Boolean(new object()) // => true - 对象
Number(undefined) // => NaN
Number(null) // => 0
String(null) // => "null"

隐式类型转换

隐式类型转换是最为隐蔽的地方,不加注意的话很容易在这一点上出错,对这一点的掌握也体现了JavaScript程序员经验。 JavaScript会自动转换表达式中对象的类型以完成表达式求值。

四则运算

加法运算符+是双目运算符,只要其中一个是String类型,表达式的值就是一个String, 会隐式调用每个元的 .toString() 方法。

对于其他的四则运算,只有其中一个是Number类型,表达式的值便是一个Number

对于非法字符的情况通常会返回NaN

'1' * 'a'     // => NaN,这是因为parseInt(a)值为NaN,1 * NaN 还是 NaN

不同类型的相加的行为比较复杂,也不一致,可以参考这里: https://www.andronio.me/2017/10/22/js-operators-incensistency/

判断语句

判断语句中的判断条件需要是Boolean类型,所以条件表达式会被隐式转换为Boolean。 其转换规则同Boolean的构造函数。比如:

var obj = {};
if(obj){
while(obj);
}

toString

有些接口只支持字符串参数,会对传入值进行 toString。 比如 JavaScript 宿主环境提供的接口:

alert({a: 1});    // => [object Object]

这里传入任何对象都会被 toString 转为字符串。

.

JavaScript显式类型转换与隐式类型转换的更多相关文章

  1. 「译」JavaScript 的怪癖 1:隐式类型转换

    原文:JavaScript quirk 1: implicit conversion of values 译文:「译」JavaScript 的怪癖 1:隐式类型转换 译者:justjavac 零:提要 ...

  2. C# 数据类型转换 显式转型、隐式转型、强制转型

    C# 的类型转换有 显式转型 和 隐式转型 两种方式. 显式转型:有可能引发异常.精确度丢失及其他问题的转换方式.需要使用手段进行转换操作. 隐式转型:不会改变原有数据精确度.引发异常,不会发生任何问 ...

  3. Java基础学习-类型转换之隐式转换

    +是一个运算符,我们应该能够看懂,做数据的加法. boolean类型不能转换为其他的数据类型. 默认转换:     byte,short,char--int--float--double     by ...

  4. 转】C#接口-显式接口和隐式接口的实现

    [转]C#接口-显式接口和隐式接口的实现 C#中对于接口的实现方式有隐式接口和显式接口两种: 类和接口都能调用到,事实上这就是“隐式接口实现”. 那么“显示接口实现”是神马模样呢? interface ...

  5. C# Interface显式实现和隐式实现

    c#中对接口的实现方式有两种:隐式实现和显式实现,之前一直没仔细看过,今天查了些资料,在这里整理一下. 隐式实现的例子 interface IChinese { string Speak(); } p ...

  6. 多态设计 zen of python poem 显式而非隐式 延迟赋值

    总结 1.python支持延迟赋值,但是给调用者带来了困惑: 2.显式而非隐式,应当显式地指定要初始化的变量 class Card: def __init__(self, rank, suit): s ...

  7. selenium-webdriver中的显式等待与隐式等待

    在selenium-webdriver中等待的方式简单可以概括为三种: 1 导入time包,调用time.sleep()的方法传入时间,这种方式也叫强制等待,固定死等一个时间 2 隐式等待,直接调用i ...

  8. (java)selenium webdriver学习---三种等待时间方法:显式等待,隐式等待,强制等待

    selenium webdriver学习---三种等待时间方法:显式等待,隐式等待,强制等待 本例包括窗口最大化,刷新,切换到指定窗口,后退,前进,获取当前窗口url等操作: import java. ...

  9. Java并发之显式锁和隐式锁的区别

    Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchr ...

  10. 大数据技术之_16_Scala学习_06_面向对象编程-高级+隐式转换和隐式值

    第八章 面向对象编程-高级8.1 静态属性和静态方法8.1.1 静态属性-提出问题8.1.2 基本介绍8.1.3 伴生对象的快速入门8.1.4 伴生对象的小结8.1.5 最佳实践-使用伴生对象解决小孩 ...

随机推荐

  1. java8-04-初识函数式接口

    为什么用函数式接口                                   在函数式编程思想下,允许函数本身作为参数传入另一个函数.使用函数式接口实现"传递行为"的思想 ...

  2. MYSQL5.7的安装(yum、二进制、编译安装)

    目录 一.环境说明 二.YUM安装 1.安装MYSQL-YUM源 2.安装说明 3.安装前的准备 4.安装 5.启动 三.变更root密码 四.BINARY-INSTALL 1.基础环境准备 2.建立 ...

  3. Java程序猿怎么才能月薪过万?

    每一个略微有点长进的人,都应该把作业里的前三名作为自己斗争的政策和对手.你离成为冠军Java程序员还有多远,看完这篇你就知道了. 软件工程师的作业生涯里,知识有一个三年的半衰期.这意味着三年后,你所具 ...

  4. webpack打包优化实践

    事情缘由 近段时间在做基于scratch3.0的改造项目.基于scratch-gui改造,项目本身已经很大了,然后里面还要用到scratch-blocks,scratch-vm,scratch-ren ...

  5. 【Java】String的首尾去空和判空

    去除字符串首尾空白字符:包括\t,\r,\n及" ": //去除字符串首尾空白字符:包括\t,\r,\n及" ": System.out.println(&qu ...

  6. __module__和__class__

    目录 一.__module__ 二.__class__ # lib/aa.py class C: def __init__(self): self.name = 'SB' # index.py fro ...

  7. C#开发BIMFACE系列15 服务端API之获取模型的View token

    系列目录     [已更新最新开发文章,点击查看详细] 在<C#开发BIMFACE系列3 服务端API之获取应用访问凭证AccessToken>中详细介绍了应用程序访问API的令牌凭证.我 ...

  8. nacos 的服务注册与发现

    nacos的服务注册于发现. 这个要求服务统一注册到注册中心,然后调用的时候就不需要通过ip来调用,直接通过服务名即可. 服务提供者 pom.xml配置,需要spring-cloud-starter- ...

  9. appium 使用name 定位报错 Locator Strategy 'name' is not supported for this session【appium-desktop】

    RF中使用 name定位 报错提示: Locator Strategy 'name' is not supported for this session 解决: 1.打开本地文件 driver.js ...

  10. ElasticStack的入门学习

    Beats,Logstash负责数据收集与处理.相当于ETL(Extract Transform Load).Elasticsearch负责数据存储.查询.分析.Kibana负责数据探索与可视化分析. ...