Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript隐式转换 #5

Open
chenshuhong opened this issue Aug 23, 2019 · 0 comments
Open

JavaScript隐式转换 #5

chenshuhong opened this issue Aug 23, 2019 · 0 comments
Labels

Comments

@chenshuhong
Copy link
Owner

chenshuhong commented Aug 23, 2019

Boolean

数据类型 转换为true的值 转换为false的值
Boolean true false
String 任何非空字符串 ""(空字符串)
Number 任何非零数字值(包括无穷大) 0和NaN
Object 任何对象 null
Undefined - undefined

在if中会进行自动转换

Number

有 3 个函数可以把非数值转换为数值: Number()、 parseInt()和 parseFloat()。 第一个函数,
即转型函数 Number()可以用于任何数据类型,而另两个函数则专门用于把字符串转换成数值。这 3 个函数对于同样的输入会有返回不同的结果

Number()

  • 如果是 Boolean 值, true 和 false 将分别被转换为 1 和 0。

  • 如果是数字值,只是简单的传入和返回。

  • 如果是 null 值,返回 0。

  • 如果是 undefined,返回 NaN。

  • 如果是字符串,遵循下列规则:

    • 如果字符串中只包含数字(包括前面带正号或负号的情况),则将其转换为十进制数值,即"1"会变成 1, "123"会变成 123,而"011"会变成 11(注意:前导的零被忽略了);
    • 如果字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值(同样,也会忽
      略前导零);
    • 如果字符串中包含有效的十六进制格式,例如"0xf",则将其转换为相同大小的十进制整
      数值;
    • 如果字符串是空的(不包含任何字符),则将其转换为 0;
    • 如果字符串中包含除上述格式之外的字符,则将其转换为 NaN。
  • 如果是对象,则调用对象的 valueOf()方法,然后依照前面的规则转换返回的值。如果转换
    的结果是 NaN,则调用对象的 toString()方法,然后再次依照前面的规则转换返回的字符
    串值。

var num1 = Number("Hello world!"); //NaN
var num2 = Number(""); //0
var num3 = Number("000011"); //11
var num4 = Number(true); //1

一元加操作符(+)的操作与 Number()函数相同

parseInt

处理整数的时候更常用的是parseInt()函数。 它会忽略字符串前面的空格,直至找到第一个非空格字符。如果第一个字符不是数字字符或者负号, parseInt()就会返回 NaN;也就是说,用 parseInt()转换空字符串会返回 NaN(Number()对空字符返回 0)。如果第一个字符是数字字符, parseInt()会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。例如, "1234blue"会被转换为 1234,因为"blue"会被完全忽略。类似地, "22.5"会被转换为 22,因为小数点并不是有效的数字字符

如果字符串中的第一个字符是数字字符, parseInt()也能够识别出各种整数格式(即前面讨论的十进制、八进制和十六进制数)。也就是说,如果字符串以"0x"开头且后跟数字字符,就会将其当作一个十六进制整数;如果字符串以"0"开头且后跟数字字符,则会将其当作一个八进制数来解析。

var num1 = parseInt("1234blue"); // 1234
var num2 = parseInt(""); // NaN
var num3 = parseInt("0xA"); // 10(十六进制数)
var num4 = parseInt(22.5); // 22
var num5 = parseInt("070"); // 56(八进制数)
var num6 = parseInt("70"); // 70(十进制数)
var num7 = parseInt("0xf"); // 15(十六进制数)

注意,在使用 parseInt()解析像八进制字面量的字符串时, ECMAScript 3 和 5 存在分歧 ,所以,可以为这个函数提供第二个参数:转换时使用的基数(即多少进制)。如果知道要解析的值是十六进制格式的字符串,那么指定基数 16 作为第二个参数,可以保证得到正确的结果,例如:

var num = parseInt("0xAF", 16); //175

实际上,如果指定了 16 作为第二个参数,字符串可以不带前面的"0x",如下所示:

var num1 = parseInt("AF", 16); //175
var num2 = parseInt("AF"); //NaN

parseFloat

与 parseInt()函数类似, parseFloat()是从第一个非0非空字符开始解析每个字符。一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。也就是说,字符串中的第一个小数点是有效的,而第二个小数点就是无效的了,因此它后面的字符串将被忽略。举例来说,"22.34.5"将会被转换为 22.34。

parseFloat()可以识别前面讨论过的所有浮点数值格式,也包括十进制整数格式。但十六进制格式的字符串则始终会被转换成 0。由于 parseFloat()只解析十进制值,因此它没有用第二个参数指定基数的用法。最后还要注意一点:如果字符串包含的是一个可解析为整数的数(没有小数点,或者小数点后都是零), parseFloat()会返回整数。以下是使用 parseFloat()转换数值的几个典型示例。

var num1 = parseFloat("1234blue"); //1234 (整数)
var num2 = parseFloat("0xA"); //0
var num3 = parseFloat("22.5"); //22.5
var num4 = parseFloat("22.34.5"); //22.34
var num5 = parseFloat("0908.5"); //908.5
var num6 = parseFloat("3.125e7"); //31250000 

String

toString

要把一个值转换为一个字符串有两种方式。第一种是使用几乎每个值都有的 toString()方法

var age = 11;
var ageAsString = age.toString(); // 字符串"11"
var found = true;
var foundAsString = found.toString(); // 字符串"true"

数值、布尔值、对象和字符串值(没错,每个字符串也都有一个 toString()方法,该方法返回字符串的一个副本)都有 toString()方法。但 null 和 undefined 值没有这个方法。
多数情况下,调用 toString()方法不必传递参数。但是,在调用数值的 toString()方法时,可以传递一个参数:输出数值的基数。默认情况下, toString()方法以十进制格式返回数值的字符串表示。而通过传递基数, toString()可以输出以二进制、八进制、十六进制,乃至其他任意有效进制格式表示的字符串值。下面给出几个例子:

var num = 10;
alert(num.toString()); // "10"
alert(num.toString(2)); // "1010"
alert(num.toString(8)); // "12"
alert(num.toString(10)); // "10"
alert(num.toString(16)); // "a “

String()

在不知道要转换的值是不是 null 或 undefined 的情况下,还可以使用转型函数 String(),这个
函数能够将任何类型的值转换为字符串。

  • 如果值有 toString()方法,则调用该方法(没有参数)并返回相应的结果;
  • 如果值是 null,则返回"null";
  • 如果值是 undefined,则返回"undefined"。

要把某个值转换为字符串,可以使用加号操作符(+)把它与一个字符
串("")加在一起。

++/--

  • 在应用于一个包含有效数字字符的字符串时,先将其转换为数字值,再执行加减 1 的操作。字
    符串变量变成数值变量。
  • 在应用于一个不包含有效数字字符的字符串时,将变量的值设置为 NaN。
    字符串变量变成数值变量。
  • 在应用于布尔值 false 时,先将其转换为 0 再执行加减 1 的操作。布尔值变量变成数值变量。
  • 在应用于布尔值 true 时,先将其转换为 1 再执行加减 1 的操作。布尔值变量变成数值变量。
  • 在应用于浮点数值时,执行加减 1 的操作。
  • 在应用于对象时,先调用对象的 valueOf()方法以取得一个可供操作的
    值。然后对该值应用前述规则。如果结果是 NaN,则在调用 toString()方法后再应用前述规
    则。对象变量变成数值变量
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

+/-

**+**和numer()同规则

在将一元减操作符应用于数值时,该值会变成负数。而当应用于非数值时,
一元减操作符遵循与一元加操作符相同的规则,最后再将得到的数值转换为负数

位操作符

如果对非数值应用位操作符,会先使用 Number()函数将该值转换为一个数值(自动完成),然后
再应用位操作。得到的结果将是一个数值。

