`
zhouyrt
  • 浏览: 1125491 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

无处不在的隐式类型转换

 
阅读更多

如果把通过函数或方法调用,明确的将某种类型转换成另一种类型称为显示转换 ,相反则称为隐式类型转换 。google和维基百科中没有找到“显示类型转换”,“隐式类型转换”的字眼。暂且这么称呼。

 

 

一、 运算中存在的隐式类型转换

 

1, “+”运算符

 

var a = 11, b = '22';
var c = a + b;

 

这里引擎将会先把a变成字符串"11"再与b进行连接,变成了"1122"。
有人会有疑问,为什么不把b变成数字22再进行算术加运算呢,这样的话c就是33了。没有为什么,当运算符“+”两边一个是数字类型,一个是字符串类型时,js引擎规定进行字符串连接运算而非算术加运算。
利用运算符“+”这个特性,可以很方便的将Number转换成String。如

 

var a = 11;
alert(typeof a); //-->number
a = a + '';
alert(typeof a); //-->string

 

2,“-”运算符

 

“-”可以是一元运算符(取负),也可以是二元(减法运算)的。如

 

var a = 11, b = '5';
var c = a - b;
alert(typeof c); //--> number

 

这里与上面的“+”相反,会把字符串b隐式的转换成数字5再进行算术减法运算。利用这个特性,可以很方便的将String转换成Number

 

var a = '11';
a = a - '';
alert(typeof a);// -->number
 

二、 语句中存在的隐式类型转换

 

1,if

 

var obj = {name:'jack'}
if(obj){
	//do more
}
 

这里会把obj隐式的转换成Boolean类型

 

2,while

 

var obj = {name:'jack'}
while(obj){
	//do more
}
 

同if

 

3,for in时的类型转换

 

定义对象字面量时发生从标识符到字符串的隐式转换。

 

var person = {'name':'jack',"age":20,school:'PKU'};
for(var a in person){
	alert(a + ": " + typeof a);
}
 

这里name,age分别加单/双引号以强调其为String类型,school没有加单/双引号。我们遍历下该对象的属性,查看其类型。发现school也被隐式的转换成了String类型。


数组的索引其实也是字符串类型。这着实令人惊叹,但事实的确如此。如

 

var ary = [1,3,5,7];
for(var a in ary){
	alert(a + ": " + typeof a);
}
 

三、 alert时存在的隐式类型转换(这是群里猪婶婶发现的)

 

String.prototype.fn = function(){return this};
var a = 'hello';
alert(typeof a.fn()); //-->object
alert(a.fn()); //-->hello

 

给String原型上添加了个fn方法,该方法返回this,我们知道this可以理解成当前类的实例对象,既然是对象那么typeof a.fn()自然返回是object了。
关键是最后的alert(a.fn()),a.fn()返回的明明是对象,但却隐式的转换成了字符串“hello”显示。

同样的情况发生在数字类型上,如

 

Number.prototype.fn = function(){return this};
var a = 10;
alert(typeof a.fn());//-->object
alert(a.fn()); //-->10

 

a.fn()返回的是对象类型,但在alert(a.fn())时会隐式的将其转换成数字。

 

 

 

 

 

分享到:
评论
7 楼 wmingjian 2011-02-06  
两个测试用例:
//-----1
var a = {
{}: 1
//IE6提示:缺少标识符、字符串或数字
//FF3提示:invalid property id
//Chrome提示:Uncaught SyntaxError: Unexpected token {
};
//-----2
var a = {
0.001: 1,
0.1e-2: 1,
.1e-2: 1
};
for(var k in a){
alert(k + "=" + typeof(k));  //0.001
}

这两个测试用例能说明一些问题,可能会招来很多人对默认类型转换的讨论。我只想说,JS对象字面量是代码文本层面的概念,JS对象的key是内部实现层面的,代码文本层面允许标识符,字符串和数字,目的是为了能够准确得知内部实现层面的字符串的值。如果语法解析中的这种转换算作类型转换,那这个属于默认类型转换。
6 楼 wmingjian 2011-02-06  
1.隐式类型转换的定义不明确,会让读者“浮想连篇”的。
2.if,for,while等语句的条件表达式,不要求是布尔表达式,只要是null,undefined,false,0,0.0,""中的任何一个,条件表达是就不成立(没有所谓的类型转换,这个就是规则)。
3.{'name':'jack',"age":20,school:'PKU'},对象定义完整的写法都应该在key上加双引号,只不过解释器做的高级一些,在“某些”条件下允许你简化之,所以也无所谓类型转换。还有标识符不是一种数据类型,JS语言中对象的key永远是字符串类型的(新的版本会不会超越这个规则不知道)。
4.很多时候很多人理解的很多的“默认类型转换”都与toString,valueOf这两个方法扯上关系。
5.C,C++等语言的强制类型转换发生在编译期,强类型语言的默认类型转换一般都是“无损”的(比如char->int,float->double),JS的类型转换只发生在运行期,因为这种弱类型语言的解析过程是不强调类型的。
5 楼 rainsilence 2010-07-28  
引用
,for in时的类型转换

定义对象字面量时发生从标识符到字符串的隐式转换。

Js代码
var person = {'name':'jack',"age":20,school:'PKU'}; 
for(var a in person){ 
    alert(a + ": " + typeof a); 


这里name,age分别加单/双引号以强调其为String类型,school没有加单/双引号。我们遍历下该对象的属性,查看其类型。发现school也被隐式的转换成了String类型。


数组的索引其实也是字符串类型。这着实令人惊叹,但事实的确如此。如

Js代码
var ary = [1,3,5,7]; 
for(var a in ary){ 
    alert(a + ": " + typeof a); 
}


javascript对象都是关联数组。关联数组的索引当然都是字符串。。。。
4 楼 rainsilence 2010-07-28  
引用
alert时存在的隐式类型转换(这是群里猪婶婶发现的)


Js代码
String.prototype.fn = function(){return this}; 
var a = 'hello'; 
alert(typeof a.fn()); //-->object 
alert(a.fn()); //-->hello 

给String原型上添加了个fn方法,该方法返回this,我们知道this可以理解成当前类的实例对象,既然是对象那么typeof a.fn()自然返回是object了。
关键是最后的alert(a.fn()),a.fn()返回的明明是对象,但却隐式的转换成了字符串“hello”显示。

同样的情况发生在数字类型上,如

Js代码
Number.prototype.fn = function(){return this}; 
var a = 10; 
alert(typeof a.fn());//-->object 
alert(a.fn()); //-->10 

a.fn()返回的是对象类型,但在alert(a.fn())时会隐式的将其转换成数字。


这里只有一部分是隐士转换
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script type="text/javascript">
	String.prototype.toString = function() {
		return 1234;
	};

	String.prototype.getName = function() {
		alert(1111);
	};
	// 用new创建
	var str = new String("test");

	// 自动创建
	var str2 = "4444";

	// 1234
	alert(str);

	// 4444
	alert(str2);

	// 1111
	str2.getName();

	// 类
	function Test() {}
	Test.prototype.toString = function() {return "test"};

	// test
	alert(new Test());
	
</script>
</head>
<body>

</body>
</html>

一般情况下,我们在打印一个对象的时候,浏览器会自动调用对象的toString方法。而不用new创建出来的。不受这个条件约束
3 楼 rainsilence 2010-07-28  
引用
1,if

Js代码
var obj = {name:'jack'} 
if(obj){ 
    //do more 


这里会把obj隐式的转换成Boolean类型


这里的转换规则比较特殊。首先判断类型,如果是布尔型,则用true/false来判断。如果是非布尔型。则按照对象来判断。如果对象==null(===null or ===undefined),则返回false,其他情况返回true

var obj = null;
if (obj) {
    alert(123);
}

2 楼 kstg750718 2010-07-28  
String.prototype.toString = function(){
	return "真的是隐式转换?";
}
String.prototype.fn = function(){return this};  
var a = 'hello';  
alert(typeof a.fn()); //-->object  
alert(a.fn());

alert(a.fn());时只是调用了String.prototype.toString而已..不是你说的什么隐式转换啦.
1 楼 蔡华江 2010-07-27  
很少用减号来转化字符串为数字,到是用加号也可以。
var a = +"2"+1;   //a=3

减号貌似有歧义,不好用!

相关推荐

    c#学习笔记.txt

    装箱是值类型到 object 类型或到该值类型所实现的任何接口类型的隐式转换。将一个值的值装箱会分配一个对象实例并将该值复制到新的对象中。关键字 object. 取消装箱是从 object 类型到值类型或从接口类型到实现该...

    LINQ 实战 1/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 3/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 4/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 2/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 7/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 11/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 5/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 6/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 8/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 10/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

    LINQ 实战 9/11

    2.2.2 使用隐式类型局部变量改进实例程序 35 2.3 对象和集合的初始化器 37 2.3.1 引入对象初始化器的动机 37 2.3.2 集合初始化器 38 2.3.3 用对象初始化器改进实例程序 39 2.4 Lambda表达式 40 2.4.1 ...

Global site tag (gtag.js) - Google Analytics