js基础-表达式和运算符

接着之前的知识点,继续学习js.还是一如既往的在简书上求个赞~

表达式呢,它是JavaScript的一个短语,js会将表达式计算出一个结果。最简单的表达式是常量。变量名也是一种简单的表达式,他的值就是赋值给变量的值。赋值的表达式有简单表达式组成,而如何去组就依靠运算符。

一、表达式

原始表达式

原始表达式是最简单的表达式了,主要包含常量,直接量、变量和关键字

3.14   //数字直接量
“hello”  //字符串直接量
/pattern/    //则表达式直接量
true  //真
false  //假
null   //空
this   //返回”当前“对象
var i;   //返回变量i的值
var sum;   //返回变量sum的值
undefined  //全局变量

这里的this是一个关键字,经常在面向对象编程中出现,在后面我们会详细进行研究~。

对象表达式

对象表达式和数组表达式实际上是一个新创建的对象和数组。也可以叫做“对象直接量”和“数组直接量”。对象直接量是有两个花括号组成{},初始化一个对象

var obj={}    //初始化一个obj对象
var foo={x:1,y:2}   //初始化一个foo对象,并赋予属性和值

对象表达式里面也可以嵌套

var obj={
     a{x:1},
     b{y:2}
}

数组表达式

数组表达式和对象表达式类似,只是花括号变成了中括号[]

var arr=[]
var arr2=[1,1,2,2,,3,3]

[]初始化一个数组,并且可以给数组元素赋值,数组各元素间用逗号隔开,当逗号隔开是没有值,则表示所在的数组元素值为undefined。

var arr=[1,,];
console.log(arr.length);
console.log(arr[1]);

数组表达式

函数表达式也可以称作“函数直接量”,表示初始化一个函数,function functionName(arguments){},function后面跟着函数名称再假小括号里面是传递给函数的形式参数,再用花括号包含函数体。当然function后面也可不要函数名,或这没有参数,

btn.onclick=function(){
    //dosomething
}

这种叫匿名函数。

属性访问表达式

属性访问表达式是为了等到一个对象属性或者数组属性的值,有两种语法

一是点语法 对象.属性

而是[]发 对象[属性]或者数组[属性]

var obj={x:1,y:2}
var arr=[1,2,3]

console.log(obj.x)    //得到x的值
console.log(obj.y)   //得到y的值
或者
obj["x"];
obj["y"]

console,log(arr[0]);  //得到数组第一项元素
console.log(arr[1]); //得到数组第二项元素

这两种方式都是没问题的,但是再属性是标识符(变量)或者不确定的值的时候优先使用[].

调用表达式

调用是函数或者方法的特有,有一个小括号组成()

function sayHi(){    //定义函数
    console.log("Hi")
}
var a{
    sort:function(){
        //dosomething
    }
}
sayHi()   //调用函数
Math.max(x,y,z)  //Math.max是一个内置函数,x,y,z是参数
a.sort()    //调用对象a的sort函数

对象创建表达式

对象创建表达式创建一个对象并调用一个函数(这个函数叫做构造函数)初始化对象的属性,对象创建表达式前面有个 new 关键字

new Object();
new Point(1,2);
new Array()

如果构造函数里面不需要参数,可以省略小括号()

new Objec();
new Function();
new Array();

关于构造函数和new的用法,我们接下去会详细来探讨,这里简单知道下,它是可以在设计模式中行作用的。

二、运算符

js的运算操作等依赖于运算符,运算符有算数运算符、比较运算符、逻辑运算符、复制运算符等,我们通过一个图表来做一个参考。

图表中,运算符是根据运算符的优先级排序的。前面的运算符优先级要高于后面的运算符优先级。

标题为A的列表表示运算符的结合性L (从左到右)或R(从右到左),所谓的结合性就是指定了在多个具有同样优先级的运算符表达式中的运算顺序。从左到右是指运算符的执行顺序是按照由左到右的顺序进行。例如减法运算符具有从左到右的结合性

a=x-y-z;等价与a=((x-y)-z)
image

*lval是left-value的简写,意思是"左值".他是一个术语。指的市表达式只能出现再赋值运算符(=)的左侧。在js中,变量、对象属性和数组元素均是左值。