在 ECMAScript 中,当对数值应用位操作符时,后台会发生如下转换过程: 64 位的数值被转换成 32
位数值,然后执行位操作,最后再将 32 位的结果转换回 64 位数值。这样,表面上看起来就好像是在操
作 32 位数值,就跟在其他语言中以类似方式执行二进制操作一样。但这个转换过程也导致了一个严重
的副效应,即在对特殊的 NaN 和 Infinity 值应用位操作时,这两个值都会被当成 0 来处理。

按位非(NOT) ~

非操作的本质:操作数的负值减 1。

var num1 = 25; // 二进制 00000000000000000000000000011001
var num2 = ~num1; // 二进制 11111111111111111111111111100110
alert(num2); //

按位与(AND) &

按位与操作只在两个数值的对应位都是 1 时才返回 1,任何一位是 0,结果都是 0。

按位或(OR) |

按位或操作在有一个位是 1 的情况下就返回 1, 而只有在两个位都是 0 的情况下才返回 0。

按位异或(XOR) ^

这个操作在两个数值对应位上只有一个 1 时才返回 1,如果对
应的两位都是 1 或都是 0,则返回 0

左移 <<

这个操作符会将数值的所有位向左移动指定的位数。例如,
如果将数值 2(二进制码为 10)向左移动 5 位,结果就是 64(二进制码为 1000000), 注意,在向左移位后,原数值的右侧多出了 5 个空位。左移操作会以 0 来填充这些空位,以便得到
的结果是一个完整的 32 位二进制数

左移不会影响操作数的符号位。换句话说,如果将-2 向左移动 5 位,结果将是-64,而非 64。

有符号的右移 >>

这个操作符会将数值向右移动,但保留符号位(即
正负号标记)。有符号的右移操作与左移操作恰好相反,即如果将 64 向右移动 5 位,结果将变回 2:

同样,在移位过程中,原数值中也会出现空位。只不过这次的空位出现在原数值的左侧、符号位的
右侧(见图 3-3)。而此时 ECMAScript 会用符号位的值来填充所有空位,以便得到一个完整的值。

无符号右移 >>>

无符号右移操作符由 3 个大于号(>>>)表示,这个操作符会将数值的所有 32 位都向右移动。对正
数来说,无符号右移的结果与有符号右移相同。

但是对负数来说,情况就不一样了。首先,无符号右移是以 0 来填充空位,而不是像有符号右移那
样以符号位的值来填充空位。所以,对正数的无符号右移与有符号右移结果相同,但对负数的结果就不一样了。其次,无符号右移操作符会把负数的二进制码当成正数的二进制码。而且,由于负数以其绝对
值的二进制补码形式表示,因此就会导致无符号右移后的结果非常之大,

布尔操作符

非(NOT)!

逻辑非操作符首先会将它的操作数转换为一个布尔值与Boolean()规则相同,然后再对其求反。

与(AND)&&

逻辑与操作可以应用于任何类型的操作数,而不仅仅是布尔值。在有一个操作数不是布尔值的情况
下,逻辑与操作就不一定返回布尔值;此时,它遵循下列规则:

  • 如果第一个操作数是对象,则返回第二个操作数;
  • 如果第二个操作数是对象,则只有在第一个操作数的求值结果为 true 的情况下才会返回该
    对象;
  • 如果两个操作数都是对象,则返回第二个操作数;
  • 如果有一个操作数是 null,则返回 null;
  • 如果有一个操作数是 NaN,则返回 NaN;
  • 如果有一个操作数是 undefined,则返回 undefined。

逻辑与操作属于短路操作,即如果第一个操作数能够决定结果,那么就不会再对第二个操作数求值。
对于逻辑与操作而言,如果第一个操作数是 false,则无论第二个操作数是什么值,结果都不再可能是
true 了。

或(OR)||

  • 如果第一个操作数是对象,则返回第一个操作数;
  • 如果第一个操作数的求值结果为 false,则返回第二个操作数;
  • 如果两个操作数都是对象,则返回第一个操作数;
  • 如果两个操作数都是 null,则返回 null;
  • 如果两个操作数都是 NaN,则返回 NaN;
  • 如果两个操作数都是 undefined,则返回 undefined。

