第三章:基本概念(操作符)

操作符

  • 定义:操作符能用于操作数据值,包括算术运算符、位操作符、关系操作符和相等操作符。操作符能适用于很多值,例如字符串、数字值、布尔值,甚至对象。在应用于对象时,相应的操作符通常会调用对象的valueOf()和(或)toString()方法,以便取得可以操作的值。

递增和递减操作符

  • (+ +,- -)应用于数值时,和java中没有区别。要注意的是操作符的位置分为前置和后置。前置递增使变量的值在语句被求以前改变(可以理解成返回递增后的值)。举个例子:
    var age = 29;
    //以下几个都是单独存在:
    var anotherage = ++age + 1;//31 age的值会在(++age) + 1之前改变(想象++age已经计算完毕),
所以最终得到了31。这种在科学领域称为副效应。
    var anotherage = age++ + 1;//输出30 刚好与前置递增相反。
    var anotherage = age++ + age + 1;//输出60 第一个age++返回了29,第二个age已经是30,再加1得到60
    var anotherage = ++age + age + 1;//输出61
    var anotherage = age + ++age + 1;//输出60 上面的现象与java中一模一样
  • 当递增递减操作符应用于字符串、布尔值或者对象时。可以理解成在上一篇文章中提到过的,先将变量通过Number()函数转换为数值,再进行计算。这里就简单举3个object的例子:
    var o1 = {
        valueOf : function () {
            return "1";
        },
        toString : function () {
            return "2";
        }
    }
    var o2 = {
        toString : function () {
            return "2";
        }
    }
    var o3 = {
        valueOf : function () {
            return "1xx";
        },
        toString : function () {
            return "2";
        }
    }
    var o4 = {
        valueOf : function () {
            return "1xx";
        },
        toString : function () {
            return "2xx";
        }
    }
    alert(++o1);//2
    alert(++o2);//3
    alert(++o3);//NaN
    alert(++o4);//NaN
  • o1和o2的结果是在预想中的,在执行自增运算时,先是求Number(o1),由于o1是对象,故先调用valueOf()方法再得到有效值”1”后,再执行Number(“1”)返回数值1自增得到2。o2的结果是因为没有重写valueOf方法,或者说valueOf方法的返回值执行Number后是NaN,所以再调用toString()最终得到3。o4的执行结果我也是可以理解的,两个都是NaN故最终结果是NaN。但是o3的结果就令我非常困惑了。书上的原话是执行valueOf得到NaN会再去调用toString。(后来我看到减法操作,发现如果有valueOf方法则使用valueOf方法的返回结果)那么按照我的理解o3最终是会得到3的。但是实验告诉我结果是NaN。我用的是Chrome浏览器,是不是书上说的已经过时了,还是我理解的不对。希望有人看到这个能评论讨论一下这个内容。这里再顺便说下如果在alert(++o4)之前alert(o4)是会输出2xx的,因为会自动调用在o4自增前o4还是个object,会自动调用toString()方法。而自增后o4已经变成一个Number类型了。

一元加和减操作符

  • 注意这里说的是一元操作符,一元加操作符对于Number类型不会有任何变化(如果是减操作符就是取相反数)。如果是其他类型则执行Number()方法,以下是例子:
    var s1 = "01";
    var s2 = "1.1";
    var s3 = "z";
    var b = false;
    var f = 1.1;
    var o = { 
        valueOf: function() {
            return -1;
        }
    };
    //以下如果做一元减操作结果会取相反数。
    s1 = +s1;   //value becomes numeric 1
    s2 = +s2;   //value becomes numeric 1.1
    s3 = +s3;   //value becomes NaN
    b = +b;     //value becomes numeric 0
    f = +f;     //no change, still 1.1
    o = +o;     //value becomes numeric -1

位操作符

  • 当对数值应用位操作符时,后台会发生如下转换过程:64位的数值被转换成32位数值,然后执行位操作,最后再将32位的结果转换为64位数值。这样表面看起来就好像是在操作32位数值。但这样会导致一个严重的副效应,再在特殊的NaN和Infinity值应用位操作时,这2个值会被当成0来对待。

