学习JavaScript之——第4章 表达式和运算符(下)

学习JavaScript之——第4章 表达式和运算符(下)

学习内容:

4.8算术表达式
4.9关系表达式
4.10 逻辑表达式
4.11 赋值表达式
4.12 表达式计算
4.13 其他运算符


4.8算术表达式
  • 所有无法转换为数字的操作数都转换为NaN值,算数运算的结果也是NaN。
  • 运算符"/"用第二个操作数来除第一个操作数,区分整型和浮点型数字的编程语言,当一个整数除以另一个整数时得到的结果是整型。但是在JavaScript中所有的数字都是浮点型的,除法运算的结果也是浮点型。
  • 除数为0的运算结果为正无穷大或负无穷大,而0/0的结果是NaN,所有这些运算均不会报错。
  • 运算数"%“计算的是第一个操作数对第二个操作数的模。换句话说,就是第一个操作数除以第二个操作数的余数。结果的符号和第一个操作数(被除数)的符号一致。
    4.8.1 "+"运算符
    二元加法运算符”+"可以对两个数字做加法,也可以做字符串的连接操作。
1+2;//3
"hello" + " " + "there";//"hello there"
"1" + "2";//"12"
  • 加号的转换规则优先考虑字符串连接,如果其中一个操作数是字符串或者转换为字符串的对象,另一个操作数将会转换为字符串,加法将进行字符串的连接操作。如果两个操作数都不是类字符串的,那么将进行算数加法运算。
  • 从技术上讲,加法操作符的行为表现为:
    如果其中一个操作数是对象,则对象会遵循对象到原始值的转换规则转换为原始类值:日期对象通过toString()方法执行转换,其它对象则通过valueOf()方法执行转换(如果valueOf()方法返回一个原始值的话)。由于多数对象都不具备可用的valueOf()方法,因此它们会通过toString()方法进行转换。
    在进行了对象到原始值的转换后,如果其中一个操作数是字符串的话,另一个操作数也会转换为字符串,然后进行字符串连接。
    否则,两个操作数都将转换为数字(或者NaN),然后进行加法操作。
1 + 2;//3
"1" + "2";//"12"
"1" + 2;//"12":数字转换为字符串后进行字符串的连接
1 + {};//"1[object Object]":对象转换为字符串后进行字符串连接
true + true;//2:布尔值转换为数字后做加法
2 + null;//2:null转换为0后做加法
2 + undefined;//NaN:undefined转换为NaN后做加法

最后,需要特别注意的是,当加号运算符与字符串和数字一起使用时,需要考虑加法的结合对运算顺序的影响。运算结果是依赖于运算符的运算顺序的。

1 + 2 + " blind mice";//"3 blind mice"
1 + (2 + " blind mice");//"12 blind mice"

4.8.2 一元算术运算符
一元算术运算符作用于一个单独的操作数,并产生一个新值。在JavaScript中,一元运算符具有很高的优先级,而且都是右结合,必要时,它们会将操作数转换为数字。需要注意的是,"+“和”-"是一元运算符也是二元运算符。

  • 一元加法(+)
    一元加法运算符把操作数转换为数字(或者NaN),并返回这个转换后的数字,如果它本身就是数字,则直接返回数字。
  • 一元减法(-)
    当"-"用作一元运算符时,它会根据需要把操作数转换为数字,然后改变运算结果的符号。
  • 递增(++)
    递增"++“运算符对其操作数进行增量(加一)操作,操作数是一个左值。运算符将操作数转换为数字,然后给数字加1,并将加1后的数值重新赋值给变量、数组元素或者对象属性。
    递增”++"运算符的返回值依赖于它相对于操作数的位置。当递增运算符在操作数之前,称为“前增量”运算符,它对操作数进行增量计算,并返回计算后的值。当运算符在操作数之后,称为"后增量"运算符,它对操作数进行增量计算,但返回未做增量计算的值。
var i = 1 , j = ++ i;
i;//2
j;//2
var i = 1 , j = i++;
i;//1
j;//1

需要注意的是,表达式++x并不总和 x = x + 1 完全一样,"++“运算符从不进行字符串连接操作,它总是会将操作数转换为数字并增1。如果x是字符串"1”,++x的结果就是2,而x+1的结果是字符串"11"。

  • 递减(–)
    递减"–“运算符的操作数也是一个左值。它把操作数转换为数字,然后减1,并将计算后的值重新赋值给操作数。
    和”++“运算符一样,递减”–"运算符的返回值依赖于它相对于操作数的位置。当递减运算符在操作数之前,操作数减一并返回减一之后的值;当递减运算符在操作数之后,操作数减一并返回减一之前的值。
    4.8.3 位运算符
