3.3 ECMAScript一元运算符及表达式
在ECMAScript语法中,对只有一个参数(对象或值)进行操作的运算符,统称为一元运算符。一元运算符包括new、delete、void、增减量运算和一元加减法等。下面对这些一元运算符逐一进行介绍。
3.3.1 一元运算符与表达式概述
关于ECMAScript语法中定义的一元运算符的内容详见表3-3。
表3-3 ECMAScript一元运算符与表达式
3.3.2 new和delete运算符及表达式
对于new和delete运算符,相信对于学习过C语言或Java语言的读者一定不陌生。ECMAScript语法中规定new运算符用于创建新的对象,而delete运算符用于删除对已存在对象的属性或方法的引用。
提示
ECMAScript语言与C和Java语言不同,ECMAScript语法中没有“类”的概念,只有“对象”的概念。其实,ECMAScript中的对象与C和Java语言中的类这两个概念,在含义、功能和用法上基本相同。读者把ECMAScript语言中的对象当作C和Java语言中的类来理解是完全没有问题的。
下面,来看一个应用new和delete运算符的代码示例(详见源代码ch03目录中ch03-js-operator-new-delete.html文件)。
【代码3-7】
01 <script type="text/javascript"> 02 // obj test 03 console.log("delete obj :"); 04 var obj = new Object; 05 obj.userid = "king"; 06 obj.username = "Leo King"; 07 obj.gentle = "male"; 08 console.log("userid : " + obj.userid); 09 console.log("username : " + obj.username); 10 console.log("gentle : " + obj.gentle); 11 console.log(obj); 12 delete obj.gentle; 13 console.log(obj); 14 delete obj.username; 15 console.log(obj); 16 delete obj.userid; 17 console.log(obj); 18 obj = null; 19 // obj2 test 20 console.log("delete obj2 :"); 21 var obj2 = new Object; 22 obj2.userid = "king"; 23 obj2.username = "Leo King"; 24 obj2.gentle = "male"; 25 console.log(obj2); 26 delete obj2; 27 console.log(obj2); 28 obj2 = null; 29 console.log(obj2); 30 </script>
关于【代码3-7】的分析如下:
第04行代码通过new运算符创建了一个对象obj(var obj = new Object;),并在第05~07行代码中为该对象(obj)定义了三个属性,同时初始化了具体属性值;
第08~10行代码分别通过对象(obj)的三个属性输出了其属性值;
而第11行代码则是直接通过对象(obj)输出了其全部属性值;
第12行、第14行和第16行代码依次通过delete运算符删除了对象(obj)的三个属性;同时,第13行、第15行和第17行代码则分别在每次进行delete运算后,输出了对象(obj)的全部属性值;
第21~29行代码与前面的代码类似,不同之处在于第26行代码中,尝试直接通过delete运算符删除对象(obj2)。
页面效果如图3.7所示。从第13行、第15行和第17行代码输出的结果来看,每次执行delete运算后,对象(obj)的属性均被成功删除,直至最后输出了一个空的“Object”对象。而从第25行和第27行代码输出的结果来看,第26行代码中尝试通过delete运算符直接删除对象(obj2)的操作没有成功,这是为什么呢?让我们再查看关于delete运算符定义的描述:“delete运算符用于删除对已存在对象的属性或方法的引用”,这就说明delete运算符仅仅对于对象的属性或方法有效,而是无法直接删除对象本身的。
图3.7 ECMAScript一元运算符(new & delete)
那么如何删除对象呢?我们看第18行和第28行代码,通过直接为对象赋值“null”,就可以清空对象了,具体效果从第29行代码输出的结果就可以看出来。
提示
清空对象并不意味着对象就从内存中被释放了,JavaScript语言有专门的垃圾回收机制负责内存释放操作,我们会在后面的内容中详细介绍JavaScript语言的内存释放管理机制。
3.3.3 void运算符及表达式
对于void运算符,相信对于学习过C语言的读者也一定不陌生。ECMAScript语法中规定void运算符对任何值均返回(undefined)值,通常void运算符的作用是用于避免输出不应该输出的值。比如在HTML页面中的<a>标签内调用JavaScript函数时,如打算正确实现该功能,则函数一定不能返回有效值,否则浏览器页面就会被清空,仅仅会替代显示出函数的返回结果。
下面,来看一个不应用void运算符的代码示例(详见源代码ch03目录中ch03-js-operator-void.html文件)。
【代码3-8】
01 <p> 02 无void运算符测试:<br> 03 <a href="javascript:window.open('about:blank')">无void运算符</a><br> 04 </p>
关于【代码3-8】的分析如下:
这段代码的主要目的就是调用window.open()方法新打开一个空的页面。但是,因为window.open()方法会有一个返回值(即对新打开窗口的引用),所以该页面会显示该返回值。
页面初始效果如图3.8所示。点击一下页面中的超链接(“无void运算符”),页面效果如图3.9所示。window.open()方法会有一个返回值,即对新打开窗口的引用(一个window对象)。因此,原页面中的内容会被该window对象的引用值([object Window])强行替换掉。
图3.8 ECMAScript一元运算符(无void)(1)
图3.9 ECMAScript一元运算符(无void)(2)
那么如何避免该问题的出现呢?这时void运算符就可以发挥作用了。下面,我们看一个应用void运算符的代码示例(详见源代码ch03目录中ch03-js-operator-void.html文件)。
【代码3-9】
01 <p> 02 有void运算符测试:<br> 03 <a href="javascript:void(window.open('about:blank'))">有void运算符 </a><br> 04 </p>
页面初始效果如图3.10所示。点击一下页面中的超链接(“有void运算符”),页面效果如图3.11所示。虽然window.open()方法会有一个返回值,但是被void运算符强制转换为“undefined”值;而“undefined”值是无意义的,因此原页面中的内容就会保留原始的内容。
图3.10 ECMAScript一元运算符(有void)(1)
图3.11 ECMAScript一元运算符(有void)(2)
3.3.4 前增量与前减量运算符及表达式
对于前增量与前减量运算符,相信对于学习过C语言和Java语言的读者也一定很熟悉。ECMAScript语法中同样也定义了前增量与前减量这两个运算符,使用方法与C语言和Java语言是一致的。
所谓前增量运算符,就是在变量前放两个加号(++),功能是在数值上加1;同理,前减量运算符就是在变量前放两个减号(--),功能是在数值上减1。注意,两个加号(++)或两个减号(--)放在变量前与放在变量后,在功能上是有所区别的,后面我们会进行详细的介绍。
下面,来看一个应用前增量与前减量运算符的代码示例(详见源代码ch03目录中ch03-js-operator-pre-ppmm.html文件)。
【代码3-10】
01 <script type="text/javascript"> 02 var i = 1; 03 console.log("i = " + i); 04 ++i; 05 console.log("++i, i = " + i); 06 console.log("++i = " + ++i); 07 console.log("i = " + i); 08 var j = 3; 09 console.log("j = " + j); 10 --j; 11 console.log("--j, j = " + j); 12 console.log("--j = " + --j); 13 console.log("j = " + j); 14 </script>
关于【代码3-10】的分析如下:
第04行代码使用前增量运算符对变量(i)进行了操作(++i);
第06行代码再次在浏览器控制台中输出了表达式(++i)的数值,这里返回的是对变量(i)使用前增量运算符后的结果;
第10行代码使用前减量运算符对变量(j)进行了操作(--j);
第12行代码再次在浏览器控制台中输出了表达式(--j)的数值,这里是对变量(j)使用前减量运算符后的结果。
页面初始效果如图3.12所示。在第04行代码对变量(i)使用前增量运算符操作(++i)后,第05行代码输出的变量(i)的值为2,说明前增量运算符对变量(i)的操作成功了。第06行代码输出的结果为3,说明直接输出表达式(++i)的数值为3。从第07行代码输出的结果3来看,经过第06行代码中前增量运算符对变量(i)的操作后,变量(i)的数值也变为3了。
图3.12 ECMAScript一元运算符(前增量与前减量)
类似的,第10行代码对变量(j)使用前减量运算符操作(--j)后,第11行代码输出的变量(j)的值为2,说明前减量运算符对变量(j)的操作成功了。从第12行代码输出的数值结果1来看,说明直接输出表达式(--j)的数值为1。而从第13行代码输出的结果1来看,经过第12行代码中前减量运算符对变量(j)的操作后,变量(j)的数值也变为1了。
以上就是对前增量与前减量运算符的测试过程,下面我们接着介绍与这两个运算符相对应的后增量与后减量运算符。
3.3.5 后增量与后减量运算符及表达式
后增量与后减量运算符可以将其理解为是相对于前增量与前减量运算符而言的。所谓后增量运算符,就是在变量后放两个加号(++),功能也是在数值上加1;同理,后减量运算符就是在变量后放两个减号(--),功能就是在数值上减1。但如前文所述,两个加号(++)或两个减号(--)放在变量后与放在变量前,在功能上是有所区别的,下面我们就通过具体代码来进行详细的分析。
这一个应用后增量与后减量运算符的代码示例(详见源代码ch03目录中ch03-js-operator-suf-ppmm.html文件),该代码是在【代码3-10】的基础上修改而完成的。
【代码3-11】
01 <script type="text/javascript"> 02 var i = 1; 03 console.log("i = " + i); 04 i++; 05 console.log("i++, i = " + i); 06 console.log("i++ = " + i++); 07 console.log("i = " + i); 08 var j = 3; 09 console.log("j = " + j); 10 j--; 11 console.log("j--, j = " + j); 12 console.log("j-- = " + j--); 13 console.log("j = " + j); 14 </script>
关于【代码3-11】的分析如下:
第04行代码使用后增量运算符对变量(i)进行了操作(i++);
第06行代码再次在浏览器控制台中输出了表达式(i++)的数值,这里是对变量(i)使用后增量运算符后的结果;
第10行代码使用后减量运算符对变量(j)进行了操作(j--);
第12行代码再次在浏览器控制台中输出了表达式(j--)的数值,这里是对变量(j)使用后减量运算符后的结果。
页面初始效果如图3.13所示。
图3.13 ECMAScript一元运算符(后增量与后减量)
以上就是对后增量与后减量运算符的测试过程,读者可以仔细对比【代码3-10】与【代码3-11】中运算符的特点。
对于前增减量和后增减,量运算符的使用特点,希望读者能够在编写代码时多加练习,熟练掌握其使用方法,以便能够提高代码编写的效率以及提高代码的美观性。
3.3.6 一元加法与一元减法运算符及表达式
ECMAScript语法中定义的一元加法与一元减法运算符与我们在数学中学习到的定义是基本一致的,但在功能用法上又有所增强。
所谓一元加法运算符,就是在变量前放一个加号(+),其对数值基本是没有影响的(因为对数值使用一元加法运算符后,数值仍是其本身),但其可以将字符串转换为数值,还可以将十六进制数转换为十进制数。同理,一元减法运算符、就是在变量前放一个减号(-),可对数值求相反数,同时对于字符串和十六进制数也起作用。
下面,来看一个应用一元加法与一元减法运算符的代码示例(详见源代码ch03目录中ch03-js-operator-uni-pm.html文件)。
【代码3-12】
01 <script type="text/javascript"> 02 var i = 123; 03 console.log("+i = " + +i); 04 console.log("-i = " + -i); 05 var j = -123; 06 console.log("+j = " + +j); 07 console.log("-j = " + -j); 08 var str1 = "123"; 09 console.log("typeof str1 = " + typeof str1); 10 console.log("+str1 = " + +str1); 11 console.log("typeof +str1 = " + typeof +str1); 12 var str2 = "-123"; 13 console.log("-str2 = " + -str2); 14 var ix16 = 0xff; 15 console.log("+ix16 = " + +ix16); 16 console.log("+ix16 = " + -ix16); 17 </script>
关于【代码3-12】的分析如下:
第03~07行代码使用一元加法和减法运算符对变量(i)、(j)进行了操作;
第08行代码定义了变量(str1),并初始化为正数形式的字符串“123”;
第09行代码使用typeof运算符对变量(str1)进行了操作(typeof str1);
第11行代码在第10行代码的基础上,使用typeof运算符和一元加法运算符对变量(str1)进行了操作(typeof +str1);
第12行代码定义了变量(str2),并初始化为负数形式的字符串“-123”;
第13行代码使用一元减法运算符对变量(str2)进行了操作(-str2);
第14行代码定义了变量(ix16),并初始化为十六进制形式的字符串0xff;
第15行代码使用一元加法运算符对变量(ix16)进行了操作(+ix16);
第16行代码使用一元减法运算符对变量(ix16)进行了操作(-ix16)。
页面初始效果如图3.14所示。
图3.14 ECMAScript一元运算符(一元加法与一元减法)
从第03行代码输出的结果123来看,说明一元加法运算符对正数值是没有意义的;那么一元加法运算符对负数值呢?从第06行代码输出的结果-123来看,一元加法运算符对负数值同样是没有意义的,这就说明一元加法运算符对数值都是没有意义的;
从第04行代码输出的结果-123来看,说明一元减法运算符起到了求负的作用,将正数123转换为负数-123;而从第07行代码输出的结果123来看,说明一元减法运算符同样起到了求负的作用,将负数-123转换为正数123;
从第09行代码输出的结果“string”来看,第08行代码定义的变量(str1)是个字符串变量;
从第10行代码输出的结果123来看,对变量(str1)使用一元加法运算符后,将字符串类型转换成了数值类型,这从第11行代码输出的结果“number”更可以得到确认;
从第13行代码输出的结果123来看,对字符串变量(str2)使用一元减法运算符后,不但可以将字符串类型转换成了数值类型,同时还可以对数值求负;
从第15~16行代码输出的结果(255和-255)来看,一元加法运算符和一元减法运算符还可以将十六进制数转换成十进制数,同时一元减法运算符仍有求负功能。
一元加法运算符和一元减法运算符看似不太起眼,不过在实际开发中还是有很多场景必须要用到的。