您的位置:首页 > Web前端 > JavaScript

JavaScript关键知识点汇总(1):类型系统和基本运算

2010-12-09 11:04 387 查看
1、在JavaScript中定义变量时,不需要显式的类型声明,所有的变量类型均是隐式的和可变的,其依据就是值的类型。即变量的类型是由其所存储的值的类型决定的,当值发生变化时,变量类型也相应变化。或者干脆说在JS中根本不存在“变量类型”这一概念,唯一被强调的是“值”的类型。这也暗暗契合了JS的OO实质:JavaScript不是“面向对象”的,而是“基于对象”的。面向对象的基础是类(Class),而基于对象的基础是对象(Object);Class是类型,Object是值,所以“值”才是整个JavaScript的基石。

2、JavaScript的类型系统包括两部分:

原始类型(Primitive Type);

对象类型(Object Type)。

3、JavaScript原始类型:

Number:包括定点数(整数)和浮点数(实数);

String:包括字符串和字符。JS中没有字符类型,即使是单个字符,也要属于该类型;

Boolean:值为true或false;

Undefined:相当于一个收容所,对未明确类型的变量提供一个默认的归属。值仅有一个——undefined。当访问一个不存在的变量,或变量已经声明但未赋值时,会得到特殊值undefined,JS引擎会自动为每一个已声明但未初始化的变量赋于该值。

Null:另一个特殊值null的类型。与undefined的区别是:null拥有明确的类型——空类型,表示不包含任何值,而undefined表示尚未明确类型的值。

任何不属于上述五种原始类型的值,均被认为是对象(Object)类型。

4、 在JavaScript语言中,变量就像一个不带任何标签的空瓶子,仅仅是一个容器,本身并没有任何实际意义,瓶子的性质和用途完全取决于其中所容纳的物质——变量的值,例如瓶子中装上水和装上汽油是完全不同的,装水的瓶子可以拿来喝,而装汽油的瓶子可以拿来投掷(呵呵,燃烧瓶!)。而且JavaScript绝不会因为你曾经用某一个瓶子装过水而给它贴上一个永久性标签,使这个瓶子只能用来装水。如果你愿意,完全可以再用这个瓶子装汽油。

由于瓶子都是一样的,我们如何确定自己曾经往瓶子里注入了什么物质呢?JavaScript提供了一个特殊的运算符:typeof,用来探知值的类型。对于每一种特定的数据类型,该运算符返回一个特定的字符串,可能的结果如下:

"number";

"string";

"boolean";

"undefined";

"object";

"function"。

奇怪,为什么没有"null"? 因为Null类型比较特殊,JavaScript认为它是一种Object。Object可以认为是对象的“泛型”,凡是不能归入非Object类型的,统统归入Object。那么到底是哪一种Object,可以使用另一个特殊运算符instanceof来判定。instanceof将另行介绍。

5、Number类型的特殊值:

5.1、Infinity(无穷大):

表示一个太大而不能被JavaScript所处理的值。例如:一个正数被0除的结果是Infinity。同理,一个负数被0除的结果将是-Infinity。任何将Infinity作为一个运算数的算术运算的结果都将是Infinity或-Infinity。那么两个运算数都为Infinity时会发生什么情况呢? 结果如下:

var a = Infinity + Infinity; // 结果为Infinity
var b = Infinity * Infinity; // 结果为Infinity
var c = Infinity - Infinity; // 结果为NaN
var d = Infinity / Infinity; // 结果为NaN
var e = Infinity % Infinity; // 结果为NaN


结果为什么会有区别呢?原因很简单,Infinity本来就够大了,再加或乘另一个Infinity,岂不是更大,更“Infinity”?反正已经Infinity了,不管你多大,就都是Infinity吧。而两个Infinity减、除和模运算的结果却是向小的方向发展,虽然大家都是Infinity,但是各自Infinity到什么程度,谁也不知道,偏偏这三类运算的结果还小了,总不能把明明比Infinity小很多的值还叫Infinity吧,怎么办呢?干脆再用一个特殊值NaN表示得了。(-Infinity同理)

