JS中的运算符

作者: HungerLyndon | 来源:发表于2017-01-02 22:42 被阅读334次
    本文章版权归饥人谷_Lyndon和饥人谷所有,转载请注明出处。

    运算符是数据处理的基础,能够从现有数据中获得新的数据。JS中的运算符种类可以分为如下六类:

    1. 算术运算符
    2. 赋值运算符
    3. 比较运算符
    4. 布尔运算符
    5. 位运算符
    6. 其他运算符(void, ,

    与这些运算符紧密联系的是运算符的优先级,优先级问题是笔试与面试时经常考察的问题。

    算术运算符

    算术运算符中最常见的是加法运算符,但是加法运算符针对不同类型的变量,组合效果有很多种。简而言之,JS中的加法运算符可以实现数字的相加,也可以实现字符串的拼接。

    // ————数字相加————
    console.log(1 + 1);  // 2
    console.log(true + true);  // 2
    console.log(1 + true);  // 2
    console.log(false - 1);  // -1
    // ————字符串拼接————
    console.log('1'+'1');  // '11'
    console.log('1.1' + ' ' + '1.1');  // '1.1 1.1'
    

    加法的计算方法一般如下:

    如果运算元素是对象,那么会先转化为原始类型的值(即valueOf方法),如果其结果还不是原始类型的值,再调用toString方法

    var obj = {name: 'Lyndon', age: 22};
    console.log('1' + obj);  // '1[object Object]'
    
    var obj = {
        name: 'Lyndon',
        toString: function toString(){
            return 'Lyndon';
        },
        valueOf: function valueOf(){
            return 'morning'
        }
    };
    console.log(1 + obj);  // '1morning'
    
    var obj = {
        name: 'Lyndon',
        toString: function toString(){
            return 'Lyndon';
        }
    };
    console.log(1 + obj);  // '1Lyndon'
    

    如果对象是Date实例,那么先执行的是toString方法

    var day = new Date();
    console.log(day);  // 'Sat Dec 31 2016 19:19:11 GMT+0800 (中国标准时间)'
    console.log('good' + day);  // 'goodSat Dec 31 2016 19:19:11 GMT+0800 (中国标准时间)'
    

    两个运算元素都是原始类型值,但只要有一个运算元素是字符串,那么另一个运算元素也会转换为字符串,执行字符串拼接

    var a = 10, b = 'days';
    console.log(a + b);  // '10days'
    

    只有加号和一个运算元素,如果唯一的运算元素是字符串,那么会转换为数字,所以结果有可能是NaN

    console.log(+ '78');  // 78
    console.log(+ 'good');  // 'NaN'
    

    否则,两个运算元素皆转换为数值,执行算术加法运算

    由于加法运算极大地依赖于参数的类型,因此使用时应该首先明确到底要执行哪种运算,如果不确定最好加上小括号。如下面的例子就说明字符串在算式中的位置不同,结果也会不同。

    console.log('3' + 4 + 5);  // '345'
    console.log(3 + 4 + '5');  // '75'
    console.log(3 + '4' + 5);  // '345'
    

    特别需要注意的还有两点

    1. 加法运算符对于其他类型的值会自动转化为字符串,然后进行字符串的拼接。
    var a = [1, 2];
    var b = 3;
    console.log(a instanceof(Object));  // true
    console.log(a + b);  // '1,23'
    2 + [2];  // '22',等同于String(2) + String([2])
    
    1. 如果只有一个运算元素,必须将其放在右边
    2 + ;  // Uncaught SyntaxError: Unexpected token ;
    console.log(2 + );  // Uncaught SyntaxError: Unexpected token )
    +-6;  // -6,等同于+(-6)
     + 3 + 4;  // 7,等同于+(3+4)
    

    相较加法运算符而言,剩下的算术运算符都相对简单些,其原则就是:将所有的运算元素全部转换为数值,再执行相应的算术运算。

    '1'/2;  // 0.5
    'a'/2;  // NaN
    '1a'/2;  // NaN,转换为数字的方式是Number('1a'),而不是parseInt('1a')
    

    需要注意几个特殊的情况。

    求余/求模运算,判断奇偶数时常用到%运算符,但是对于负数而言需要使用到绝对值,否则不能给出正确答案

    function isOdd(n){
        return n % 2 === 1;
    }
    console.log(isOdd(-3));  // false
    console.log(isOdd(-4));  // false
    

    但是-3明显是一个奇数,应该返回true,所以需要进行如下修改:

    function isOdd(n){
        return Math.abs(n) % 2 === 1;
    }
    console.log(isOdd(-3));  // true
    console.log(isOdd(-4));  // false
    

    自增与自减的运算符前后问题。如果将++--放在变量之后,会先返回变量原始值,再进行自增或自减操作;如果将符号放在变量之前,会先进行自增或自减操作,再返回操作后的结果

    var a = 1, b = 1;
    a1 = a++;
    b1 = ++b;
    console.log(a1, b1, a, b);  // 1 2 2 2
    

    赋值运算符

    常用的赋值运算符有:=, +=, -=。关于赋值运算符的主要考虑问题,应该是运算符的优先级与左结合、右结合问题。

    比较运算符

    比较运算符进行运算后返回的结果始终是布尔值。

    ==是相等,具体而言是:比较两个值是否相等;===是严格相等,具体而言是:两个值是否是同一个值,需要保证变量类型也是相同的;!=是不相等,!==是严格不相等

    2 == '2';  // true
    2 === '2';  // false
    1 == true;  // true
    1 === true;  // false
    NaN === NaN;  // false,NaN与任何值都不想等,包括其自身
    15 === 0xf;  // true,同类型的基础类型值,虽然进制不一样,但是代表的值相等,因此也严格相等
    

    除了相等与严格相等运算符之外,如果两个运算元素都是字符串,那么将按照字典顺序进行ASCII值的比较;否则两个运算元素都会转换为数值进行比较

    5 > '4';  // true
    false < true;  // true
    'cathy' > 'Cathy';  // true,因为小写字母c的ASCII值为99,而大写字母C的ASCII值为67
    

    如果运算元素是对象,那么会先调用valueOf方法,如果返回的还是对象,接着调用toString方法

    var x = [];
    x.valueOf = function(){
        return 12;
    }
    console.log(x < '11');  // false
    console.log(x > '11');  // true
    var y = [2];
    x > '12';  // false,等同于[2].valueOf().toString()='2'>'11'
    var x = {a: 2, b: 3};
    var y = {a: 3, b: 4};
    console.log(x > y);  // false
    console.log(x < y);  // false
    console.log(x >= y);  // true,等同于x.valueOf().toString()>=y.valueOf().toString(),结果是'[object Object]'>='[object Object]'
    

    复杂类型的比较原则:两个复杂对象是否指向同一个对象

    [] === [];  // false
    var a1 = [];
    var a2 = a1;
    a1 === a2;  // true
    

    相等运算符:对于基础类型的值会转换成数值类型再进行比较;如果对象与基础类型值比较,会先将对象转化为原始类型的值,再进行比较

    [1] == 1;  // true
    [1] == '1';  // true,等同于Number(String([1]))==Number('1')
    [1] == true;  // true
    

    相等运算符之后隐藏的类型转换,往往会使人困惑,因此最好广泛使用严格相等运算符,少使用相等运算符

    布尔运算符

    布尔运算符用于将表达式转换为布尔值。

    取反运算符会自动将非布尔值转换为布尔值,以下是能够转换为false的5个值,对于其取反就能转换为true。两次取反是将一个值转换为对应布尔类型的简便方法

    !undefined;  // true
    !null;  // true
    !'';  // true
    !0;  // true
    !NaN;  // true
    !!NaN;  // false
    

    且运算符(&&):如果第一个运算元素的布尔值为true,那么会返回第二个运算元素的值;如果第一个运算元素的布尔值为false,那么直接返回第一个运算元素的值。这种跳过第二个元素的机制常被称为"短路"

    var a = 2;
    console.log('hello') && (a - 2);  // undefined,等同于console.log('hello')并不返回任何值,所以是undefined,而!!undefined=false,所以直接返回第一个运算元素的值:undefined
    

    或运算符(||):如果第一个运算元素的布尔值为true,那么会返回第一个运算元素的值;如果第一个运算元素的布尔值为false,则返回第二个运算元素的值

    var a = 2;
    console.log('hello') || (a - 2);  // 0,等同于第一个运算元素的布尔值为false,那么返回第二个运算元素的值0
    

    三元运算符(?:):与if...else...条件判断语句有着相同的表达效果,但是三元条件运算符有返回值,if...else...却没有

    console.log(0 ? true : false);  // false
    console.log(1 ? true : false);  // true
    

    位运算符

    位运算符中比较常用的是:或运算与与运算。位运算符直接处理的是每一个比特位,是非常底层的运算,常常用在加密算法中,好处是速度比较快,缺点是不直观,增加了代码的复杂度,提升了维护成本。

    或运算(or):符号为|,两个二进制位都为0,则结果为0,否则为1
    与运算(and):符号为&,两个二进制位都为1,结果为1,否则为0

    console.log(1 | 3);  // 3,等同于:1表示为二进制是001,3表示为二进制是011,因此最后结果为011,转化为十进制即为3
    console.log(1 & 3);  // 1,等同于:1表示为二进制是001,3表示为二进制是011,因此最后结果为001,转化为十进制即为1
    

    位运算符仅仅对整数有效,遇到小数时,会将小数点后的部分抹去,只保留整数部分。

    console.log(1 | 3.965);  // 3
    

    在JS内部,数值都是以64位浮点数的形式进行存储,但是进行位运算的时候,是以32位进行运算的。也即2在JS内部是00000000000000000000000000000010,因此进行否运算时,原来的0全部变为1,而1变为0。因此-2进行否运算后第一位是1,所以这个数是一个负数。但是JS采取补码的方式来表示负数,因此需要将这个数减去1,再取一次反,所以最后的结果是00000000000000000000000000000011,加上负号后就是-3

    console.log(~2);  // -3
    

    void运算符

    void运算符的作用是:执行表达式,然后只返回undefined,由于void的优先级比较高,因此使用时最好加上小括号

    console.log(void 1 + 2);  // NaN,等同于:undefined + 2
    console.log(void(1 + 2));  // undefined
    

    逗号运算符

    逗号运算符的作用是对两个表达式求值,然后返回后一个表达式的值。

    1, 10;  // 10
    
    var x = 1;
    var y = 10;
    var z = (x, y);
    z;  // 10
    

    相关文章

      网友评论

        本文标题:JS中的运算符

        本文链接:https://www.haomeiwen.com/subject/jlqbvttx.html