位运算符卡哇伊对由数字表示的二进制数据进行更底层的按位运算。
这里将操作数的每个位当作布尔值(1=true , 0=false),其他三个位运算符用来进行左移位和右移位。
位运算符要求它的操作数是整数,这些整数表示32位整型而不是64位浮点型。移位运算符要求右操作数在0——31之间。在将其操作数转换为无符号的32位整数后,它们将舍弃第5位之后的二进制位,以便生成一个位数正确的数字。
需要注意的是,位运算符会将NaN、Infinity、-Infinity都转换为0。
  • 按位与(&)
    位运算符"&"对它的整型操作数逐位执行布尔与(AND)操作。只有两个操作数中相对应的位都是1,结果中的这一位才是1。
0x1234 & 0x00FF;// = 0x0034 :52
  • 按位或(|)
    位运算符"|"对它的整型操作数逐位执行布尔或(OR)操作。如果其中一个操作数相应的位为1,或者两个操作数相应的位都是1,结果中的这一位就是1。
0x1234 | 0x00FF;// = 0x12FF : 4863
  • 按位异或(^)
    位运算符"^"对它的整型操作数执行布尔异或(XOR)操作。异或是指第一个操作数为true或第二个操作数为true,但两个不能同时为true。如果两个操作数中只有一个相应位为1(不能同时为1),那么结果中的这一位就是1。
0xFF00 ^ 0xF0F0;// = 0x0FF0 :4080
  • 按位非(~)
    位运算符"~ “是一元运算符,位于一个整型参数之前,它将操作数的所有位取反。根据JavaScript中带符号的整数的表示方法,对一个值使用”~"运算符相当于改变它的符号并减1。
~0x0F;// = 0xFFFFFFF0 : -16
  • 左移(<<)
    将第一个操作数的所有二进制位进行左移操作,移动的位数由第二个操作数指定,移动的位数是0——31之间的一个整数。例如:在表达式a<<1中,a的第一位变成了第二位,a的第二位变成了它的第三位,以此类推,新的一位用0来补充,舍弃第32位。将一个值左移一位相当于它乘2,左移两位相当于乘4,以此类推。
7 << 2;//28
  • 带符号右移(>>)
    运算符">>"将第一个操作数的所有位进行右移操作,移动的位数由第二个操作数指定,移动的位数是0——31之间的一个整数。右边溢出的位数将忽略。填补在左边的位由操作数的符号决定,以便保持结果的符号与原操作数一致。如果第一个操作数是正数,移位后用0填补最高位;如果第一个操作数是负数,移位后就用1填补高位。将一个值右移一位,相当于它除以2(忽略余数),右移两位,相当于它除以4,以此类推。
7 >> 1;//3 
-7 >> 1;//-4
  • 无符号右移(>>>)
    运算符">>“和运算符”>>>"一样,只是左边的高位总是填补0,与原来的操作数符号无关。
-1 >> 4;//-1
-1 >>> 4;//0x0FFFFFFF :268435455
4.9关系表达式