5.2、NaN(Not a Number):

虽然从字面意思上讲NaN表示“不是一个Number类型”,但Not a Number说的不是人家自己,而是它所表示的运算结果。NaN的的确确是一个Number类型的值,typeof NaN的结果是如假包换的“number”。
当某个结果为Number类型的运算失败时,会得到值NaN。例如10*"f" 的结果显然不会是一个Number值,正如之前所描述的,这个“不是Number值”的结果用NaN表示,而NaN本身却是一个Number值。

NaN具有传染性,但凡有NaN参与的算术运算,结果只有一个——NaN,即使是Infinity也逃脱不了。

6、String类型重点汇总:

6.1、单引号('')和双引号("")都是合法字符串常量值的界定符,但是不能交叉配对。
6.2、String类型与Number类型的隐式转换:

一个String值和一个Number进行 + 运算时,会将Number值隐式转换为String值,之后执行字符串连接运算。undefined会被转换为字符串"undefined",NaN会被转换为字符串"NaN";

一个String值和一个Number进行 -、*、/、% 运算时,会将String值隐式转换为Number值,之后执行相应算术运算。如果String值中包含非法数字字符,计算结果为NaN;

利用上述特点,任何Number值与空字符串("")连接,都会得到该Number值得字符串形式;任何String值乘(*)数值1,都会得到该String值的数值形式。

6.3、String类型与Numbe类型的显式转换:

将Number型变量显式转换为String值,可以通过toString()函数实现。

String值显式转换为Number值,可以通过函数parseInt()或parseFloat()实现,代码如下:

var i1=parseInt("1234"); 		// i1=1234
var i2=parseInt("-1234.5"); 	// i2=-1234 截断小数部分
var i3=parseInt("0377"); 		// i3=255 "0377"为八进制形式字符串
var i4=parseInt("0xFF"); 		// i4=255 "0xFF"为十六进制形式字符串
var i5=parseInt("1234abcd"); 	// i5=1234 转换过程到最后一个合法数字字符
var i6=parseInt("3E2"); 		// i6=3 指数形式是非法的整数表示
var i7=parseInt("abcd1234"); 	// i7=NaN

var f1=parseFloat("1234"); 		// f1=1234
var f2=parseFloat("-1234.5"); 	// f2=-1234.5
var f3=parseFloat("0377"); 		// f3=377 浮点数不支持八进制形式
var f4=parseFloat("0xFF"); 		// f4=0 浮点数不支持十六进制形式
var f5=parseFloat("-.1234"); 	// f5=-0.1234
var f6=parseFloat("3E2"); 		// f6=300 指数形式是合法的浮点数表示</p>
var f7=parseFloat("abcd1234"); 	// f7=NaN


7、Boolean类型与逻辑运算

7.1、以Boolean为目标类型的隐式转换:如果需要,所有非Boolean类型的数据都将被隐式转换为true,但以下值除外:
0(Number类型);
NaN(Number类型);
""(String类型,空串);
null(Null类型);
undefined(Undefined类型);
基于以上原则,字符串"0","false"都将被转换为true,Infinity和-Infinity也会被转换为true。

7.2、以Boolean为目标类型的显式转换:任何非Boolean值经过两次逻辑非运算,均可将其转换为Boolean类型,例如:
var b1=!!NaN;		// b1=false;
var b2=!!"false";	// b2=true;


7.3、基于Boolean类型的隐式转换:根据不同的目标类型,Boolean值会被隐式转换为如下形式:
转换为Number:true→1;false→0;
var i1=true+1;	// i1=2
var i2=1*true;	// i2=1
var i3=false+1;	// i3=1
var i4=false*1;	// i4=0

转换为String:true→"true";false→"false";
var s1="The value is:"+true;	// s1="The value is:true"
var s2=false+"";				// s2="false"


