《JavaScript权威指南(第六版)》笔记0x2 表达式和运算符

    表达式(expression) JavaScript中的一个短语, JavaScript解释器会将其计算(evaluate)出一个结果。程序中的常量是最简单的一类表达式。变量名也是一种简单的表达式,它的值就是赋值给变量的值。复杂表达式是由简单表达式组成的。

    将简单表达式组合成复杂表达式最常用的方法就是使用运算符(operator)。运算符按照特定的运算规则对操作数(通常是两个)进行运算,并计算出新值。

原始表达式

//常数值
1.23//数字直接量
"hello"//字符串直接量
/pattern///正则表达式直接量

//保留字
true//返回一个布尔值:真
false//返回一个布尔值:假
null//返回一个值:空
this//返回"当前"对象

//变量
i//返回变量i的值
sum//返回sum的值
undefined//undefined是全局变量,和null不同,它不是一个关键字

对象和数组的初始化表达式

[]//一个空数组: []内留空即表示该数组没有任何元素
[1+2,3+4]//拥有两个元素的数组,第一个是3,第二个是7

//表达式嵌套
var matrix=[[1,2,3],[4,5,6],[7,8,9]];

//数组直接量中的列表逗号之间的元素可以省略,这时省略的空位会填充值undefined。
//结尾处可以留下单个逗号,这时并不会创建一个新的值为undefined的元素
var sparseArray=[1,,,,5];

//对象初始化表达式
var p={x:2.3,y:-1.2};//一个拥有两个属性成员的对象
var q={};//一个空对象
q.x=2.3;q.y=-1.2;//q的属性成员和p的一样
//对象直接量嵌套
var rectangle={upperLeft:{x:2,y:2},
lowerRight:{x:4,y:5}};

函数定义表达式

//这个函数返回传入参数值的平方
var square=function(x){return x*x;}

属性访问表达式

expression.identifer
expression[expression]

调用表达式

f(0)//f是一个函数表达式; 0是一个参数表达式
Math.max(x,y,z)//Math.max是一个函数;x,y和z是参数
a.sort()//a.sort是一个函数,它没有参数

对象创建表达式

new Object()
new Point(2,3)

运算符

    JavaScript中的运算符用于算术表达式、比较表达式、逻辑表达式、赋值表达式等。

    操作数的个数

    JavaScript中的大多数运算符(比如“*”乘法运算符)是一个二元运算符(binaryoperator),将两个表达式合并成一个稍复杂的表达式。 JavaScript同样支持一些一元运算符(unaryoperator),它们将一个表达式转换为另一个稍复杂的表达式。表达式-x中的“-”运算符就是一个一元运算符,是将操作数x求负值。最后, JavaScript支持一个三元运算符(ternary operator),条件判断运算符“?:”,它将三个表达式合并成一个表达式。

    操作数类型和结果类型

    JavaScript运算符通常会根据需要对操作数进行类型转换.

    运算符的结合性

w=x-y-z;
w=((x-y)-z);//等效于上式

x=~-y;
w=x=y=z;
q=a?b:c?d:e?f:g;

x=~(-y);w=(x=(y=z));q=
a?b:(c?d:(e?f:g));

算术表达式

    “+”运算符

1+2//=>3
"hello"+""+"there"//=>"hello there"
"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"

    一元算术运算符

    在JavaScript中,一元运算符具有很高的优先级,而且都是右结合(rightassociative)。

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

    位运算符

    按位与(&)
    位运算符“&”对它的整型操作数逐位执行布尔与(AND)操作。只有两个操作数中相对应的位都是1,结果中的这一位才是1。
    按位或(|)
    位运算符“|”对它的整型操作数逐位执行布尔或(OR)操作。如果其中一个操作数相应的位为1,或者两个操作数相应位都是1,那么结果中的这一位就为1。
    按位异或(^)
    异或是指第一个操作数为true或第二个操作数为true,但两者不能同时为true。如果两个操作数中只有一个相应位为1(不能同时为1),那么结果中的这一位就是1。
    按位非(~)
    运算符“~”是一元运算符,位于一个整型参数之前,它将操作数的所有位取反。根据JavaScript中带符号的整数的表示方法,对一个值使用“~”运算符相当于改变它的符号并减1。
    左移(<<)
    将第一个操作数的所有二进制位进行左移操作,移动的位数由第二个操作数指定,移动的位数是0~31之间的一个整数。例如,在表达式a<<1中, a的第一位变成了第二位, a的第二位变成了它的第三位,以此类推。新的第一位用0来补充,舍弃第32位。将一个值左移1位相当于它乘以2,左移两位相当于乘以4,以此类推。例如, 7<<2=28。
    带符号右移(>>)
    运算符“>>”将第一个操作数的所有位进行右移操作,移动的位数由第二个操作数指定,移动的位数是0~31之间的一个整数。右边溢出的位将忽略。填补在左边的位由原操作数的符号决定,以便保持结果的符号与原操作数一致。如果第一个操作数是正数,移位后用0填补最高位;如果第一个操作数是负的,移位后就用1填补高位。将一个值右移1位,相当于用它除以2(忽略余数),右移两位,相当于它除以4,以此类推,例如, 7>>1=3, -7>>1=-4。
    无符号右移(>>>)
    运算符“>>>”和运算符“>>”一样,只是左边的高位总是填补0,与原来的操作数符号无关,例如, -1>>4=-1,但是-1>>>4=0x0FFFFFFF。

    关系表达式