关系运算符用于测试两个表达式之间的关系,根据关系是否存在而返回true或false。
4.9.1 相等和不相等运算符

  • " == “和” === "运算符用于比较两个值是否相等,允许任意类型的操作数,操作数相等返回true,否则返回false。
  • " === "称为严格相等运算符(有时也称为恒等运算符)
  • " != "和 " !== “的运算符检测规则是” == “和” === "的求反。
  • === 和 !== 只有在相同类型下,才会比较其值。(值和类型都相同的情况下比较)
  • ===,不做类型转换,类型不同的一定不等。
  • JavaScript对象的比较是引用的比较,而不是值的比较。对象和其本身是相等的,但和其它任何对象都不相等。如果两个不同的对象具有相同数量的属性,相同的属性名和值,它们依然是不相等的。相应位置的数组元素的相等的两个数组也是不相等的。
  • 严格相等运算符" === "首先计算其操作数的值,然后比较这两个值,比较过程没有任何类型转换:
    如果两个值类型不同,则不相等。
    如果两个值都是null或undefined,则相等。
    如果两个值都是布尔值true或布尔值false,则相等。
    如果其中一个值是NaN,或两个都是NaN,则不相等。NaN和其它任何值都是不相等的,包括它本身!通过x!==x来判断x是否为NaN,只有在x为NaN的时候,这个表达式才为true。
    如果两个值为数字且数值相等,则相等。0 === -0
    如果两个值为字符串且所含的对应位上16位数完全相等,则相等。两个字符串可能含义完全一样且显示出的字符也一样,但具有不同编码的16位值。
    如果两个引用值指向同一个对象、数组、函数,则它们是相等的;指向不同的对象,则它们是不同的。
  • 相等运算符" == “和恒等运算符类似,但相等比较并不严格。如果两个操作数不是同一类型,那么相等运算符会尝试进行一些类型转换,然后进行比较:
    如果两个操作数类型相同,则和” === “的比较规则一样
    如果两个操作数类型不同,” == "相等操作符也可能会认为它们相等。
    如果一个值是null,另一个是undefined,则相等。
    如果一个值是数字,另一个是字符串,先将字符串转换为数字,然后使用转换后的值进行比较。
    如果一个值是true,先将其转换为1再进行比较。如果一个值是false,则将其转换为0再进行比较。
    如果一个值是对象,另一个值是数字或字符串,则使用3
    其它不同类型之间的比较均不相等。
"1" == true;//true

4.9.2 比较运算符

  • 比较运算符用来检测两个操作数的大小关系(数值大小或字母表的顺序)
  • 小于(<)、大于(>)、小于等于(<=)、大于等于(>=),比较结果为true或false
  • 比较操作数可能是任意类型,只有数字和字符串才能真正执行比较操作,其它类型都将进行类型转换。
  • 转换规则:
    • 如果操作数为对象,那么这个对象将转换为原始值:如果valueOf()返回一个原始值,那么直接使用这个原始值。否则使用toString()的转换结果进行比较操作。
    • 对象转换为原始值之后,如果两个操作数都是字符串,将依照字母表的顺序对两个字符串进行比较,“字母表顺序”是指组成这个字符串的16位Unicode字符的索引顺序。
    • 在对象转换为原始值之后,如果至少有一个操作数不是字符串,那么两个操作数都将转换为数字进行数值比较。
    • 如果其中一个操作数是(或转换后是)NaN,那么比较操作符总是返回false。
    • 字符串比较是区分大小写的,所有大写的ASCII字母都"小于"小写字母的ASCII,对于不区分大小写的字母比较来说,需要首先将字符串全部转换为小写字母或大写字母,通过String.toLowerCase()和String.toUpperCase()做大小写转换。
    • 加号运算符:如果其中一个操作数是字符串的话,则进行字符串的连接操作。
    • 比较运算符:只有在两个操作数都是字符串的时候才会进行字符串的比较
1 + 2;//3:加法
"1" + "2";//"12":字符串的连接
"1" + 2;//"12" : 2转换为"2"
11 < 3;//false : 数字的比较
"11" < "3";//true : 字符串的比较
"11" < 3;//false : "11"转换为11
"one" < 3;//false : 数字的比较,"one"转换为NaN

4.9.3 in运算符
in运算符希望它的左操作数是一个字符串或可以转换为字符串,希望它的右操作数是一个对象。如果右侧的对象拥有一个名为左侧操作数值的属性名,那么表达式返回true。

var point = {x:1 , y:1};
"x" in point;//true:对象有一个名为"x"的属性
"z" in point;//false :对象不存在名为"z"的属性
"toString" in point;//true : 对象继承了toString()方法

var data = [7,8,9];
"0" in data;//true:包含数组元素"0"
1 in data;//true:数字转换为字符串,当它是数字的时候,这个数字表示索引(数组的下标),有索引为1的元素
3 in data;//false:没有索引为3的元素
'unshift' in [];//true

4.9.4 instanceof 运算符
instanceof运算符希望左操作数是一个对象,右操作数标识对象的类。如果左侧的对象是右侧类的实例,表达式返回true;否则返回false。JavaScript中对象的类是通过初始化它们的构造函数来定义的,这样的话,instanceof的右操作数应当是一个函数。

var d = new Date();//创建一个新对象
d instanceof Date;//true:d是由Data()创建的
d instanceof Object;//true:!!!!!所有的对象都是Object的实例 !!!!
d instanceof Number;//false:d不是一个Number对象

