侧边栏壁纸
博主头像
恪晨博主等级

前端程序员

  • 累计撰写 138 篇文章
  • 累计创建 41 个标签
  • 累计收到 17 条评论

目 录CONTENT

文章目录

JavaScript-权威指南-表达式与运算符

恪晨
2020-03-11 / 0 评论 / 0 点赞 / 3,678 阅读 / 1 字 / 正在检测是否收录...

前言

表达式是JavaScript中的一个短语,JS解释器会将其计算出一个结果;

原始表达式

  原始表达式是表达式最小的单位--它不再包含其他表达式,JavaScript中的原始表达式包含常量和直接量、关键字、变量。

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

  对象和数组初始化表达式实际上是一个新创建的对象和数组,这些初始化表达式有事称作“对象直接量”或者“数组直接量”,但是它们不是原始表达式,因为它们所包含的成员或者元素都是子表达式。

  • 数组初始化表达式是通过一对方括号和其内的逗号隔开的列表构成的,初始化的结果是创建一个新的数组,数组的元素是逗号分隔的表达式的值;数组初始化表达式中的元素初始化表达式也可以是数组初始化表达式,即表达式可以嵌套,如二维数组。
 var arr = [1+2,3+5];
 var arr = [[1,2,3],[2,3,4],[5,7,8]];
 ```

- 对象初始化表达式中使用花括号包括其内的子表达式构成,其每个子表达式都包含一个属性名和一个冒号作为前缀;
 ```javascript
 var obj = {x:2,y:3};
 var obj = {
     left:{1,2,3},
     right:{4,5,6}
  };
 ```

#### 函数定义表达式
>   函数定义表达式定义一个JavaScript函数,表达式的值是这个新定义的函数;使用function关键字进行一个函数的定义;

#### 属性访问表达式
>   属性访问表达式运算得到一个对象属性或一个数组元素的值,JavaScript为属性访问定义了两种语法:

- expression .identifier   一个表达式后面跟随一个句点和标识符
- expression [expression]  方括号内是另一个表达式(适用于对象、数组)
**null和undefined不包含任意属性;命名的属性不存在则整个属性访问表达式的值就是undefined**
```javascript
 var o = {x:1,y:{2,3}};
 var a = [o,4,[5,6]];

 // o.x; 方位o的x属性
 // o.y.z;访问o.y的z属性
 // a[1];访问a中索引为1的元素
 // a[2]['1'];访问a[2]中索引为1的元素

调用表达式

  JavaScript中的调用表达式是一种调用或者执行函数或方法的语法表示;以一个函数表达式开始,这个函数表达式指代了要调用的函数,函数表达式后跟随一对圆括号,括号内是一个以逗号隔开的参数列表,参数可以为空也可以为多个。

对象创建表达式

  对象创建表达式创建一个对象并调用一个函数(这个函数是构造函数)初始化新对象的属性,使用关键字new进行创建对象表达式;JavaScript首先创建一个新的空对象,通过传入指定的参数将这个新对象当做this的值来调用一个指定的函数,这个函数可以使用this来初始化这个新创建的对象的属性。

   new Object();
   new Point(2,3);
   new Object;  // 不需要传递参数给构造函数可省略括号

运算符描述

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

  • 下面内容表示运算符的优先级从高到底
  • L表示运算符的结合性从左至右,R表示运算符的结合性从右至左
  • 数字表示操作数的个数,最后一列表示运算前的结果类型和运算后的结果类型
  • 一元运算符
    one.png
  • 二元运算符
    two.png
  • 三元运算符
    three.png

算术表达式

  • “+”运算符

    • 如果其中一个操作数是对象,则对象会遵循对象到原始值的转换规则转换为原始类值:日期对象通过toString()方法执行转换,其他对象通过valueOf方法执行转换;由于多数对象不具备可用的valueOf方法,因此会通过toString()方法来执行转换
    • 在进行了对象到原始值的转换以后,如果其中一个操作数是字符串的话,另一个操作数也会转换为字符串,然后进行字符串的拼接;
    • 否则两个操作数都将转换为数字或者NaN,然后进行加法操作;

    "1" + 2; 输出12,数字会转换为字符串,并进行字符串拼接;
    1 + {}; 输出1[object Object],对象转换为字符串后进行字符串拼接;
    true + true; 输出2,布尔值准换为数字以后做加法;
    2 + null; 输出2,null转换为数字后做加法;
    2 + undefined; 输出NaN,undefined转换为NaN之后做加法;
    1 + 2 + 'hello'; 输出 3hello,1和2先进行加法运算,之后再转换为字符串进行字符串拼接

  • 一元算术运算符
      一元算术运算符作用于一个单独的操作数,并产生一个新值;一元运算操作符具有很高的优先级,并且是右结合的;

    • 一元加法
      一元加法运算符把操作数转换为数组或者NaN,并返回这个转换后的数字,若操作数本身是数字,则直接返回这个数字;
    • 一元减法
      当“-”用作一元运算符时,它会根据需要把操作数转换为数字,然后改变运算结果的符号;
    • 递增++
      递加“+”运算符的操作数是一个左值,它把操作数转换为数字,然后加1,并将计算后的值重新赋值给变量、数组元素或者对象属性;
      • var i=1; j=++i; i和j都是2,++i表示先操作后增加
      • var i=1; j=i++; i是2,j是1,i++表示先增加后操作
        如果x是字符串“1”,++x的结果是2,x+1的结果是字符串“11”
    • 递减--
      递减“-”运算符的操作数是一个左值,它把操作数转换为数字,然后减1,并将计算后的值重新赋值给操作数;
      • var i=2; j=i--; i是1,j=2;先操作后递减
      • var i=2; j=--i; i和j都是1,先递减后操作
  • 位运算符作用于数值类型的操作数并返回数字;主要包括:

    • 按位与运算 &
    • 按位或运算 |
    • 按位异或运算 ^
    • 按位非运算 ~
    • 左移 <<
    • 带符号右移 >>
    • 无符号右移 >>