1+2//加法.结果是3
"1"+"2"//字符串连接,结果是"12"
"1"+2//字符串链接, 2转换为"2",结果是"12"
11<3//数字的比较,结果为false
"11"<"3"//字符串比较,结果为true
"11"<3//数字的比较, "11"转换为11,结果为false
"one"<3//数字的比较, "one"转换为NaN,结果为false

//in运算符
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:数字转换为字符串
3 in data//=>false:没有索引为3的元素

//instanceof运算符
var d=new Date();//通过Date()构造函数来创建一个新对象
d instanceof Date;//计算结果为true, d是由Date()创建的
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,数组不是正则表达式

逻辑表达式

//逻辑与(&&)
x==0&&y==0//只有在x和y都是0的时候,才返回true

var o={x:1};
var p=null;
o&&o.x//=>1:o是真值,因此返回值为o.x
p&&p.x//=>null:p是假值,因此将其返回,而并不去计算p.x

//“&&”的行为有时称做“短路”(short circuiting)
if(a==b)stop();//只有在a==b的时候才调用stop()
(a==b)&&stop();//同上

//逻辑或(||)
//如果max_width已经定义了,直接使用它;否则在preferences对象中查找max_width
//如果没有定义它,则使用一个写死的常量
var max=max_width||preferences.max_width||500;

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

//逻辑非(!)
//对于p和q取任意值,这两个等式都永远成立
!(p&&q)===!p||!q
!(p||q)===!p&&!q

赋值表达式

i=0//将变量i设置为0
o.x=1//将对象o的属性x设置为1

i=j=k=0;//把三个变量初始化为0

total+=sales_tax
total=total+sales_tax//等价于上

表达式计算

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

eval("3+2")//=>5

    eval()是一个函数,但由于它已经被当成运算符来对待了,因此将它放在本章来讲述。 JavaScript语言的早期版本定义了eval()函数,从那时起,该语言的设计者和解释器的作者对其实施了更多限制,使其看起来更像运算符。现代JavaScript解释器进行了大量的代码分析和优化。而eval()的问题在于,用于动态执行的代码通常来讲是不能分析。一般来讲,如果一个函数调用了eval(),那么解释器将无法对这个函数做进一步优化。

    eval()只有一个参数。如果传入的参数不是字符串,它直接返回这个参数。如果参数是字符串,它会把字符串当成JavaScript代码进行编译(parse),如果编译失败则抛出一个语法错误(SyntaxError)异常。如果编译成功,则开始执行这段代码,并返回字符串中的最后一个表达式或语句的值,如果最后一个表达式或语句没有值,则最终返回undefined。如果字符串抛出一个异常,这个异常将把该调用传递给eval() 。

var geval=eval;//使用别名调用eval将是全局eval
var x="global",y="global";//两个全局变量
function f(){//函数内执行的是局部eval
var x="local";//定义局部变量
eval("x+='changed';");//直接eval更改了局部变量的值
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 globalchanged":

其他运算符

    条件运算符(?:)

x>0?x:-x//求x的绝对值

     typeof运算符

(typeof value=="string")?"'"+value+"'":value

     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在数组中已经不存在了
a.length//=>3:注意,数组长度并没有改变,尽管上一行代码删除了这个元素,但删除操作留下了一个“洞”,实际上并没有修改数组的长度,因此a数组的长度仍然是3

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值