7.4、toString()函数同样适用于Boolean变量;
而parseInt()和parseFloat()不适用于Boolean类型,parseInt(true)的结果为NaN。

7.5、双目逻辑运算符(&&和||)的运算结果:
&&和||作用于Boolean值,运算结果没什么可说的,参看真值表即可。这里要说的是使用&&或||对一个Boolean值和一个非Boolean值或两个非Boolean值进行运算的结果。虽然我们在实际编写代码过程中应尽量避免这么做,但本着探究的精神,深入了解它们的精确行为,对我们编写逻辑清晰、语义明确的代码非常必要:
7.5.1、逻辑与(&&)与逻辑或(||)的运算结果并不一定都是都是Boolean值;
7.5.2、当发生短路时,运算结果为第一个操作数的值,例如:
document.write(null&&NaN);		// 结果为第一个操作数的值 null
document.write("one"||1); 		// 结果为第一个操作数的值 "one"

7.5.3、当不发生短路,运算结果为第二个操作数的值,例如:
document.write(undefined||"one");	// 结果为第二个操作数的值 "one"
document.write(undefined||null);	// 结果为第二个操作数的值 null
document.write("one"&&NaN);			// 结果为第二个操作数的值 NaN
document.write("one"&&1);			// 结果为第二个操作数的值 1

7.5.4 以上结论依然适用于使用多个双目逻辑运算符进行混合运算的情况,例如:
document.write(null||undefined&&NaN);	// 运算结果为 undefined

分析:null作为||的第一个操作数,不发生短路,结果应为表达式undefined&&NaN的值,undefined作为&&的第一个操作数,发生短路,所以最终结果为undefined。又如:
document.write("one"&&undefined||null);	// 结果为 null

分析:"one"&&undefined的运算结果为undefined,该值作为||的第一个运算数,不发生短路,所以最终结果应为null。
再次强调:在实际编码过程中,应尽量避免直接将非Boolean值作为逻辑运算符的运算数,取而代之的应是其与相应类型特定值进行关系运算的结果或判定函数的返回值。

8、关系运算

关系运算的结果一定是Boolean值。
除了传统的六个关系运算符(==、!=、>、<、>=、<=)之外,根据自身的语言特性,JavaScript还额外提供了两个运算符:===和!==,并且对前者制定了新的运算规则。JavaScript后台具有强大的隐式类型转换机制,为语言的类型系统带来了很大的灵活性。为了全面贯彻这一思想,JavaScript的设计者将这种机制也引入到了关系运算符,尤其是==与!=之中。
8.1、==与!=的新行为特性
在进行相等(==)与不等(!=)比较之前,JavaScript引擎会首先将其转换为统一的类型,然后再比较。也就是说,这两个运算符关注的是变量的值,而不考虑其类型,即使是两个类型不同的值,只要它们具有基于同一类型的相同的值,那么这两个原始值就是相等的。
8.2、新成员:===与!==
虽然隐式类型转换为我们带来了一定的便利,但并不是所有人在任何时候都这么认为,有时候我们还是要基于特定类型进行判等的。因此JavaScript提供了严格相等(===)运算符和严格不等(!==)运算符来满足这种需求。使用这两个运算符时,值不再是唯一决定相等或不等的因素,类型成为了另一个参考。
只有当两个值相等且类型相同时,才严格相等;只要两个值不相等或类型不同,就被认为是严格不等。
8.3、==与===、!=与!==的对比
1==1	/*结果为 true*/			1===1	/*结果为true*/
1==2	/*结果为 false*/			1===2	/*结果为false*/
1=='1'	/*结果为 true*/			1==='1'	/*结果为false*/
1!=1	/*结果为 false*/			1!==1	/*结果为false*/
1!=2	/*结果为 true*/			1!==2	/*结果为true*/
1!='1'	/*结果为 false*/			1!=='1'	/*结果为true*/

8.4、特殊值
null==undefined			// 结果为true
null===undefined		// 结果为false

