《JavaScript权威指南第六版》:表达式和运算符
原始表达式(primary expression),包括常量或直接量,关键字和保留字
1.直接量
1.23 //数字直接量
"hello" //字符串直接量
/pattern/ //正则表达式直接量复制代码
2.保留字
true //返回一个布尔值:真
false //返回一个布尔值:假
null //返回一个值:空
this //返回"当前"对象复制代码
3.变量
i //返回变量i的值
sum //返回sum的值
undefined //undefined是全局变量,和null不同,他不是一个关键字复制代码
对象和数组的初始化表达式
1.数组初始化表达式
[] //一个空数组:[]内留空即表示该数组没有任何元素
[1+2,3+4] //拥有两个元素的数组,第一个是3,第二个是7
var mamtrix = [[1,2,3],[4,5,6],[7,8,9]] //嵌套
var sparseArray = [1,,,,5]; //省略的空位会填充值undefined复制代码
2.对象初始化表达式
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.identifier //表达式指定对象,标识符则指定需要访问的属性的名称
expression[expression] //表达式指定要访问的属性的名称或者代表要访问数组元素的索引复制代码
eg:
var o = {x:1,y:{z:3}}; //一个示例对象
var a = [0,4,[5,6]]; //一个包含这个对象的示例数组
o.x //=>1:表达式o的x属性
o.y.z //=>3:表达式o.y的z属性
o["x"] //=>1:对象o的x属性
a[1] //=>4:表达式a中索引为1的元素
a[2]["1"] //=>6:表达式a[2]中索引为1的元素
a[0].x //=>1:表达式a[0]的x属性复制代码
对象创建表达式
new Object();
new Point(2,3);复制代码
运算符概述
1.操作数的个数
一元运算符
二元运算符
三元运算符
2.操作数类型和结果类型
3.左值
4.运算符的副作用
5.运算符优先级
6.运算符的结合性
7.运算顺序
算术表达式
1."+"运算符
(1).加法
(2).字符串连接
1 + 2 //=>3:加法
"hello" +" "+ "world" //=>"hello world":字符串连接
"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"复制代码
(3)."+"运算符具有从左至右的结合性
2.一元算术运算符
(1).一元加法(+)
(2).一元减法(-)
(3).递增(++)
前增量
var i=1,j=++i //i和j的值都是2复制代码
后增量
var i=1,j=i++ //i是2,j是1复制代码
(4).递减(--)
3.位运算符
-----2017.6.26--------
(1).位运算符要求它的操作数是整数
(2).位运算符会将NaN、Infinity和-Infinity都转换为0
(3).按位与(&)
只有两个操作数中相对应的位都是1,结果中的这一位才是1
(4).按位或(|)
如果其中一个操作数相应的位为1,或者两个操作数相应位都是1,那么结果中的这一位就是1
(5).按位异或(^)
异或是指第一个操作数为true或第二个操作数为true,但两者不能同时为true。如果两个操作数中只有一个相应位为1(不能同时为1),那么结果中的这一位就是1。
(6).按位非(~)
(7).左移(<<)
(8).带符号右移(>>)
(9).无符号右移(>>>)
关系表达式
关系表达式总是返回一个布尔值
1.相等和不等运算符
(1)."=" //=>得到或赋值
(2)."==" //=>相等,定义非常宽松,可以允许进行类型转换
(3)."===" //=>恒等,严格相等
(4)."!=" //=>不相等
(5)."!==" //=>不严格相等
2.比较运算符
比较运算符用来检测两个操作数的大小关系(数值大小或者字母表的顺序)
(1).小于(<)
(2).大于(>)
(3).小于等于(<=)
(4).大于等于(>=)
加号运算符中一个操作数是字符串的话,则进行字符串连接操作。比较运算符只有在两个操作数都是字符串的时候,才会进行字符串的比较。
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复制代码
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:数字转换为字符串
3 in data //=>false:没有索引为3的元素复制代码
4.instanceof运算符
instanceof运算符希望左操作数是一个对象,右操作数标识对象的类。如果左侧的对象是右侧类的实例,则表达式返回true,否则返回false
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:数组不是正则表达式复制代码
所有的对象都是Object的实例
逻辑表达式
---------2017.6.27---------
1.逻辑与(&&) =>AND
(1)."&&"运算符可以从三个不同的层次进行理解
A.第一层:当操作数都是布尔值的时候,并且两个都为true,它才返回true
x == 0 && y == 0 //只有在x和y都是0的时候,才返回true复制代码
关系运算符的优先级比"&&"(和"||")要高,因此类似这种表达式可以放心地书写,而不用补充圆括号
B.第二层:但并没有说明这个"真值"或者"假值"到底是什么值。
C.第三层:会先根据左操作数的值进行计算,若为假,就为假;若为真,根据右操作数的值进行计算。
var o ={x:1};
var p = null;
o && o.x //=>1:o是真值,因此返回值为o.x
p && p.x //=>null:p是假值,因此将其返回,而不去计算p.x复制代码
(2)."&&"的行为有时称做"短路"(shot circuiting)
if(a == b){
stop() //只有在a == b的时候才调用stop()
}
(a == b) && stop(); //同上复制代码
2.逻辑或(||) =>OR
-------2017.6.28----------
"||"运算符对两个操作数做布尔或(OR)运算。如果其中一个或者两个操作数是真值,它返回一个真值。如果两个操作数都是假值,它返回一个假值。
var max = max_width || preferences.max_width || 500;
//如果max_width已经定义了,直接使用它,否则在preferences对象中查找max_width
//如果没有定义它,则使用一个写死的常量
//将o的成员属性复制到p中,并返回p
function copy(o,p){
p = p || {}; //如果向参数p没有传人任何对象,则使用一个新创建的对象
//函数体内的主逻辑
}复制代码
3.逻辑非(!)
"|"运算符是一元运算符。它放置在一个单独的操作数之前。它的目的是将操作数的布尔值进行求反。
//对于p和q取任意值,这两个等式都永远成立
!(p && q) === !p || !q
!(p || q) === !p && !q复制代码
赋值表达式
1.JavaScript使用"="运算符来给变量或者属性赋值
i = 0; //将变量i设置为0
o.x = 1; //将对象o的属性x设置为1
(a = b) == 0; //"="具有非常低的优先级,需要补充圆括号以保证正确的运算顺序复制代码
2.赋值操作符的结合性是从右至左,运算顺序是从右到左
i = j = k = 0; //把三个变量初始化为0复制代码
3.带操作的赋值运算
运算符"+="执行的是加法运算和赋值操作
total += sales_tax
total = total + sales_tax复制代码
4.如果其操作数是数字,它将执行加法运算和赋值操作;如果其操作数是字符串,它将执行字符串连接操作和赋值操作;
表达式计算
1.JavaScript通过全局函数eval()解释运行由JavaScript源代码组成的字符串,并产生一个值。
eval("3+2") //=>5复制代码
2.eval()是一个函数还是一个运算符
(1).eval()只有一个参数。如果传人的参数不是字符串,它直接返回这个参数。如果参数是字符串,它会把字符串当成JavaScript代码进行编译。
(2).它使用了调用它的变量作用域环境。也就是说,它查找变量的值和定义新变量和函数的操作和局部作用域中的代码完全一样。
eval("function f(){ return x+1; }") //声明一个局部函数复制代码
(3).全局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); //localchanged global
console.log(g(),y); //local globalchanged复制代码
-----------2017.7.11---------
(4).严格eval()
在严格模式下,eval执行的代码段可以查询或更改局部变量,但不能在局部作用域中定义新的变量或函数
其他运算符
1.条件运算符(?:)
(1).条件运算符是JavaScript中唯一的一个三元运算符(三个操作数)
x > 0 ? x : -x复制代码
第一个操作数当成布尔值,如果它是真值,那么将计算第二个操作数,并返回其计算结果。
否则,如果第一个操作数是假值,那么将计算第三个操作数,并返回其计算结果。
第二个和第三个操作数总是会计算其中之一,不可能两者同时执行。
greeting = "hello" + (username ? username : "three");
greeting = "hello";
if(username){
greeting += username;
}else{
greeting += "three";
}复制代码
2.typeof运算符
(1).typeof是一元运算符,放在其单个操作数的前面,操作数可以是任意类型。返回值为表示操作数类型的一个字符串。
(typeof value == "string") ? "'" + value + "'" : value;复制代码
3.delete运算符
(1).delete是一元运算符,它用来删除对象属性或者数组元素。
(2).它是用来做删除操作的,不是用来返回一个值的
var o = {x : 1, y : 2}; //定义一个对象
delete o.x; //删除一个属性
"x" in 0 ; //=>false:这个属性在对象中不再存在
var a = [1,2,3]; //定义一个数组
delete a[2]; //删除最后一个数组元素
2 in a; //=>false:元素2在数组中已经不存在了
a.length; //=>3:数组长度并没有改变,尽管上一行代码删除了这个元素。
var o ={x:1,y:2}; //定义一个变量,初始化为对象
delete o.x; //删除一个对象属性,返回true
typeof o.x; //属性不存在,返回"undefined"
delete o.x; //删除不存在的属性,返回true
delete o ; //不能删除通过var声明的变量,返回false;在严格模式下,将抛出一个异常
delete 1; //参数不是一个左值,返回true
this.x = 1; //给全局对象定义一个属性,这里没有使用var
delete x; //试图删除它,在非严格模式下返回true;在严格模式下会抛出异常,这时使用"delete this.x"来替代
x; //运行时错误,没有定义x复制代码
4.void运算符
(1).void是一元运算符,它出现在操作数之前,操作数可以是任意类型。
操作数会照常计算,但忽略计算结果并返回undefined
<a href="javascript:void window.open();">打开一个新窗口</a>复制代码
5.逗号运算符
(1).逗号运算符是二元运算符,它的操作数可以是任意类型。
它首先计算左操作数,然后计算右操作数,最后返回右操作数的值
i = 0, j = 1, k = 2; //=>2
i = 0; j = 1; k = 2;复制代码
总是会计算左侧的表达式,但计算结果忽略掉
//for循环中的第一个逗号是var语句的一部分
//第二个逗号是逗号运算符
//它将两个表达式(i++和j--)放在一条(for循环中的)语句中
for(var i=0,j=10;i<j;i++,j--){
console.log(i+j);
}
作者:xf27
链接:https://juejin.im/post/59f49b8e51882561a05a55cd
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。