JavaScript教学 - 运算子(Operators) - 下
介绍JavaScript中的运算子(Operators)的用法,包含逻辑运算子(Logical Operator)、字串运算子(String Operator)和特殊运算子(Special Operator)。
6. 逻辑运算子
逻辑运算子(Logical Operator)在程式语言中一般用来做布林代数使用,进行复数的条件判断,例如:
n >= 0 && n <= 100
包含以下运算子
范例 | 说明 |
---|---|
a && b | 逻辑AND,a为true且b为true,则回传true |
a || b | 逻辑OR,a为true或b为true,则回传true |
!a | 逻辑NOT,a为false,则回传true |
然而JavaScript和其它语言在&&和||逻辑运算子的行为上有些不同之处。
6.1 逻辑AND(&&)
JavaScript中的&&回传的结果并不一定是布林值,实际上他会依据以下规则回传运算结果:
- 如果运算式转为布林值为false,则回传该数值。(例如0, null, undefined, NaN和空字串)
- 如果为true,则回传右边运算式的数值;换句话说,当全部成立时,回传最右边运算式的数值。
true && null && 100 // null true && {} && 100 // 100
而如同一般程式语言一样,如果左方的运算式结果为false时,将不会执行右边的运算式:
false && neverExec() // 右边的函式将永远不会触发
6.2 逻辑OR(||)
如同AND一样,JavaScript中的||回传结果不一定是布林值,他会依据以下规则回传运算结果:
- 如果运算式转为布林值为true,则回传该数值。
- 如果为false,则回传右边运算式的数值;如果全部为false,则回传false。
而如同一般程式语言一样,如果左方的运算式结果为true时,将不会执行右边的运算式:
true || neverExec() // 右边的函式将永远不会触发
除此之外,由于OR的特性,时常会被拿来利用作为指派预设值之用:
option = option || 'default';
7. 字串运算子
字串运算子(String Operator)使用+号作为连接字串之用,由于和算术运算子的数值相加符号一样,所以在数字和字串混合使用的时候可能需要注意,避免产生未预期的结果,可以看以下范例:
1 + '2' // 12 1 + 2 + '3' // 33 '1' + 2 + 3 // 123 '1' + (2 + 3) // 15
执行顺序为由左至右,当遇到字串之后才会变成字串连接,在变成字串之前还是会使用算术相加,可使用括号先执行算术运算后在转为字串连接。
8. 特殊运算子
JavaScript中包含一些其他的特殊运算子(Special Operator),以下逐一介绍。
8.1 条件运算子
条件运算子(Conditional Operator)是唯一的三元运算子,语法如下:
expr ? true_val : false_val
使用范例如下:
score >= 60 ? 'pass' : 'fail' n > 0 ? 100 / n : 0 a > b ? a : b
8.2 逗号运算子
逗号运算子(Comma Operator)使用逗号(,)隔开镁个运算式,并回传最右边的运算式结果,这个运算子通常用在回圈之中,同时对多个变数进行变量操作,例如:
for(var i = 0, j =0;i < 10;++i, j += 2) sum += i * j;
8.3 阵列与物件存取运算子
我们可以透过中括号([])来存取阵列的元素,而物件的成员我们可以用点(.)和中括号([])来存取,例如以下范例:
var a = [123]; a[0] // 123 var o = {n: 456}; o.n // 456 o['n'] // 456
其中物件也可以使用中括号代字串的方式存取成员,利用此特性可以透过程式的方式动态的存取不同的成员:
var o = {}; for(var i = 0;i < 5;++i) o['n' + i] = i; o // {n0: 0, n1: 1, n2: 2, n3: 3, n4: 4}
8.4 in
in运算子可以用来判断一个物件是否包含某个属性,并回传布林结果,范例如下:
var army = {black: 'color', fault: null, illegal: undefined}; console.log('black' in army); // true console.log('fault' in army); // true, 即使宣告null或undefined也是存在 console.log('illegal' in army); // true console.log('truth' in army); // false var arr = [1, 2, 'hello']; console.log(1 in arr); // true, 实际上指的是arr[1]存在 console.log('1' in arr); // true, arr['1'] console.log('hello' in arr); // false, arr['hello']不存在 console.log(3 in arr); // false, arr[3]不存在
注意以上阵列的用法,并不是以值有没有在阵列之中作为判断。
8.5 instanceof
instanceof运算子可以用来判断一个实例(instance)是否为某一种类型所建构出来,左边必须放要被判断的实例,右边必须为类别建构式,以下为一个范例:
function Animal() {} function Dog() {} Dog.prototype = new Animal(); function Cat() {} Cat.prototype = new Animal(); var dog = new Dog(); console.log(dog instanceof Animal); // true console.log(dog instanceof Dog); // true console.log(dog instanceof Cat); // false console.log(dog instanceof Object); // true console.log(Dog instanceof Animal); // false
以上范例简单的建立了一些继承关系,透过继承关系的范例可以容易理解运作的意涵。
8.6 typeof
typeof运算子可以用来取得一个物件的型别,在之前的文章JavaScript教学 - 资料型态(Data Type) - 上中已经有介绍过,不过值得注意的地方是,自定的类别物件使用typeof只会回传"object"的字串,如果要进一步判断是哪一种类别,必须使用上面的instanceof的运算子。
8.7 new
new运算子可以用来产生物件实例,比较特别的是,在JavaScript中,如果不带参数允许省略括号,一些范例如下:
var date = new Date(); var obj = new Object; var point = new Point(x, y);
8.8 delete
delete运算子可以用来移除物件的属性、阵列元素或变数,并回传是否成功的布林结果,以下两种情况的物件属性是无法删除的:
- 核心属性,例如window.document。
- var宣告的变数。
JavaScript中的delete只是将该属性或元素的参考连结移除,并不会直接将该物件作释放记忆体的动作。delete和将值设成undefined或null是不一样的意思,delete后该属性将不会存在。另外在标准中的定义,如果对象不是属性、阵列元素或变数时也是会回传true,以下为一些范例:
console.log(delete window.document); // false var a = 1; console.log(window.a); // 1 console.log(delete window.a); // false console.log(window.a); // 1 b = 2; console.log(window.b); // 2 console.log(delete window.b); // true console.log(window.b); // undefined c = 3; console.log(window.c); // 3 console.log(delete c); // true console.log(window.c); // undefined var arr = ['Test', 178]; arr[0] = undefined; console.log(0 in arr); // true console.log(delete arr[0]); // true console.log(0 in arr); // false console.log(delete nofound); // true console.log(delete "you can't delete"); // true
8.9 void
void运算子可以执行一段运算式,然后不回传结果(也就是回传undefined),实务上最常使用在超连结之中,用来执行一段JavaScript语法而避免页面跳转(一些旧的浏览器需要回传undefined才不会跳转),例如:
<a href="javascript: alert('Hello')">Click</a>
早期也用作产生undefined数值之用。
8.10 get / set
在一些程式语言中,支援使用属性的方式来处理getter / setter,而在JavaScript 1.8.5版本加入了这项实作,宣告与使用方法如下:
var user = { get Name() { return this.name || 'Anonymous'; }, set Name(value) { this.name = value.charAt(0).toUpperCase() + value.slice(1); } } console.log(user.Name); // Anonymous user.Name = 'john'; console.log(user.Name); // John
不过由于这个功能是比较新版本的浏览器才有支援,所以在普及之前可能还是避免使用。
8.11 let
JavaScript 1.7中提出了let的操作子,不过目前似乎未被大部份浏览器纳入支援,故暂时不做介绍。
8.12 yield
JavaScript 1.7中提出了yield的操作子,不过目前似乎未被大部份浏览器纳入支援,故暂时不做介绍。
延伸阅读