运算符的副作用

有一些表达式具有副作用,就是说前后表达式的运算会相互的影响。比如赋值表达式(=),给一个变量赋值,那么使用这个变量或属性的表达式的值都会发生改变,此外还有++和--递增递减运算符。delete运算符同样也是,删除一个属性就像(不一定一样)给这个属性赋值undefined

var a=1;
console.log(a);
var a=2;
console.log(a);
...

运算符的优先级

上图中运算符是按照优先级从高到低排序的,每个水平线分割的一组运算符具有相同的优先级。运算符优先级控制这运算符的执行顺序。优先级高的运算符的执行总是先与优先级低的运算符。

注意的是=赋值运算符具有最低的优先级,因此赋值操作是再右侧的表达式计算出结果后进行的。

运算符也可以像数学那样,使用圆括号()来指定那个运算符的顺序。接下来就来了解下常见的运算符,其他的运算符大家可以去书上看更加详细的介绍~

算术表达式

算术运算符加(+)减(-)乘(*)除(/)模(%)也叫余。

首先,我们抛开前面复杂的概念,单纯来理解这些运算符。要知道的是,运算符具有隐式转换的作用。这些算术运算符都希望自己左右两侧操作数是数值,所有会对非数值的操作是转换为数组,转换的规则可以参考我之前写的文章。所有无法转换为数字的操作数都会转换成NaN值。如果操作数是NaN的话,那么算术运算符的结果也为NaN.

+运算符既可以对两个数字做加法运算,也可以做字符串连接

1+1  //2
“a”+1   //"a1"

注意,当+左右两侧操作符有一个是字符串的时候,那么他们就会做字符串连接了。还有()可以改变运算符的运算顺序,例如

1+1+“a”    //"2a"
1+(1+"a")   //11a

其他的运算也是类似,这里我们重点强调下%求余运算符,直接上代码

3%3   //0
4%3   //1
5%3   //2
6%3   //0

就是求余的操作。

一元算术运算符

算术运算符还有个可以操作与单独的操作数,并产生一个新值,这就是一元运算符。常见有++(递增) 、--(递减)、+(加)、(-)减法,其中加+和-即使一元运算符也是二元运算符。+可以对操作数转换为数字,并返回这个数字,-可以对操作数转换为数字,并返回这个数字的同时改变运算结果的符号。下面我们重点关照++和--。

++

递增运算符的操作数可以再操作符的左侧也可以再右侧。以此根据分别称之为前增量和后增量。

下面我们来看一个直观的例子来这两个

var i=1;
var j=++i
console.log(i+" "+j);   //2  2 

var a=1;
var b=a++;
console.log(a+" "+b);   //2 1

区别:前增量对操作数进行增量计算,并且返回计算后的值。后增量对操作数进行增量计算,但返回为增量计算的值。

同理--(递减也是同样道理)

var x=2;
var y=--x;
console.log(x+" "+y);

var c=2;
var d=c++;
console.log(c+" "+d);

关系表达式

关系运算符呢用于测试两个值的关系,他们间的关系有相等、小于、属性从属关系等等,关系运算符会根据两个值的关系是否存在而返回true或者false。他们总是会返回一个布尔值

==(相等)和===(全等运算符)运算符用于比较两个值是否相等。他们允许任意类型的操作数,如果操作数相等则返回true,否则返回false.===全等是严格相等的运算符,它操作两个数是否严格相等,当然啦,相等和严格相等也是有个依据的,我们来仔细理解下。首先,我们把=(等于)放进来一起,他们都有区别的

=是赋值(等于),==是相等,===是严格相等(全等);

!=和!==是==和===运算符的求反。

现在我们来理清下什么情况下==和什么情况下===

首先,我们先来对全等运算符进行讨论,我们在上一篇文章知道,js对象比较就是引用的比较,而不是值的比较,对象只和他们本身是相等的,和他们任何对象都不相等。

===严格运算符首先会计算操作数的值,然后比较两个值,特别注意的是:全等比较过程中没有任何的类型转换

也就是说类型不同,值相等或者值相等类型不同都是不全等的

console.log(1==="1");
console.log(undefined===null)  
console.log(NaN===NaN)
console.log("true"===true)
console.log(0===-0)
var a={}
var c=a;
console.log(a===c);