按位非 (‘~’)

    var num1 = 25;             //binary 00000000000000000000000000011001
    var num2 = ~num1;          //binary 11111111111111111111111111100110
    alert(num2);               //-26
  • 按位非操作其实就相当于取反减一。但其速度会优于取反减一操作。

按位与 (‘&’)

  • 按位与有2个操作数。与运算是在两个值都为1的时候才为1,这里省略例子。

按位或 (‘|’)

  • 按位或有2个操作数。或运算是在两个值都为0的时候才为0,这里省略例子。

按位异或 (‘^’)

  • 按位异或有2个操作数。异或运算是在两个值都不相同的时候才为1,这里省略例子。

左移(‘<<’)

  • 左移运算就是把32位下的后31位(除去符号位)进行左移,右边多出来的空位填0。例子如下:
    var a = 2;
    alert(a << 2);//得到8相当于乘以2^n

右移(有符号右移’>>’,无符号右移’>>>’)

  • 通常来说右移相当于除以2操作。有符号右移与左移类似。无符号右移对于正数来说和有符号右移没有区别。但是对负数进行无符号右移时,由于负数存的是补码,此时会将其当做正数处理,所以一般会造成得到的结果非常大。

布尔操作符

  • 布尔操作符有3个(!, &&, ||),和java中用法相同。以下分别对三个操作符进行说明:
  • 逻辑非(!):只有一个操作数,可以应用任何值,无论这个值是什么都会返回布尔值(注意和下面两个操作符的区别)。其实它的功能总结起来就是先用Boolean()函数对这个值取结果,然后再进行逻辑非运算。所以连续两个逻辑非’!!’的效果和Boolean()是一模一样的。
  • 逻辑与(&&):有两个操作数。在有一个操作数不是布尔值的时候,其返回结果就不一定是布尔值。
    alert("12" && true);//true
    alert("" && "34");//""
    alert("12" && "34");//"34"
    alert(true && "34");//"34"
    alert(null && "34");//"null"
    alert(NaN && null);//NaN
    alert(undefined && null);//undefined
    alert(false && null);//false
  • 因为逻辑与操作符是短路操作符(逻辑或操作符也是),所以上述的结果其实很好理解了。首先会对第一个操作数进行Boolean()操作。如果是false,那么对不起直接返回第一个操作数的原型(原来是什么就返回什么),第二个到底是什么就不管了(即使第二个操作数未定义)。如果第一个是true。再去对第二个操作数进行Boolean()操作,如果还是true,那就返回第二个操作数的原型。那如果第二个操作数是false。那么也会返回第二个操作数的原型。所以总结下来就是( 以下是我的个人总结,如有不对欢迎指出。):
    1. 第一个操作数使用Boolean()计算是false,则返回第一个操作数原型。
    2. 第一个操作数使用Boolean()计算是true,则返回第二个操作数原型。
  • 逻辑或(||):有两个操作数。在有一个操作数不是布尔值的时候,其返回结果就不一定是布尔值。类比上面的逻辑与操作符有总结如下:
    1. 第一个操作数使用Boolean()计算是true,则返回第一个操作数原型。
    2. 第一个操作数使用Boolean()计算是false,则返回第二个操作数原型。
    alert("12" || true);//"12"
    alert("" || "34");//"34"
    alert("12" || "34");//"12"
    alert(true || "34");//true
    alert(null || "34");//"34"
    alert(NaN || null);//null
    alert(undefined || null);//null
    alert(false || null);//null
  • 小tips:上述逻辑或的特性常用于给函数赋默认值,如下:
    function getAjaxResponse(url,method) {
        method = method || "get";
        ...
    }
    /*上述做法当调用getAjaxResponse("hello world!")时,
     *由于method未传,在函数中为undefined,
     */利用逻辑或的特性可以为method赋值"get"

乘性操作符

  • 乘性操作符包括乘除和取余。总结一句话就是如果操作数不是数值类型,利用Number()隐性转换。如果操作数中包含NaN,那么结果是NaN。如果包含Infinity:
    1. Infinity * Infinity = Infinity
    2. Infinity / Infinity = NaN
    3. Infinity % Infinity = NaN
    4. 10 / Infinity = 0
    5. 10 / 0 = Infinity
    6. 0 / 0 = NaN

加性操作符