var a =[1,2,3];//创建一个数组
a instanceof Array;//true:a 是一个数组
a instanceof Object;//true:!!!!!所有的数组都是对象 !!!!!
a instanceof RegExp;//false:数组不是正则表达式

所有的数组都是对象

  • 需要注意的是,所有的对象都是Object的实例,当通过instanceof判断一个对象是否是一个类的实例的时候,这个判断也会包含对"父类(superclass)"的检测,如果instanceof的左操作数不是对象的话,instanceof返回false;如果右操作数不是函数,则抛出一个类型错误异常。
  • 为了理解instanceof运算符是如何工作的,必须首先理解"原型链",为了计算表达式 o instanceof f ,JavaScript首先计算f.prototype,然后在o的原型链中查找它,如果找到,那么o是f(或f的父类)的一个实例,表达式返回true。如果f.prototype不在o的原型链中,o就不是f的实例(f和o没有发生派生关系),表达式返回false。
4.10 逻辑表达式

逻辑运算符"&&"、"||"、"!"是对操作数进行布尔算术运算,经常和关系运算符一起配合使用,逻辑运算符将多个表达式组合起来组成一个更复杂的表达式。
4.10.1 逻辑与(&&)

  • 逻辑运算符"&&“对两个值执行与(AND)操作,只有在第一个操作数和第二个操作数都是true的时候,它才返回true,否则返回false。”&&"的操作数不一定是布尔值。
  • 运算符首先计算"&&“左侧的表达式。如果计算结果是假值,那么整个表达式也一定是假值,因此”&&"这时简单地返回左操作数的值,并不会对右操作数进行计算。
var o = {x : 1};
var p = null;
o && o.x;//1:o 是真值,因此返回值为o.x
p && p.x;//null:p是假值,因此将其返回,而并不计算p.x(如果计算p.x的话会抛出一个类型错误异常)

"&&"的行为有时候称作“短路”,很多代码利用这一特性有条件地执行代码

if(a == b) stop();
(a == b) && stop();//只有在 a == b 的时候才会调用stop()

4.10.2 逻辑或(||)

  • 逻辑运算符"||“对两个操作数做布尔或(OR)运算。如果其中一个操作数是真值,则它返回一个真值;如果两个数都是假值,则返回假值。和”&&"运算符一样,同样应当避免右操作数包含一些具有副作用的表达式,除非你目的明确的在右侧使用带副作用的表达式,而有可能不会计算右侧的表达式。
  • 这个运算符最常用的方式是用来从一组备选表达式中选出第一个真值表达式。
var max = max_width || preferences.max_width || 500;

如果max_width已经定义了,直接使用它;否则在preferences对象中查找max_width,如果没有定义它,则使用一个写死的常量
这种惯用法通常用在函数体内,用来给参数提供默认值

function copy(o,p){//将o的成员属性复制到p中,并返回p
  p = p || {};//如果向参数p没有传入任何对象,则使用一个新创建的对象
}

4.10.3 逻辑非(!)

  • "!"运算符是一个一元运算符。它放置在一个单独的操作数之前,它的目的是将操作数的布尔值进行求反。
  • 和"&&“和”||“不同,”!“与运算符首先将其操作数转换为布尔值,然后再对布尔值求反。也就是说”!"总是返回true或false,并且可以通过使用两次逻辑非运算来得到一个值的等价布尔值:!!x。
  • 对于p和q取任意值,这两个等式都永远成立
!(p && q) === !p || !q;
!(p || q) === !p && !q; 
4.11 赋值表达式

JavaScript使用"=“运算符来给变量或属性赋值。”="运算符的左操作数是一个左值:一个变量或对象属性(或数组元素),右操作数是任意类型的任意值,赋值表达式的值就是右操作数的值。

var o = {x : 0};
var i = o;//将变量i设置为o
o.x = 1;//将对象o的属性x设置为1
  • "="具有非常低的优先级,有时候需要配合圆括号以保证正确的运算顺序
  • 赋值操作符的结合性是从右至左,也就是说,如果一个表达式中出现了多个赋值运算符,运算符的顺序是从右到左。
var i = j = k = 0;//把三个变量都初始化为0

带操作的赋值运算
运算符"+="可以作用于数字或字符串,如果操作数是数字,它将执行加法运算和赋值操作;如果操作数是字符串,它就执行字符串的连接操作和赋值操作。