var x={"a":1};
var y={"a":1};
console.log(x===y);

大家可以动手尝试一下,从上面可以测试得出

类型不同,值相等或者值相等类型不同都是不全等的

NaN和任何数字都不全等,即使是它本身

如果两个数字,一个为0,一个为-0,那么他们是全等的(我认为是特殊的,值和类型相等,但是运算符号不同)

如果两个应用指向同一个对象,那么他们全等,如果指向不懂对象,即使这两个对象具有同样的属性,那么他们也是不全等的。

==相等操作符就没有全等那样严格了,同样,我们理解下==的操做规则

如果两个操作数是全等的,那么他们一定是相等的,这个没有疑问

值相等当时类型不同也是相等的,不同类型比较需要先转换为同类型在来比较值

下面我们上代码,看看掌握了没

console.log(1==2);
console.log(1=="1");
console.log(true==1);
console.log(0==false);
console.log(undefined==null)
console.log("true"=="false");

比较运算符

比较运算符用来检测两个操作数的大小关系(数组大小或者字母表顺序),也就是说只能对数值和字符串进行操作,如果操作数不是数值或者字符串,那么他们会像转换成数值或者字符串进行比较,具体转换规则可以参考上几篇文章。

<小于

如果第一个操作数小于第二个操作数则返回true,否则为false

大于

如果第一个操作数大于第二个操作数则返回true,否则为false

同样还有小于等于<=和大于等于>=

注意比较字符串的时候,字符串是区分大小写的,所有大写字符都小于小写字母。

console.log(1<2);
console.log(“11”>2);
console.log("one"<3);

这里再次提醒下,NaN和任何数进行操作返回的结果都是false.

in运算符

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

var obj={
    x:1,
    y:2
}
console.log("x" in  obj)
console.log("z" in obj);
console.log("toString" in obj)

var arr=[1,2,3]
console.log(“0” in arr);
console.log("1" in arr);
console.log("3" in arr);

要注意是属性名而不是值。还有就是toString()是所有对象都拥有的方法,因为他是从object继承过来的,以后我们会更加仔细来学习

instanceof运算符

instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上,这样说有点晕,很多刚开始学习的人可能很疑惑,我们先简单说下,js在es6之前是没有真正意义上的类的,什么为类了,我理解是一个抽象的总称,而由这些抽象的类具象出来的就叫做对象。好比如:人类(类)和我(对象),动物(类)和猫(具体的个体,具象化的类,也就是对象)。

instanceof的左操作数就是对象,右操作数就是类了,如果对象是类的实例(具象化的独立个体),则instanceof返回true,否则为false.有关与原型,构造函数,类,继承等等,后续我会专门整理出来,按照我的理解尽量让读者看懂,学到东西哈哈。

var obj={};
console.log(obj instanceof Object)

var arr=[];
console.log(arr instanceof Array)

js里用构造函数来模拟类。这里我们不深入探讨,只要知道instanceof的用法就可以了,我在准备些时间,在接下来的专题会更加仔细来学习。

关系表达式就差不错了,接下来来一起探究逻辑表达式~求赞,求收藏

逻辑表达式

逻辑运算符有&&(逻辑与)、||(逻辑非)、和!(逻辑非),他们是对操作数进行布尔值算术运算,怎么说了,因为他们会对“真值”和“假值”进行布尔值转换,从而返回布尔值,他们也经常和关系运算符一起配合使用,组合成更加复杂的表达式。

逻辑与&&

&&逻辑与有左右两个的操作数,首先,他会对第一个操作数进行布尔值运算,“真值”就转换为true,“假值”就转换为false。左边的操作数为false的时候,&&操作符就不会对右边的操作数进行布尔运算,从而直接返回false,如果左边操作数为true的话,那么就会对&&右边的操作数进行布尔运算了,如果右边返回true,则&&操作符,返回true,否则为false.可以理解为“一假必假”。

console.log(true&&false);
console.log(true&&true);
console.log(false&&false);
console.log(false&&true);

js在对&&左边操作数进行运算时,如果左边返回false,那么js就会“偷懒”,不会去判断右边的操作数。

逻辑非||