加法

  • 普通数值操作就不说了,以下是几个特例
    console.log(+0 + +0);//"0"
    console.log(-0 + -0);//"-0" alert不会体现
    /*
     *如果操作数不是数字,当其中有一个为字符串时,
     *转成字符串进行拼接。(前一章有提到)(书上说是toString,
     *但实验结果说明valueOf优先于toString)。
     *如果两者都不是字符串,则通过Number()获取两个结果进行加法运算。
     */
    var a;
    var b = "123";
    var c = 123;
    alert(a + b);//"undefined123"
    alert(a + c);//NaN 这里认为是数值加法运算
    var a = {
        valueOf: function () {
            return 1;
        },
        toString: function () {
            return 2;
        }
    }
    var b = {
        valueOf: function () {
            return 4;
        },
        toString: function () {
            return 8;
        }
    }
    var c = "hello";
    alert(a);//输出2 前面章节提到过
    alert(a + c);//输出 "1hello" 这里会先调用valueOf
    alert(a && c);//输出 "hello" a不是空对象为true
    alert(a || c);//输出 2 这里会先调用toString
    alert(a + b);//输出5

减法操作符

  • 减法同加法没有什么区别,唯一的区别是减法没有截取字符串一说。以下是例子:当遇到操作数不是数值的时候,会隐性的调用Number()方法转成数值。
    var a = {
        valueOf: function () {
            return 1;
        },
        toString: function () {
            return 2;
        }
    }
    var b = {
        toString: function () {
            return 8;
        }
    }
    var c = "hello";
    var d = "1";
    var e = "1xx";
    alert(a - c);//输出 NaN (1-NaN) 这里会先调用valueOf
    alert(a - b);//输出-7
    alert(a - d);//输出0
    alert(a - e);//输出NaN (1-NaN)

关系比较符(>, <, >=, <=)

  1. 如果两个操作数都是数值,执行数字比较。
  2. 如果都是字符串,比较对应的字符编码值。(按高到低)
  3. 如果一个是数值,则将另外一个操作数通过Number()转换为数值进行比较。
  4. 如果一个操作数是对象,调用valueOf方法。如果没有valueOf方法则调用toString()方法。再按照前三条规则比较。
  5. 如果是布尔值则通过Number()转换成数值,再按照前三条。
    var a = "123";
    var d = "123xx";
    var b = {
        valueOf: function () {
            return 2;
        },
        toStrong: function () {
            return "2";
        }
    }
    var c = {
        toStrong: function () {
            return "2";
        }
    }
    alert(a > b);//true 先是valueOf返回数值2 再将"123"转为数值123 比较得到true
    alert(a > c);//false 先是toString返回字符串"2"  "123" < "2"
    alert(d > 1 || d <= 1);//false 先是Number()返回NaN NaN不管怎么比较都是false

相等操作符

相等和不相等(==, !=)

  1. 如果一个操作数是布尔值,先转成数值再进行比较。
  2. 如果一个是字符串,一个是数值,则将字符串转成数值比较(可能得到NaN)。
  3. 如果一个是对象,一个不是,则调用该对象的valueOf方法(如果valueOf返回的还是对象则调用toString),通过返回的值的类型再按照上面规则进行比较。
  4. null 和 undefined相等,且不能将其转换成其他值。
  5. 如果操作数中有NaN, 相等永远为false。不等永远为true。(NaN != NaN)
  6. 如果都是对象,则比较他们是不是同一个对象。如果指向同一个对象返回true。

全等和不全等(===, !==)

  • 全等比较符除了在比较前不转换类型外,其他都与相等操作符一样。(null !== undefined)

条件操作符

  • 和java中一样。例如:
    var max = (num1 > num2) ? num1 : num2;

赋值操作符

  • 此处简单略过,使用类似 += -=其实主要目的是简化赋值操作。不会带来性能的提升。有以下几个赋值操作:
    1. *=
    2. /=
    3. %=
    4. +=
    5. -=
    6. <<=
    7. >>=
    8. >>>=

逗号操作符

  • 使用逗号操作符多用于声明多个变量。除此之外,逗号操作符还可以用于赋值。用于赋值时,逗号操作符总会返回表达式中的最后一项。例子如下:
    var num1=1, num2=2, num3=3;
    var num = (1, 2, 3, 4, 5);//num最终为5
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值