运算符示例等价于
+=a+=ba=a+b
-=a-=ba=a-b
*=a*=ba=a*b
/=a/=ba=a/b
%=a%=ba=a%b
<<=a<<=ba=a<<b
>>=a>>=ba=a>>b
>>>=a>>>=ba=a>>>b
%=a%=ba=a%b
&=a&=ba=a&b
|=a|=ba=a|b
^=a^=ba=a^b
  • 大多数表达式为:a op= b(表达式a计算了一次) 等价于 a = a op b(表达式a计算了两次)
  • 只有在a包含具有副作用的表达式(比如函数调用和赋值操作)的时候,两者才不等价。例如:
var i = 1;
var data = [3,4,5,6,7];
data[i++];//4
data[i++] *= 2;//8 :4*2
data[i++];//6
data[i++] = data[i++] * 2;//14 : 7*2
4.12 表达式计算

4.12.1 eval()
和很多其他解释性语言一样,JavaScript同样可以解释允许由JavaScript源代码组成的字符串,并产生一个值。JavaScript通过全局函数eval()来完成这个工作:

  • FireFox在解释eval()函数的时候如果出现被阻拦,在浏览器地址栏输入about:config 搜索 security.csp.enable 将true改为false就可以运行了
eval("3+2");//5
  • eval()只有一个参数。如果传入的参数不是字符串,它直接返回这个参数。如果传入的参数是字符串,它会把字符串当成JavaScript代码进行编译(parse)(注:编译不包括代码的执行),如果编译失败则抛出一个语法错误异常;如果编译成功则返回字符串中的最后一个表达式或语句的值,如果最后一个表达式或语句没有,最终返回undefined;如果字符串抛出一个异常,这个异常将把该调用传递给eval()。
  • 关于eval()最重要的是,它使用了调用它的变量作用域环境。也就是说,它查找变量的值和定义新变量和函数的操作和局部作用域中的代码完全一样。
  • 如果一个函数定义了一个局部变量x,然后调用函数eval(“x”),它会返回局部变量的值。如果它调用eval(“x=1”),它会改变局部变量的值。如果函数调用了eval(“var y = 3;”),它会声明一个新的局部变量y。一个函数可以声明一个局部函数:eval("function f() { return x+1}");
  • 如果在最顶层代码中调用eval(),它会作用于全局变量和全局函数
  • 需要注意的是,传递给eval()函数的字符串必须在语法中讲的通,如果字符串作为一个单独的脚本是有语义的,那么将其传递给eval()作参数是完全没有问题的,否则,eval()将抛出语法错误异常。
    4.12.2 全局eval()
  • eval()具有改变局部变量的能力。当通过别名调用时,eval()会将其字符串当成顶层的全局代码来执行。执行的代码可能会定义新的全局变量和全局函数,或者给全局变量赋值,但却不能使用或修改主调函数中的局部变量,因此不会影响到函数内部的代码优化。
  • 当直接使用非限定的“eval”名称来调用eval()函数时,通常称为"直接eval"。直接调用eval()时,它总是在调用它的上下文作用域内执行。其他的间接调用则使全局对象作为其上下文作用域,并且无法读、写、定义局部变量和函数。
var geval = eval;//使用别名调用eval将是全局eval
var x = "global";
var y = "global";//两个全局变量
function f(){//函数内执行局部eval
  var x = "local";
  eval("x += ' changed';");
  return x;
}
function g(){//函数内执行全局eval
  var y = "local";
  geval("y += ' changed';");
  return  y;
}
console.log(f(),x);//local changed global:更改了局部变量
console.log(g(),y);//local global changed:更改了全局变量

4.12.3 严格eval()

  • ECMScript 5规定,当在严格模式下调用eval()时,或者eval()执行的代码段以"use strict"指令开始,这里的eval()是私有上下文环境中的局部eval。也就是说,在严格模式下,eval执行代码段可以查询或更改局部变量,但不能在局部作用域中定义新的变量或函数。
  • 此外,严格模式将"eval"列为保留字,这让eval()更像一个运算符。不能用一个别名覆盖eval()函数。并且变量名、函数名、函数参数、异常捕获的参数都不能取名为"eval"
4.13 其他运算符

4.13.1 条件运算符(?: )
形式:操作数1 ? 操作数2 : 操作数3
第一个操作数当作布尔值,如果它是真值,将计算第二个操作数,并返回其结果;否则如果第一个操作数是假值,将计算第三个操作数,并返回其结果。
其实使用if语句也会带来同样的效果

var username = "cyy";
greeting = "hello " + (username ? username : "three");//"hello cyy"
//等价于
greeting = "hello ";
if(username)
  greeting += username;//"hello cyy"
else
  greeting += "three";

4.13.2 typeof运算符
typeof是一个一元运算符,放在其单个操作数前面,操作数可以是任意类型。返回值为表述操作数类型的一个字符串
任意在typeof运算后的返回值:

xtypeof x
undefined“undefined”
null“null”
true或false“boolean”
任意数字或NaN“number”
任意字符串“string”
任意函数“function”
任意内置对象(非函数)“object”
任意宿主对象由编译器各自实现的字符串,但不是"undefined"、“boolean”、“number”、“string”

typeof最常用的用法是写在表达式中,例如:

var value = "cyy52";
(typeof value == "string") ? " ' " + value + " ' " : value;//" ' cyy52 ' "

typeof运算符同样在switch语句中非常有用,typeof运算符可以带上圆括号。typeof(i);

  • 我们注意到当操作数是null的时候typeof返回"object",如果想将null和对象区分开,则必须针对特殊值显示检测。如果想区分对象的类,则需要使用其他手段,比如instanceof运算符、class特性以及constructor属性。
  • 尽管JavaScript中的函数是对象的一种,但typeof运算符还是将函数特殊对待,对函数做typeof运算有着特殊的返回值。所有的函数都是可执行的,但是对象也有可能是可执行的,可以像调用函数一样调用它,但它并不是一个真正的函数。根据ECMAScript 3规范,对于所有内置可执行对象,typeof运算符一律返回"function"。ECMAScript 5规范扩充至所有可执行对象,包括内置对象和宿主对象,所有可执行对象进行typeof运算都将返回"function"。
    4.13.3 delete运算符
    delete是一元操作符,它用来删除对象属性或数组元素。
var o ={x:1,y:2};
delete o.x;
"x" in o;//false
var a = [1,2,3];
delete a[2];
2 in a;//false : 注意此时的2表示数组下标而不是2这个值
a.length;//3 : 注意数组的长度并没有改变,尽管删除了这个元素,但删除操作留下了一个"洞",实际上并没有修改数组的长度
  • 删除属性或删除数组元素不仅仅是设置了一个undefined的值。当删除一个属性时,这个属性将不再存在。读取一个不存在的属性的值的时候将返回undefined,可以通过in运算符来检测这个属性是否在对象中存在。
  • delete希望它的操作数是一个左值,如果不是左值,那么delete将不进行任何操作,同时返回true;否则delete将试图删除这个指定的左值,删除成功返回true。
  • 然而并不是所有的属性都可以删除的,如:一些内置核心和客户端属性、通过var语句声明的变量、通过function语句定义的函数和函数参数,都不能删除。
  • 在ECMAScript 5 严格模式中如果delete的操作数是非法的(如变量、函数、函数参数),delete操作将抛出一个语法错误异常,只有操作数是一个属性访问表达式的时候它才会正常工作。严格模式下,delete删除不可配置的属性时会抛出一个类型错误异常。非严格模式下,这些delete操作都不会报错,只是简单的返回false以表明操作数不能执行删除操作。
var o ={x:1,y:2};
delete o.x;//true
typeof o.x;//"undefined":属性不存在
delete o.x;//true:删除不存在的属性
delete o;//false:不能删除通过var声明的变量
delete 1;//true:参数不是一个左值,没有执行删除操作并返回true
this.x = 1;//给全局对象定义一个属性,这里没有使用var
delete x;//true : 试图删除它,非严格模式下返回true;非严格模式下抛出异常
x;//运行错误,没有定义x

4.13.4 void运算符
void是一个一元运算符,它出现在操作数之前,操作数可以是任意类型。操作数会照常计算,但忽略计算结果并返回undefined。由于void会忽略操作数的值,因此在操作数具有副作用的时候使用void来让程序更具语义。
4.13.5 逗号运算符(,)
逗号运算符是二元运算符,它的操作数可以是任意类型。它首先计算左操作数,然后计算右操作数,最后返回右操作数的值。

i = 0 ,j = 1 , k = 2;//2
//等价于
i = 0 ; j =1 ; k = 2;//2

逗号运算符最常用的场景是在for循环中,这个for循环通常具有多个循环变量:

for (var i=0 , j=10 ; i<j ; i++,j--)
  console.log(i+j);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值