介绍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中的&&回传的结果并不一定是布林值,实际上他会依据以下规则回传运算结果:

  1. 如果运算式转为布林值为false,则回传该数值。(例如0, null, undefined, NaN和空字串)
  2. 如果为true,则回传右边运算式的数值;换句话说,当全部成立时,回传最右边运算式的数值。
true && null && 100 // null
true && {} && 100 // 100

而如同一般程式语言一样,如果左方的运算式结果为false时,将不会执行右边的运算式:

false && neverExec() // 右边的函式将永远不会触发

6.2 逻辑OR(||)

如同AND一样,JavaScript中的||回传结果不一定是布林值,他会依据以下规则回传运算结果:

  1. 如果运算式转为布林值为true,则回传该数值。
  2. 如果为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运算子可以用来移除物件的属性、阵列元素或变数,并回传是否成功的布林结果,以下两种情况的物件属性是无法删除的:

  1. 核心属性,例如window.document。
  2. 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的操作子,不过目前似乎未被大部份浏览器纳入支援,故暂时不做介绍。

延伸阅读

上一篇 JavaScript教学 - 运算子(Operators) - 上

相关文章