关系表达式

  测试两个值之间的关系,根据关系是否存在返回true或者false,关系表达式总是返回一个布尔值;

  • 相等和不相等
    “==”和“===”运算符允许任意类型的操作数,如果操作数相等则返回true,否则返回false;两个不同的对象具有相同的属性、相同的属性名和值,但是它们依然不相等
    - 严格相等运算符“===”:
    1. 如果两个值类型不相同,则它们不相等;
    2. 如果两个值都是null或者undefined,则它们不相等;
    3. 如果两个值都是布尔值true或者都是false,则它们相等;
    4. NaN与任何值不相等,包括它自己;通过x!=x来判断,只有在x为NaN的时候这个表达式才是true;
    5. 如果两个值为数字且数值相等,则它们相等;0与-0相等;
    6. 如果两个值为字符串,且所含的对应位上的16位参数完全相等,则它们相等;
    7. 如果两个引用值指向同一个对象、数组、或者函数,则它们相等;
    - 不严格相等运算符“==”
    1. 如果一个值是null,另一个是undefined,则它们相等;
    2. 如果一个值是数字,另一个是字符串,先将字符串转换为数字,然后使用转换后的值比较;
    3. 如果一个值是true,则将其转换为1进行比较(false转换为0)
    4. 如果一个值是对象,另一个值是数字或者字符串,则通过valueOf方法(优先)或者toString方法转换为原始值在进行比较;
    5. 其他不同类型的比较均不相等;

  • 比较运算符
    比较运算符主要有:小于、大于、小于等于、大于等于;比较操作符的操作数可能是任意类型,但是只有数字和字符串才能执行真正的比较操作,因为对于不是数字或者字符串的操作数需要进行类型转换;

    • 如果操作数是对象,利用valueOf或者toString方法转换为原始值进行比较操作;
    • 在对象转为原始值之后,如果两个操作数是字符串,那么按照字母表的顺序进行比较;
    • 在对象转换为原始值之后,如果至少有一个操作数不是字符串,那么两个操作数都转换为数字进行比较;
    • 如果有一个操作数转换后为NaN,那么比较操作符总是返回false;
  • 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
         1  in data;   返回true       二者都是根据索引,加引号与不加引号效果一样,数字也会转换为字符串
         3  in data;   返回false      数组中没有索引值为3的元素;
    
  • instanceof运算符
    instanceof希望左操作数是一个对象,右操作数标识对象的类,如果左侧的对象是右侧类的实例,则表达式返回true,否则返回false;如果instanceof的左操作数不是对象的话,instanceof返回false,如果右操作数不是函数,则抛出一个类型错误异常;
    instanceof.png
    **instanceof工作原理:**为了计算表达式o instanceof f,JavaScript首先计算f.prototype,然后再原型链中查找o,如果找不到,那么o是f(f的父类)的一个实例,表达式返回true,如果f。prototype不在o的原型链中,则o不是f的实例,instanceof返回false;

逻辑表达式

  • 逻辑与操作(&&):两个操作数中有一个是false则返回false,两个都是true则返回true;当第一个操作数是false,则不对第二个操作数进行判断,直接返回false;
  • 逻辑或操作(||):两个操作数中有一个是true则返回true,两个都是false,则返回false;当第一个操作数是true,则不对第二个操作数进行判断,直接返回true;
  • 逻辑非操作(!) : 一元运算符,对操作数的布尔值进行取反操作;

赋值表达式

  赋值表达式主要用于给变量或者属性赋值;赋值表达式的副作用是:右操作数的值赋值给左侧的变量或者对象属性,后续对改变这个变量和对象属性的引用将会得到这个值,带操作的赋值表达式:
copy.png

表达式计算

  JavaScript中通过eval()函数来讲JavaScript源代码转换为字符串并产生一个值;

  • eval()
    eval()只有一个参数,它使用了调用它的变量作用域环境,它只能在函数中起作用;
    • 如果传入的参数不是字符串,则它直接但会这个参数;
    • 如果参数是字符串,它会把字符串当成JavaScript代码进行编译,编译失败则跑出语法错误异常,编译成功则执行这段代码,并返回字符串中的最后一个表达式或语句的值;
    • 如果最后一个表达式或者语句没有值,则最终返回undefined;
    • 如果字符串抛出一个异常,则这个异常把该调用传递给eval();
  • 全局eval()
    当直接使用非限定的“eval”名称来调用eval()函数时,通过成为“直接eval()”,直接调用eval()时,它总是在调用它的上下文作用域内执行,其他的间接调用则使用全局对象作为其上下文作用域,并且无法读、写、定义局部变量和函数;
  • 严格eval()
    在严格模式下,eval执行的代码可以查询或更改局部变量,但不能在局部作用域中定义新的变量或函数;另外严格模式中将“eval”列为一个关键字,不能用别名覆盖eval()函数;
0
博主关闭了当前页面的评论