逻辑或操作符也是短路操作符

乘性操作符

乘 *

  • 如果操作数都是数值,执行常规的乘法计算,即两个正数或两个负数相乘的结果还是正数,而
    如果只有一个操作数有符号,那么结果就是负数。如果乘积超过了 ECMAScript 数值的表示范围,
    则返回 Infinity 或-Infinity;
  • 如果有一个操作数是 NaN,则结果是 NaN;
  • 如果是 Infinity 与 0 相乘,则结果是 NaN;
  • 如果是 Infinity 与非 0 数值相乘,则结果是 Infinity 或-Infinity,取决于有符号操作数
    的符号;
  • 如果是 Infinity 与 Infinity 相乘,则结果是 Infinity;
  • 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的
    规则。

除法 /

  • 如果操作数都是数值,执行常规的除法计算,即两个正数或两个负数相除的结果还是正数,而
    如果只有一个操作数有符号,那么结果就是负数。如果商超过了 ECMAScript 数值的表示范围,
    则返回 Infinity 或-Infinity;
  • 如果有一个操作数是 NaN,则结果是 NaN;
  • 如果是 Infinity 被 Infinity 除,则结果是 NaN;
  • 如果是零被零除,则结果是 NaN;
  • 如果是非零的有限数被零除,则结果是 Infinity 或-Infinity,取决于有符号操作数的符号;
  • 如果是 Infinity 被任何非零数值除,则结果是 Infinity 或-Infinity,取决于有符号操作
    数的符号;
  • 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的规则。

求模 %

  • 如果操作数都是数值,执行常规的除法计算,返回除得的余数;
  • 如果被除数是无穷大值而除数是有限大的数值,则结果是 NaN;
  • 如果被除数是有限大的数值而除数是零,则结果是 NaN;
  • 如果是 Infinity 被 Infinity 除,则结果是 NaN;
  • 如果被除数是有限大的数值而除数是无穷大的数值,则结果是被除数;
  • 如果被除数是零,则结果是零;
  • 如果有一个操作数不是数值,则在后台调用 Number()将其转换为数值,然后再应用上面的规则。

加性操作符

加法 +

  • 如果有一个操作数是 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"。

减法 -

  • 如果两个操作符都是数值,则执行常规的算术减法操作并返回结果;
  • 如果有一个操作数是 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()
    方法并将得到的字符串转换为数值。

关系操作符

  • 如果两个操作数都是数值,则执行数值比较。
  • 如果两个操作数都是字符串,则比较两个字符串对应的字符编码值。
  • 如果一个操作数是数值,则将另一个操作数转换为一个数值,然后执行数值比较。
  • 如果一个操作数是对象,则调用这个对象的 valueOf()方法,用得到的结果按照前面的规则执
    行比较。如果对象没有 valueOf()方法,则调用 toString()方法,并用得到的结果根据前面
    的规则执行比较。
  • 如果一个操作数是布尔值,则先将其转换为数值,然后再执行比较。

相等操作符

  • 如果有一个操作数是布尔值,则在比较相等性之前先将其转换为数值——false 转换为 0,而
    true 转换为 1;

  • 如果一个操作数是字符串,另一个操作数是数值,在比较相等性之前先将字符串转换为数值;

  • 如果一个操作数是对象,另一个操作数不是,则调用对象的 valueOf()方法,用得到的基本类
    型值按照前面的规则进行比较;
    这两个操作符在进行比较时则要遵循下列规则。

  • null 和 undefined 是相等的。

  • 要比较相等性之前,不能将 null 和 undefined 转换成其他任何值。

  • 如果有一个操作数是 NaN,则相等操作符返回 false,而不相等操作符返回 true。重要提示:
    即使两个操作数都是 NaN,相等操作符也返回 false;因为按照规则, NaN 不等于 NaN。

  • 如果两个操作数都是对象,则比较它们是不是同一个对象。如果两个操作数都指向同一个对象,
    则相等操作符返回 true;否则,返回 false。

@chenshuhong chenshuhong added the js label Aug 27, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant