【读书笔记】JavaScript高级编程(三)

书中第3章 基本概念摘要(二) 编程

3.5 操做符

3.5.1 一元操做符

1.递增和递减操做符
var s1 = "2";
var s2 = "z";
var b = false;
var f = 1.1;
var o = {
    valueOf: function() {
        return -1;
    }
};

s1++; // 值变成数值3
s2++; // 值变成NaN
b++; // 值变成数值1
f--; // 值变成0.10000000000000009(因为浮点舍入错误所致)
o--; // 值变成数值-2
4个操做符(a++,++a,a--,--a)对任何值都适用,在应用于不一样的值时,递减和递增操做符遵循下列规则。
    应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减1的操做。字符串变量变
成数值变量。
    在应用于一个不包含有效数字字符的字符串时,将变量的值设置为 NaN 。字符串变量变成数值变量。
    在应用于布尔值false时,先将其转换为0再执行加减1的操做。布尔值变量变成数值变量。
    在应用于布尔值true时,先将其转换为1再执行加减1的操做。布尔值变量变成数值变量。
    在应用于浮点数值时,执行加减1的操做。
    在应用于对象时,先调用对象的valueOf()方法以取得一个可供操做的值。而后对该值应用前述规则。
若是结果是NaN,则在调用toString()方法后再应用前述规则。对象变量变成数值变量。

2.一元加和减操做符
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; // 值变成数值1
s2 = +s2; // 值变成数值1.1
s3 = +s3; // 值变成NaN
b = +b; // 值变成数值0
f = +f; // 值未变,仍然是1.1
o = +o; // 值变成数值-1

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; // 值变成数值-1
s2 = -s2; // 值变成数值-1.1
s3 = -s3; // 值变成NaN
b = -b; // 值变成数值0
f = -f; // 值变成-1.1
o = -o; // 值变成数值1

3.5.3 布尔操做符

1.逻辑非
alert(!false); // true
alert(!"blue"); // false
alert(!0); // true
alert(!NaN); // true
alert(!"");  // true
alert(!" "); // false
alert(!12345); // false
逻辑非操做符会将它的操做数转换为一个布尔值,而后在对其求反。
    若是操做数是一个对象,返回false;
    若是操做数是一个空字符串,返回true;
    若是操做数是一个非空字符串,返回false;
    若是操做数是数值0,返回true;
    若是操做数是任意非0数值(包括Infinity),返回false;
    若是操做数是操做数是null,返回true;
    若是操做数是NaN,返回true;
    若是操做数是undefined,返回true。

2.逻辑与
逻辑与操做能够应用于任何类型的操做数,而不只仅是布尔值。在有一个操做数不是布尔值的状况下,逻辑
与操做就不必定返回布尔值;此时,它遵循下列规则:
    若是第一个操做数是对象,则返回第二个操做数;
    若是第二个操做数是对象,则只有在第一个操做数的求值结果为true的状况下才会返回该对象;
    若是两个操做数都是对象,则返回第二个操做数;
    若是有一个操做数null,则返回null;
    若是有一个操做数是NaN,则返回NaN;
    若是有一个操做数是undefined,则返回undefined。

短路操做:
    var found = true;
    var result = (found && someUndefinedVariable); // 这里会发生错误
    alert(result);  //这一行不会执行
上面代码中,由于found为true,因此逻辑与操做符会继续对变量someUndefinedVariable求值。但
someUndefinedVariable还没有定义,所以就会致使错误。这说明不能在逻辑与操做中使用未定义的值。若是将found的值设为false,发生“短路”不会对someUndefinedVariable继续求值,就不会发生错误:
    var found = false;
    var result = (found && someUndefinedVariable); // 不会发生错误
    alert(result);  //会执行alert

3.逻辑或
与逻辑与操做类似,若是有一个操做数不是布尔值,逻辑或也不必定返回布尔值;此时,它遵循下列规则:
    若是第一个操做数是对象,则返回第一个操做数;
    若是第一个操做数的求值结果为false,则返回第二个操做数;
    若是两个操做数都是对象,则返回第一个操做数;
    若是有一个操做数null,则返回null;
    若是有一个操做数是NaN,则返回NaN;
    若是有一个操做数是undefined,则返回undefined。

短路操做:
    var found = true;
    var result = (found || someUndefinedVariable); // 不会发生错误
    alert(result);  // 会执行alert
这个例子跟前面例子同样,变量someUndefinedVariable也没有定义。可是,因为变量found的值是true,而
变量someUndefinedVariable永远不会被求值,所以不会报错。
    var found = false;
    var result = (found || someUndefinedVariable); // 这里会发生错误
    alert(result);  // 这一行不会执行
咱们能够利用逻辑或的这一行为来避免为变量赋null或undefined值。例如:
    var myObject = preferredObject || backupObject;
在这个例子中,变量myObject将被赋予等号后面两个值中的一个。变量preferredObject中包含优先赋给变
量myObject的值,变量backupObject负责在preferredObject中不包含有效值的状况下提供后备值。

