挑战TJS Section1.9:条件分支常用操作符

正篇

Yuu:这次我们会介绍一些常用于条件分支中的操作符。

Yuni:上次我们用的是==操作符呢。

Yuu:当左右两边的值相等时,==的比较结果是真,否则为假。译者注:请回忆,操作符左边的值称为左值,右边的值称为右值。这一点与前面讲到的加减乘除是一样的。

Yuni:这就意味着。。。如果左值和右值相等,那么紧跟在if后面的语句将会被执行。如果两者不相等,那么else后面的语句将会被执行。

Yuu:没错,就是这么个事儿。下面的操作符称为相等比较符(原文:同定演算子),一共有4种。

相等比较符

==当左值和右值相等时,为真;否则为假。如果左值和右值的类型不同,它们会被自动转换再比较。
!=当左值和右值不等时,为真;否则为假。如果左值和右值的类型不同,它们会被自动转换再比较。
===当左值和右值类型相同且相等时,为真;否则为假。
!==当左值和右值类型相同且不等时,为真;否则为假。

Yuni:==!=的结果是相反的!

Yuu:没错,而且===!==的结果也是相反的。

Yuni:那=====的区别是什么呢?

Yuu:对于==,如果左值和右值的类型不相同,它们会被转换成相同的类型再进行比较。因此,即使左值和右值的类型不同,如果“内容”相同,==比较的结果依然是真。而只要类型不同,===的值一定是假。举个栗子:

// 使用 == 和 === 操作符的不同

var  a = 1;     // a 是整数 1
var  b =  "1" ;   // b 是字符串 "1"

if (a == b)
    System.inform( "比较条件为真." );
else
    System.inform( "比较条件为假." );

if (a === b)
    System.inform( "比较条件为真." ) );
else
    System.inform( "比较条件为假." );

Yuu:试试这个。

Yuni:emmm。。。一开始“比较条件为真.”输出了,然后“比较条件为假.”输出了。

Yuu:变量b是字符串类型,但是通过1.6节讲到的单目操作符+就可以转换成数值类型了。它也就和变量a的值相同,都是1了。

Yuni:嗯对。

Yuu:如果左值和右值类型不同,==操作符会将类型转化为相同的再进行比较。因此在上面的例子中,二者相同。类型不同的时候,===操作符就是假,而不会关注内容是否相同。

Yuni:所以第一次是true而第二次是false。

Yuu:没错。下面来看比较操作符(原文:比較演算子),同样也有4个。

比较操作符

<如果左值小于右值,为真;否则为假。
>如果左值大于右值,为真;否则为假。
<=如果左值小于等于右值,为真;否则为假。
>=如果左值大于等于右值,为真;否则为假。

Yuni:这很容易理解嘛。

Yuu:是呀。多说一句,如果比较数值和字符串,字符串总会被转换成数值再进行比较。

Yuni:嗯好。

Yuu:另外,如果比较的左值和右值都是字符串,它们会按照字符编码的顺序进行比较。不过这有点复杂,这次我会先跳过比较的细节。

Yuni:嗯。。。

Yuu:下面是||&&运算符。它们分别被称为逻辑或运算符(原文:論理 OR 演算子)和逻辑与运算符(原文:論理 AND 演算子)。

逻辑或运算符和逻辑与运算符

||当左值或者右值一者为真或者二者都为真时为真,否则为假;译者注:一真即真
&&当左值和右值全部为真时为真,否则为假;译者注:都真才真

Yuu:它们通常用于同时连接两个或更多的条件,像这样。

//使用逻辑或和逻辑与操作符的例子

var  a = 1;
var  b = 2;

if (a >1 || b> 1)
    System.inform( "a和b至少一个比1大." );
else
    System.inform( "a和b都没有1大." );

if (a >1 && b >1)
    System.inform( "a和b都比1大." );
else
    System.inform( "a和b至少一个没有1大." );

Yuni:嗯。。变量a是1,变量b是2,因此a>1是假而b>1是真。

Yuu:对。

Yuni:那么” a> 1 || b> 1 ” 就是 “真 || 假“,也就是真。” a> 1 && b> 1 ” 就是 “真 && 假“, 也就是假。

Yuu:嗯,就是这样。最后是!操作符。这是逻辑非操作符(原文:論理否定演算子),用来对右值颠倒真假。

逻辑非操作符

!对右值的逻辑值取反

Yuni:所以!是个单目运算符?

Yuu:没错,用法是像这样子。

//逻辑非操作符的例子

var  a = 1;

if (!(a == 1))
    System.inform( "a不是1." );
else
    System.inform( "a是1." );

Yuni:emmm。。。 a == 1 是真,前面有一个!,所以说它应该是假,也就是显示“a是1”?

Yuu:嗯是的。

Yuni:我可以问个问题吗?

Yuu:什么问题?

Yuni:为什么条件表达式有括号?写作!a == b 不可以吗?

Yuu:哦,这是因为!运算符比==运算符具有更高的优先级。

Yuni:优先级?

Yuu:1+2×3是多少 ?

Yuni:额,先做乘法变成1+6,所以是7.

Yuu:优先级就是“乘法比加法先计算”。

Yuni:哦,我明白是怎么回事儿了。

Yuu:就是这样。由于!运算符比==运算符具有更高的优先级,因此!a==b的含义是(!a)==b,也就是将(!a)b进行相等比较。

Yuni:明白了。所以要加上括号,让a和b先进行比较。但是你如何知道运算符的优先级呢?

Yuu:像加号减号这种和算术运算具有相同优先级的运算符是比较容易理解的。除此之外,TJS2参考手册的“表达式与运算符”一节从低到高列出了运算符的优先级,可供参考。

Yuni:因为有太多运算符了我也搞不清楚了。。。

Yuu:哈哈,你需要记住常用操作符的优先级,其他的可以在需要的时候查阅文档或者使用括号指明优先顺序。

Yuni:加括号怎么讲呢

Yuu:举个栗子,我们通常会写" a = 1 + 2 * 3 ",不过呢,写作" a = 1 + (2 * 3) "也可以得到同样的结果。如果你把需要先计算的部分用括号括起来,那一定不会错。

Yuni:嗯,没问题。

Yuu:对于很长的表达式,加上括号会更加易读。例如,表达式" (a == b) && (c >= d-2) && (e <f) " 就比" a == b && c >= d-2 && e <f " 要容易阅读对吧?

Yuni:嗯,有括号的的确更容易看懂。

Yuu:当然了,如果你用了太多的括号,表达式一样难以看懂。因此要在适当的位置使用,像为了保证优先级而使用就是不可避免的。而非必需场景下,添加括号主要是为了易于阅读。

Yuni:OK我明白了

Yuu:到此为止我们已经介绍了所有在条件分支表达式中常用的运算符。下边我们要来完成点击OK和取消有不同动作的程序脚本了。

Yuni:好。

// 点击OK和Cancel执行不同操作的脚本

var  value = System.inputString( "几分钟?" ,  "请输入数字" ,  "" );

if (value == void)
{
    // value是void意味着按下了取消键
    System.inform( "Cancel." );
}
else
{
    // value不是void意味着按下了OK键
    value = +value;
    var  d =  new  Date( );
    var  hour = d.getHours();
    var  minute = d.getMinutes() + value;
    hour += minute \ 60;
    minute %= 60;  
    hour %= 24;  
    System.inform( "从现在开始+ value +  "几分钟后是" + hour + " 点 " + minute + " 分。");
}

Yuni:这样就可以吗?

Yuu:嗯,让我们来试一试。

Yuni:这次点击“取消”按钮。

Yuu:嗯。

Yuni:啊这次“取消”的消息显示出来了。

Yuu:虽然在这个例子没有问题,不过有一处可以调整的。

Yuni:额,是哪里?

Yuu:在if的比较表达式中,我们使用了“==”

Yuni:嗯,所以呢。。。

Yuu:使用“===”运算符判断是否与void相等。

Yuni:“===”运算符会检查类型是否相同对吧。为什么这里要用它呢?

Yuu:来试一下下面的脚本。

Yuni:好。

// 与void的比较

var  a = 0;     // a is an integer 0 and is not void
var  b =  "" ;    // b is an empty string and not void

if (a == void)
    System.inform( "a is void. " );
else
    System.inform( "a is not void." );

if (b == void)
    System.inform( "b is void." ) );
else
    System.inform( "b is not void. " );

Yuni:诶,这两个都输出和void相等。这是为什么?

Yuu:因为如果比较的双方类型不同时,“==”运算符在比较前会将比较的两者转换为相同的类型。

Yuni:嗯。

Yuu:因此呢,void转换成数值就是0;而转换成字符串也就是空字符串了。因此使用“==”比较,得到的结果就是相等。

Yuni:原来如此。

Yuu:因此当判断是否是void时,我们要考察是否需要比较类型。如果我们使用“a === void”的方式比较,除了a的确是void,否则都不会是真。

Yuni:嗯好,那这样呢?

// 点击OK和Cancel执行不同操作的脚本-2

var  value = System.inputString( "几分钟?" ,  "请输入数字" ,  "" );

if (value === void)
{
    // value是void意味着按下了取消键
    System.inform( "Cancel." );
}
else
{
    // value不是void意味着按下了OK键
    value = +value;
    var  d =  new  Date( );
    var  hour = d.getHours();
    var  minute = d.getMinutes() + value;
    hour += minute \ 60;
    minute %= 60;  
    hour %= 24;  
    System.inform( "从现在开始+ value +  "几分钟后是" + hour + " 点 " + minute + " 分。");
}

Yuu:没有问题了。记得在判断void的时候最好用“===”

Yuni:了解。

Yuu:好啦,这次的目标达成,下回见!

要点

  1. 三等号和三不等号的含义与其他语言的等号不等号是相同的用法。双等号和双不等号遇到类型不同的比较值会尝试转换为相同类型再比较。因此,2=="2"2!=="2"都是成立的。JavaScript的等号和不等号也是这样使用的。
  2. 大于、小于、大于等于、小于等于的用法和其他语言是相同的。如果比较值的类型不同也会尝试转换成相同类型。
  3. 逻辑与的口诀是“全真才真”;逻辑或的口诀是“一真即真”;逻辑非的口诀是“非假即真”
  4. 逻辑与和逻辑或具有“短路效应”。当表达式从左向右依次计算时,如果已经能确定真假值,后面的表达式将不会再进行计算。举例:假设a=1,(a > 0) || (a % 2 == 0) 表达式在计算了a > 0之后是真,逻辑或的口诀是一真即真,所以a % 2 == 0就不会被计算了。这个特性在很多判断中可以作为保险判断。
  5. System.inputString()方法如果点击了Cancel按钮将会得到一个void的返回值,可以用于判断输入是否被打断。

发表评论