NaN===NaN				// 结果为false
NaN!==NaN				// 结果为true
Infinity===Infinity		// 结果为true
null===null				// 结果为true
undefined===undefined	// 结果为true

8.5、有趣的结果,也许对你有用:
0xa=='a'		// 结果为false
0xa=='0xA'		// 结果为true
37=='037'		// 结果为true
037=='37'		// 结果为false
037=='037'		// 结果为false

8.6、其它关系运算符
与==和!=一样,>、<、>=和<=在比较之前对操作数也是要进行隐式类型转换的。例如:
123>='123'	// 结果为true
0>'-1'		// 结果为true


9、Undefined类型与Null类型

9.1、当声明了一个变量但是未将其初始化时,JavaScript会自动将其初始化为默认值undefined。而null值必须由程序员通过代码赋值给变量。
9.2、typeof undefined的结果是"undefined",而typeof null的结果则是"object"。
9.3、null与undefined的类型转换:
9.3.1、隐式转换为Number:undefined→NaN,null→0。例如:
var n1=undefined*10;		// n1=NaN
var n2=null+1;				// n2=1

9.3.2、隐式转换为String:undefined→"undefined",null→"null"。例如:
var s1=""+undefined;		// s1="undefined"
var s2=""+null;				// s2="null"

9.3.3、显示转换为Boolean:undefined→false,null→false。例如:
var b1=!!undefined;		// b1=false
var b2=!!null;			// b2=false


10、假值的判定

在实际编码过程中,我们经常需要对各种类型的值进行必要的判定和探空,以规避非正常数据对程序逻辑的影响,从而增强程序代码的健壮性。虽然JavaScript为我们提供了关系运算符,但我们却不能仅仅依赖于它们。
10.1、undefined的判定
当不能确定一个变量是否存在或是否被初始化时,应进行undefined判定。尤其在您无法直接控制代码的行为(例如:当实现一个函数,但并不确定函数在被调用时是否指定了与形参数目相同的实参)时,首先判定undefined便显得尤为重要,毕竟我们谁都不希望自己代码的执行会频频被浏览器抛出的异常所打断。
对undefined的判定最好不要直接使用变量值和undefined进行相等比较,除非你不介意浏览器抛出的undefined异常。我们之所以要对变量值进行undefined判定,正是为了避免在访问该变量的值时,可能使浏览器抛出undefined异常。而事实上拿变量的值与undefined进行比较,恰恰是对变量值的访问。正确的做法是使用typeof运算符获得变量的类型字符串,然后与串"undefined"进行比较。注意typeof运算符仅仅获得变量的类型,而与变量的值无任何直接接触,所以即使变量不存在或尚未初始化,此操作也不会抛出undefined异常。
typeof variableNotDeclared === "undefined" 		// 结果为true
var variableNotIntialized;
typeof variableNotInitialized === "undefined"	// 结果为true
var nullValue=null;
typeof nullValue === "undefined"				// 结果为false

10.2、null的判定:直接与值null进行比较
var nullValue=null;
nullValue===null		// 结果为true

10.3、NaN的判定:NaN不能通过关系相等运算符(===、==)或关系不等运算符(!==、!=)来判定(参见8.4),JavaScript为此提供了一个函数,专门进行Number值得NaN判定:isNaN()
isNaN(3*"2");					// 结果为true
isNaN('1'+2);					// 结果为false
var variableNotInitialized;		//variableNotInitialized已定义但尚未初始化
isNaN(variableNotInitialized);	//结果为true
var nullValue=null
isNaN(nullValue);				// 结果为false

10.4、''(空串)的判定
var str='strDemo';
str===''
str.length===0


11、自我检测:写出以下变量或表达式的值,并说明为什么。

var a; typeof a;

var s = '1s'; s++;

!!"false"

!!undefined

typeof -Infinity

10 % "0"

undefined == null

false === ""

typeof "2E+2"

3&&2||true

(null||Infinity)&&('0'||true)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: