逻辑运算
JavaScript中支持两种逻辑运算,“逻辑或(||)”和“逻辑与(&&)”,他们的使用方法与基本的布尔运算一致:
这种运算符的特殊之处在于,他既不改变运算元的数据类型,也不强制运算结果的数据类型。除此之外,还有两条特性:
因此上例中,
x运算结果为:str;
y运算结果为:obj。
比较运算
1.等值检测
等值检测的目的是判断两个变量是否相等或相同。
相等是指运算符“==”和“!=”,相同是指运算符“===” 和"!=="。
名称 |
运算符 |
说明 |
相等 |
== |
比较两个表达式,看是否相等。 |
不等 |
!= |
比较两个表达式,看是否不相等 |
相同 |
=== |
比较两个表达式,看值是否相等并具有相同的数据类型。 |
不同 |
!== |
比较两个表达式,看是否具有不相等的值或不同的数据类型。 |
等值检测中“相等”的运算规则
类型 |
运算规则 |
两个值类型进行比较 |
转换成相同数据类型的值进行“数据等值”比较。 |
值类型与引用类型进行比较 |
将引用类型的数据转换成为与值类型数据相同的数据,再进行“数据等值”比较。 |
两个引用类型比较 |
比较引用地址。 |
等值检测中“相同”的运算规则
类型 |
运算规则 |
两个值类型进行比较 |
如果数据类型不同,则必然“不相同”;数据类型相同时,进行“数值等值”比较。 |
值类型与引用类型进行比较 |
必然“不相同”。 |
两个引用类型比较 |
比较引用地址。 |
特别举例说明引用类型的等值比较,“比较引用地址” 的实际意义是:如果不是同一个变量或其引用,则两个变量不相等,也不相同。
alert(obj1
== obj2); // 返回false
“===“和“!==”运算符的一般性用途
在JavaScript中false、‘’、0和Null、undefined是两两“相等”的:
以上的结果都是true,因此当比较的数据元中包含以上5种情况时,应使用“===”和“!==”。
PS:一个值应该与其自身“相等/相同”,但存在一个例外:一个NaN值,与自身不相等,也不相同。
2.序列比较(比较大小)
可比较序列的类型 |
序列值 |
Boolean |
0~1 |
String |
|
Number |
负无穷大~正无穷大 |
类型 |
运算规则 |
两个值类型进行比较 |
直接比较数据在序列中的大小。 |
值类型与引用类型进行比较 |
将引用类型的数据转换为与值类型数据相同的数据,再进行“序列大小”比较。 |
两个引用类型比较 |
无意义。(*注1) |
注1:其实,对引用类型进行序列检测运算仍然是等可能的,但这与valueOf()运算的效果有关。
以下是上述的例子:
// 当字符串转换为数值时得到NaN,任何数据与NaN比较都为false
void运算符
使用void的语法格式是:[void 表达式]。
其作用是使后面的表达式立即执行,但忽略返回值(返回undefined)。
以下的例子很好的诠释了这句话的含义:
利用这种特性,我们可以使<a>标签中的Href属性失去作用,就像我们常看到的那样:
这里void后的括号并不是必须的,只不过它仍然满足[void 表达式]这一语法格式,表达式等于(0)而已,千万不要当成了函数调用。
由此应该可以想到,既然这里使用到的是void 忽略返回值这一特性,那么该链接么有执行默认行为的原因并不是我们原以为的0在起作用,如下形式会得到同样的效果:
函数调用
最常用的函数调用方式:
}
foo();
// 匿名函数通过引用来调用
下面来看看几种不常见的函数调用方式:
}();//这里的括号对表示函数调用运算符 (*注)
运算符void用于使其后的函数表达式执行运算,可理解为一种强制运算,类似示例1。
上面3个例子中标(*注)的地方都是函数调用运算符,既然是函数调用的语法,那么和普通的函数调用一样,也是可以传递参数的。
void function(s)
{
alert(s);
}('test');
break的不常见用法
一般情况下,break子句作用于循环语句的内层或者switch语句中,但break子句也具有一种扩展的语法,以指示它所作用的范围。
该范围用已经声明过的标签来表示:
if (s1 == " 1 " )
}
alert(s1);
continue的不常见用法
continue后面也可以带一个标签,这时它表明从循环体内部中止,并继续到标签指示处开始执行。
运算符的二义性
一、加号“+”的二义性
加号作为运算符在JavaScript中有三种作用:
1.字符串连接符
2.表达式求和运算符
3.数字取正运算符
第3点不常用,他的意思是表示数学里的正号。
这三种情况中,1、2两点最容易出现二义性问题。因为这两种处理运算处理方式依赖与数据类型,而无法从运算符上进行判断。如:
是根本无法知道他真实的含义是在求和还是在做字符串连接。
由于这种二义性的存在会出现一些问题。浏览器中,由于DOM模型的许多值看起来是数字,但实际上确实字符串。因此试图做加法运算时,实际却变成了字符串连接。
另外,还有一条关于加号运算符的规则:如果表达式中存在字符串,则优先按字符串连接进行运算。
二、逗号“,”的二义性
先看下面几个示例,分析其表达的含义:
// 示例2
// 示例3
// 示例4
示例1中,逗号被作为连续运算符使用,连续运算符(也叫逗号表达式)的意义是返回最后一个表达式的值,所以示例1的效果是“变量a赋值为3”。
示例2整个表达式为一个逗号表达式,因此整个表达式的值为最后一个表达式的值3,而变量a被赋值为1.
示例3中的逗号有两中含义(3,4,5)中的逗号表示连续运算符,而在1,2中则表示数组声明时的语法分隔符,因此示例3为将a声明为一个[1,2,5,6]的数组。
示例4并不会像示例2一样正常执行。因为这里的逗号被解释成了语句var声明时用来分隔多个变量的语法分隔符(var a, b,c),而数字2,3为不合法的语法声明,因此会在解释期就提示出错。
三、方括号“[]”的二义性
这个奇怪的语句并没有语法错误,尽管我们几乎不能理解,但JavaScript解释器可以理解。为了弄清这个问题,必须了解方括号的作用:
1.用于声明数组直接量。
2.存取数组下标的运算符。
3.对象成员存取。
因此第一个"[1]"被理解成了一个数组的直接量,它只有一个元素。接下来,由于他是对象,所以第二个“[1]”就被理解为取下标为1的元素,很显然,这个元素还没有声明。
因此“[1][1]”的结果为undefined,而a就变成了a =[undefined],只有一个元素的数组,该元素为undefined.
下面再来看一个稍微复杂一点的例子:
['a',1,2]仍然是一个数组的直接量,但['b',3,4]怎么解释呢?
首先要了解'b',3,4被解释成为了一个逗号表达式,而他的值为4,因此[4]表示数组成员的存取,后面的过程就与上一个示例一样了。