3.5.4 乘性操做符
ECMAScript定义了3个乘性操做符:乘法、除法和求模。这些操做符与Java、C或者Perl中的相应操做符相似
,只不过在操做数为非数值的状况下会执行自动的类型转换。若是参与乘法计算的某个操做数不是数值,后台会先使用Number()转型函数将其转换为数值。也就是说,空字符串将被看成0,布尔值true将被看成1。

1.乘法
在处理特殊值的状况下,乘法操做符遵循下列特殊的规则:
    若是操做数都是数值,执行常规乘法计算。若是乘积超过了ECMAScript数值的表示范围,则返回
Infinity或-Infinity;
    若是有一个操做数是NaN,则结果是NaN;
    若是是Infinity与0相乘,则结果是NaN;
    若是是Infinity与非0数值相乘,则结果是Infinity或-Infinity,取决于有符号操做数的符号;
    若是是Infinity与Infinity相乘,则结果是Infinity;
    若是有一个操做数不是数值,则在后台调用Number()将其转换为数值,而后再应用上面的规则。

2.除法
与乘法相似,对特殊值的处理规则以下:
    若是操做数都是数值,执行常规除法计算。若是乘积超过了ECMAScript数值的表示范围,则返回
Infinity或-Infinity;
    若是有一个操做数是NaN,则结果是NaN;
    若是是Infinity被Infinity除,则结果是NaN;
    若是是Infinity被任意数值除,则结果是Infinity;
    若是是零被零除,则结果是NaN;
    若是是非零的有限数被零除,则结果是Infinity或-Infinity,取决于有符号操做数的符号;
    若是是Infinity被任何非零数值除,则结果是Infinity或-Infinity,取决于有符号操做数的符号;
    若是有一个操做数不是数值,则在后台调用Number()将其转换为数值,而后再应用上面的规则。

3.求模
var result = 26 % 5; //等于1
与另外两个乘法操做符相似,求模操做符会遵循下列特殊规则来处理特殊的值:
    若是操做数都是数值,执行常规除法计算。返回除得的余数;
    若是被除数是无穷大值而除数是有限大的数值,则结果是NaN;
    若是被除数是有限大的数值而除数是零,则结果是NaN;
    若是是Infinity被Infinity除,则结果是NaN;
    若是被除数是有限大的数值而除数是无穷大的数值,则结果是被除数;
    若是被除数是零,则结果是零;
    若是有一个操做数不是数值,则在后台调用Number()将其转换为数值,而后再应用上面的规则。

3.5.5 加性操做符

1.加法
若是两个操做数都是数值,执行常规的加法计算,而后根据下列规则返回结果:
    若是有一个操做数是NaN,则结果是NaN;
    若是是Infinity加Infinity,则结果是Infinity;
    若是是-Infinity加-Infinity,则结果是-Infinity;
    若是是Infinity加-Infinity,则结果是NaN;
    若是是+0加+0,则结果是+0;
    若是是-0加-0,则结果是-0;
    若是是+0加-0,则结果是+0;
不过,若是有一个操做数是字符串,那么就要应用以下规则:
    若是两个操做数都是字符串,则将第二个操做数与第一个操做数拼接起来;
    若是只有一个操做数是字符串,则将另外一个操做数转换为字符串,而后再将两个字符串拼接起来。
若是有一个操做数是对象、数值或布尔值,则调用它们的toString()方法取得相应的字符串值,而后再应用
前面关于字符串的规则。对于undefined和null,则分别调用String()函数并取得字符串"undefined"和"null"。
    var result1 = 5 + 5;  //两个数值相加
    alert(result1);  //10
    var result2 = 5 + "5";  //一个数值和一个字符串相加
    alert(result2);  //"55"
忽视加法操做中的数据类型是ECMAScript编程中最多见的一个错误,以下
    var num1 = 5;
    var num2 = 10;
    var message = "The sum of 5 and 10 is " + num1 + num2;
    alert(message);  // "The sum of 5 and 10 is 510"
若是想先对数值执行计算,而后再拼接,应该像下面这样使用圆括号:
    var num1 = 5;
    var num2 = 10;
    var message = "The sum of 5 and 10 is " + (num1 + num2);
    alert(message);  // "The sum of 5 and 10 is 15"


2.减法
与加法相似,减法操做符在处理各类数据类型转换时,一样须要遵循一些特殊规则:
    若是两个操做数都是数值,执行常规的减法运算并返回结果:
    若是有一个操做数是NaN,则结果是NaN;
    若是是Infinity减Infinity,则结果是NaN;
    若是是-Infinity减-Infinity,则结果是NaN
    若是是Infinity减-Infinity,则结果是Infinity;
    若是是-Infinity减Infinity,则结果是-Infinity;
    若是是+0加+0,则结果是+0;
    若是是-0加-0,则结果是+0;
    若是是+0加-0,则结果是-0; 
    若是有一个操做数是字符串、布尔值、null或undefined,则先在后台调用Number()函数将其转换为数