逻辑非和逻辑与有点类似,||对左右两个操作数进行布尔运算,当左边操作数为true的话就会返回true,也会“偷懒”不去计算右边操作数,而当左边为false的话,哪||就会对右边进行计算,如果右边为true则返回true,否则为false.只有||前后都是false的时候才返回false,否则返回true。可以理解为“一真必真”。

console.log(true||false);
console.log(true||true);
console.log(false||false);
console.log(false||true);

console.log(''||1);
console.log(1||2);

这种特性可以做几个操作

var a='';
...
var b=a||1;

当我们不知道a是否改变了,我们可以用这种技巧,这个和if/else语句类似,只不过写的代码少了。更加精简。

逻辑非!

逻辑非!就是放在操作数之前并对他的操作数转换的布尔值进行求反, 比如!A,如果A是真值,则返回false,如果A是假值,则返回true.并且逻辑非的优先级很高,和操作数紧密绑定在一起。随便说一下,以下,对于pq的取值,等式永远成立,(来自《JavaScript权威指南》)

!(p && q)===!p || q;
!(p || q)===!p && !q

赋值表达式

js使用=运算符来给标识符(变量或者属性等)赋值。

var a=1;
a=2;
var b=a;

=具有非常低的优先级,通常在最后才计算,同时还要注意区分==和===,在之前我们了解过,这里就不说啦。此外,=运算符还可以和其他运算符进行组合操作,组合攻击波有没有~~~

例如

var a=1;
var b;
b+=a;
console.log(b);

这种和其他运算符组合一起的,都有一个规律就是

A+=B 等价与 A=A+B

换成其他符号也是如此的,还有-=、*=、/=、%=等等。

条件运算符?:(三元运算符)

不多说,我直接上个用法,读者就知道啦~

计算结果是否为true ? true的时候取这个值(如果为true) : false的时候去这个值(如果为false);

var a=1;

var b=(a > 0 ? 3 : 0); //b=3

条件运算符的操作数有三个,其中?前面的会进行布尔运算,如果为ture的话就返回 ?后 :前的那个操作数,这个例子时3,因为a是大于0的,如果前面的操作数返回false,那么结果就是最后一个操作数了。

如果用if/else语句来解释的话就好比

var a=1;
var b;
if(a >0 ){
    b=3
}else{
   b=0
}

同样的意思,只不过?:更加精简了,而且他是一个三元运算符,也是目前js中唯一一个三元运算符(以我知识面来说)。

typeof运算符

typeof是一元运算符,放在单个操作数前面,操作数可以是任意类型,返回值有如下

[table id=15 /]

typeof也可以加()像函数一样用也是可以的,只是要注意的是,typeof是运算符,不是函数,

typeof(null)

关于typeof更加深层次的用法,后续有设计~

delete运算符

delete是一元操作符,他是用来删除对象属性活着数组元素的,要记住他是用来做删除操作的,不是用来返回一个值的

var obj={x:1}
delete obj.x;
console.log(obj.x)   //false 这个属性在对象中不再存在

var arr=[1,2.3];
delete arr[2];
console.log(arr)  //最后已经被删除了

注意,用delete删除数组的某一项,数组的长度并没有改变,,当读取一个不存在的属性将返回undefined,还有delete不能删除以var 声明的标识符,和以function函数什么表达式的函数。

void运算符

void是一元运算符,他会忽略计算寄过并返回undefined,由于void会忽略操作数的值,因此再操作数具有副作用的时候使用void来让程序更加语义化

最常用的就是

<a href="javascrit:void(0)">超链接</a>

让用户点击的时候不必显示这个表达式的结果,当然啦,具体怎么用还是具体看实际需求啦。

还有不常用的表达式和运算符没有提到,大家可以去查资料,当然有很多术语,对刚刚接触的开发者有点绕,但是没事的,熟能生巧,滴水穿石,只要坚持下去,什么都不是问题,先打好坚固的基础哈,现在这篇文章就到这儿结束啦,又代表新的篇章要开始啦,欢迎交流,

本文的全部内容就到这了,欢迎大家留言补充。

原创文章,转载请注明出处,谢谢欢迎一起讨论交流

欢迎访问我的个人网站zhengyepan

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容