值,而后再根据前面的规则执行减法计算。若是转换的结果是NaN,则减法的结果就是NaN;
    若是有一个操做数是对象,则调用对象的valueOf()方法以取得表示该对象的数值。若是获得的值是NaN,则减法的结果就是NaN。若是对象没有valueOf()方法,则调用其toString()方法并将获得的字符串转换为数值。   
var result1 = 5 - true; // 4,由于true被转换成了1
var result2 = NaN - 1; //NaN
var result3 = 5 - 3; // 2
var result2 = 5 - ""; //5, 由于""被转换成了0
var result2 = 5 - "2"; //3,由于"2"被转换成了2
var result2 = 5 - null; //5,由于null被转换成了0

3.5.6 关系操做符
小于(<)、大于(>)、小于等于(<=)和大于等于(>=)这几个关系操做符用于对两个值进行比较,比较的规则与
咱们在数学课上所学的同样,这几个操做都返回一个布尔值。当关系操做符的操做数使用了非数值时,也要进行数据转换或完成某些奇怪的操做。
    若是两个操做数都是数值,则执行数值比较;
    若是两个操做数都是字符串,则比较两个字符串对应的字符编码值;
    若是一个操做数是数值,则将另外一个操做数转换为一个数值,而后执行数值比较;
    若是一个操做数是对象,则调用这个对象的valueOf()方法,用获得的结果按照前面的规则执行比较。
若是对象没有valueOf()方法,则调用toString()方法,并用获得的结果根据前面的规则执行比较;
    若是一个操做数是布尔值,则先将其转换为数值,而后再执行比较。

在比较字符串时,实际比较的是两个字符串中对应位置的每一个字符的字符编码值。通过一番比较以后,再返
回一个布尔值。因为大写字母的字符编码所有小于小写字母的字符编码,所以咱们就会看到以下所示的奇怪现象:
    var result = "Brick" < "alphabet";  //true
在这个例子中,字母B的字符编码为66,而字母a的字符编码是97.若是想按照字母表顺序比较字符串,就必
须把两个操做数转换为相同的大小写形式(所有大写或所有小写),而后再执行比较:
    var result = "Brick".toLowerCase() < "alphabet".toLowerCase();  //false
另外一种奇怪的现象发生在比较两个数字字符串的状况下,好比:
    var result = "23" < "3";  //true
这是由于两个操做符数都是字符串,而字符串比较的是字符编码("2"的字符编码是50,而"3"的字符编码是
51)。不过,若是将一个操做数改成数值,比较的结果就正常了:
    var result = "23" < 2;  //false
若是字符串为一个不能被转换成合理的数值的字符呢?
    var result = "a" < "3";  //false,由于"a"被转换成了NaN。
任何操做数与NaN进行关系比较,结果都是false。
    var result1 = NaN < 3;  //false
    var result2 = NaN >= 3;  //false

函数

3.5.7 相等操做符 编码

1.相等和不相等
相等操做符 == ,不相等操做符 != 。这两个操做符都会先转换操做数(一般称为强制转型),而后再比较它们的相等性。
spa

在转换不一样数据类型时,相等和不相等操做符遵循下列基本规则:
    若是有一个操做数是布尔值,则在比较相等性以前先将其转换为数值——false转换为0,而true转换为1;
    若是一个操做数是字符串,另外一个操做数是数值,在比较相等性以前先将字符串转换为数值;
    若是一个操做数是对象,另外一个操做数不是,则调用对象的valueOf()方法,用获得的原始值按照前面的规则进行比较;
这两个操做符在进行比较时则要遵循下列规则。
    null和undefined是相等的。
    要比较相等性以前,不能讲null和undefined转换成其余任何值。
    若是有一个操做数是NaN,则相等操做符返回false,而不相等操做符返回true。重要提示:即便两个操做数都是NaN,相等操做符也返回false;所以按照规则,NaN不等于NaN。
    若是两个操做数都是对象,则比较它们是否是同一个对象。若是两个操做数都指向同一个对象,则相等操做符返回true;不然,返回false。
下表列出了一些特殊状况及比较结果:

设计

2.全等和不全等 对象

除了在比较以前不转换操做数以外,全等和不全等操做符与相等和不相等操做符没有什么区别。全等操做符 === 
    var result1 = ("55" == 55);  //true,由于转换后相等
    var result2 = ("55" === 55);  //false,由于不一样的数据类型不相等
不全等操做符 !==
    var result1 = ("55" != 55);  //false,由于转换后相等
    var result2 = ("55" !== 55);  //true,由于不一样的数据类型不相等
ip

3.5.8 条件操做符 字符串

条件操做符遵循与Java中的条件操做符相同的语法形式。 数学

3.5.10 逗号操做符 it

使用逗号操做符能够在一条语句中执行多个操做,以下:
    var num1=1, num2=2, num3=3;
 逗号操做符多用于声明多个变量;但除此以外,逗号操做符还能够用于赋值。在用于赋值时,逗号操做符总会返回表达式中的最后一项,以下:
    var num = (5, 1, 4, 8, 0); //num值为0

以上全部内容均摘自图书《JavaScript 高级程序设计(第2版)》[美] Nicholas C.Zakas 著 李松峰 曹力 译

相关文章
相关标签/搜索