一、JavaScript是一种动态类型语言(dynamically typed language)。这意味着你在声明变量时可以不必指定数据类型,而数据类型会在代码执行时根据需要自动转换。
【示例1】alert会自动将任何值都转换为字符串以进行显示。
【示例2】算术运算符会将值转换为数字。

【示例】以下哪些语句触发了隐式的类型转换?
A. parseInt(12.34, 10)
B. 0 ? 1 : 2
C. 2e1 0xaa
D. 1 + ‘1’
答案:ABD
解析
1. parseInt() 函数可解析一个字符串,并返回一个整数。
所以说,number类型的12.34发生隐式转换为string。
1. 三元运算符,会判断?前的表达式为true或者false。所以number类型的0发生了隐式转换为boolean。
1. +运算发生了字符串的隐式转化。原本number类型的1,和string类型的’1’进行了+运算,连接了字符串。返回’11’。
1. C选项:
e是js里面指数的一种表示形式。也就是10的多少次方。
2e1 等价于 2
(10^1) = 20
2e2 等价于 2 (10^2)= 200
0xaa是16进制的表示方法。相当于十进制的170。
这里都是number类型,发生了数字的乘法运算:20
170,没有发生类型转换。

常用的类型转换

一、转换场景
字符串转换: 转换发生在输出内容的时候,也可以通过String(value)进行显式转换。
数字型转换: 转换发生在进行算术操作时,也可以通过Number(value)进行显式转换。
布尔型转换: 转换发生在进行逻辑操作时,也可以通过Boolean(value)进行显式转换。

转换为string类型

显式转换

一、可以显式地调用String(value)来将value转换为字符串类型。

  1. let value = true;
  2. alert(typeof value); // boolean
  3. value = String(value); // 现在,值是一个字符串形式的 "true"
  4. alert(typeof value); // string

运算符

一、在包含数字和字符串的表达式中使用加法运算符(+),JavaScript会把数字转换成字符串。
在设计其它运算符(如减号-,乘号*, 除号/)时,JavaScript语言不会把数字变成字符串。

  1. '37' + 7 // '377'
  2. '37' - 7 // 30
  3. '37' * 7 // 259
  4. '37' / 7 // 5.285714285714286
【示例】Javascript中表达式 ”2”+3+4 的值为?
A. “27”
B. 9
C. “234”
D. “9”
答案:C
解析:考察点:一元操作符+,类型转换
“+”是左关联,表达式相当于(”2” + 3) + 4

toString()

number -> string

一、方法num.toString(base)返回在给定base进制数字系统中num的字符串表示形式。

  • base的范围可以从2到36。默认情况下是10。
    • base=16 用于十六进制颜色,字符编码等,数字可以是0..9或A..F。
    • base=2 主要用于调试按位操作,数字可以是0或1。
    • base=36 是最大进制,数字可以是0..9或A..Z。所有拉丁字母都被用于了表示数字。 | 【示例】当我们需要将一个较长的数字标识符转换成较短的时候,例如做一个短的 URL。可以简单地使用基数为36的数字系统表示:javascript alert( 123456..toString(36) ); // 2n9c | | —- |

| 【示例】```javascript let num = 255;

alert( num.toString(16) ); // ff alert( num.toString(2) ); // 11111111

  1. |
  2. | --- |
  3. 二、数字后面的.会被解析为小数点
  4. | 【示例】将12toString方法转换为字符串```javascript
  5. 12..toString(); // 如果我们放置一个点:12.toString(),那么就会出现一个 error,因为 JavaScript 语法隐含了第一个点之后的部分为小数部分。如果我们再放一个点,那么 JavaScript 就知道小数部分为空,现在使用该方法。
  6. 12 .toString();
  7. (12).toString();

| | —- |

转换为number类型

转换规则

一、以下值会转换为0: empty, 0, ‘’, ‘0’, false, null, [], [0]

| 【示例】```javascript Number(); // 0 Number(0); // 0 Number(‘’); // 0 Number(‘0’); // 0 Number(false); // 0 Number(null); // 0 Number([]); // 0 Number([0]); // 0

 |
| --- |

⭐️ 二、用表格表示,则为

| 值 | 变成... |
| --- | --- |
| undefined | NaN |
| null | 0 |
| boolean 布尔类型 | true:1,  false: 0 |
| string 字符串类型 | 去掉首尾空格后的纯数字字符串中含有的数字。<br />如果剩余字符串为空,则转换结果为0。<br />否则,将会从剩余字符串中“读取”数字。当类型转换出现 error 时返回NaN。 |
| object 复杂类型 | 会先调用该值得valueOf()方法,如果有并且返回基本类型之,就是用该值进行强制类型转换。如果没有就是使用toString()的返回来进行强制类型转换。 |

| 【示例】```javascript
alert( Number(undefined) );        // NaN
alert( Number(null) );                // 0
alert( Number(true) );        // 1
alert( Number(false) );       // 0
alert( Number("   123   ") ); // 123
alert( Number("123z"));       // NaN(从字符串“读取”数字,读到 "z" 时出现错误)

| | —- |

| 【示例】```javascript var test1 = { valueOf: function(){ return 10; //valueOf方法的将被调用; }, toString: function(){ return 666; } }

Number(test1) ; //10 2*test1; //20

Number(test2); //666 Number(test2)/2; //333

 |
| --- |

| 【示例】Number([])和Number([1,2,3])的值分别是什么?说明其原理?<br />**答案**:```javascript
Number([]) // 0
Number([1, 2, 3]) // NaN

解析
1. 数字的valueOf()方法返回的是数组本身,不是一个基本类型,所以还会调用toString()方法
1. 数组的toString()方法返回的是数组各项经过都好拼接在一起的字符串(可以理解为调用了Array.prototype.join(‘,’)方法)
1. 所以空数组转换为字符串为空字符串’’,转换为数字就是0;
数组[1, 2, 3],转换为字符串为’1, 2, 3’,转换为数字就是NaN
拓展
Number([100])输出多少```javascript Number([100]) // 100

 |
| --- |

<a name="Wf4hs"></a>
### 转换方式
<a name="LSBkq"></a>
#### 显式转换 Number(value)

一、可以使用Number(value)显式地将这个vlaue转换为number类型

| 【示例】```javascript
let str = "123";
alert(typeof str); // string

let num = Number(str); // 变成 number 类型 123

alert(typeof num); // number

| | —- |

二、当我们从 string 类型源(如文本表单)中读取一个值,但期望输入一个数字时,通常需要进行显式转换
三、如果该字符串不是一个有效的数字,转换的结果会是NaN

| 【示例1】```javascript let age = Number(“an arbitrary string instead of a number”);

alert(age); // NaN,转换失败

 |
| --- |

| 【示例】```javascript
alert( Number(" ") ); // 0
alert( Number(' 123')); // 123 // 字符串开头或结尾的空格会被忽略

| | —- |

算术运算符

一、在算术函数和表达式中,会自动进行 number 类型转换。

除法/

| 【示例】当把除法/用于非number类型```javascript alert( “6” / “2” ); // 3, string 类型的值被自动转换成 number 类型后进行计算

 |
| --- |


<a name="IrKI6"></a>
##### 一元加法运算符
| 【示例】```javascript
'1.2' + '1.1' = '1.21.1'
(+'1.2') + (+'1.1') = 2.3 // 加入括号是为清楚起见,不是必须
+'1.2' + +'1.1' = 2.3
+'1.2 ++'1.1' // 报错:Uncaught SyntaxError: Invalid left-hand side expression in postfix operation

| | —- |

| 【示例】```javascript alert(+” “); // 0 alert(+’ 123’); // 123 // 字符串开头或结尾的空格会被忽略

 |
| --- |

| 【示例】如下代码输出的结果是什么: ```html
console.log(1+ "2"+"2");
console.log(1+ +"2"+"2");
console.log("A"- "B"+"2");
console.log("A"- "B"+2)

A. 122 122 NaN NaN
B. 122 32 NaN NaN2
C. 122 32 NaN2 NaN
D. 122 32 NaN2 NaN2
答案:C | | —- |

parseInt()、parseFloat()

见数字对象:https://www.yuque.com/tqpuuk/yrrefz/vz1ofh

转换为boolean类型

转换规则

一、转换规则:直观上为“空”的值(如0、空字符串’’、null、undefined和NaN)将变为false,其他值变成true。
二、用表格表示,则为

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

| 【示例】```javascript alert(Boolean(true)); // true alert(Boolean(false)); // false

alert( Boolean(1) ); // true alert( Boolean(0) ); // false

alert( Boolean(“hello”) ); // true alert( Boolean(“”) ); // false

alert( Boolean(“0”) ); // true alert( Boolean(“ “) ); // 空白,也是 true(任何非空字符串都是 true)

 |
| --- |

<a name="XAOkZ"></a>
### 转换方式
一、布尔(boolean)类型转换发生在逻辑运算中,但是也可以通过调用 Boolean(value) 显式地进行转换。
<a name="r3adf"></a>
#### 隐式转换
一、逻辑运算使用布尔类型的隐式转换

| 【示例】```html
console.log(([])?true:false); 
console.log(([]==false?true:false)); 
console.log(({}==false)?true:false)

上面这段代码运行后得到的结果分别是什么?
A. false true true
B. true true true
C. true false true
D. true true false
答案:D
解析:考察点:条件(三元)运算符运算规则、Boolean()转换规则、比较运算符==转换规则、对象与原始值之间的转换
一、相关规则
1、条件运算符运算规则:条件判断时使用Boolean的隐式转换,即调用Boolean();
2、Boolean()转换规则:直观上为“空”的值(如0、空字符串’’、null、undefined和NaN)将变为false,其他值变成true。
3、比较运算符==的转换规则:当对不同类型的值进行比较时,JavaScript 会首先将其转化为数字(number)再判定大小。
4、对象与原始值之间的转换算法:如果存在则调用objSymbol.toPrimitive,否则尝试obj.valueOf()和obj.toString()
二、代码解析
1、①[]属于对象,Boolean(对象)为true。②true?true:false,结果为true
2、①[]==false, 即Number([])==Number(false)。②左边为([]).toString()=’’, Number(‘’)=0,最终比较的是0==0,即为true。③Boolean(true)为true。④true?true:false,结果为true
3、①{}==false,即Number({})==Number(0),。②左边为({}).toString()=’[object Object]’, Number(‘[object Object]’)=NaN,最终比较的是NaN==0,即为false。③Boolean(false)为false。④false?true:false,结果为false | | —- |

显式转换

一、可使用Boolean(value)显式转换

对象与原始值之间的转换

一、对象、原始值转换
1、对象 to-boolean
(1)所有的对象在布尔上下文(context)中均为true。所以对于对象,不存在 to-boolean 转换,只有字符串和数值转换。
2、对象 to-number
(1)数值转换发生在对象相减或应用数学函数时。

【示例】Date对象可以相减,date1 - date2的结果是两个日期之间的差值。

3、对象 to-string
(1)字符串转换: 通常发生在我们像alert(obj)这样输出一个对象和类似的上下文中。

【示例】当使用alert(obj)打印时会发生什么?
答案:在这种情况下,对象会被自动转换为原始值,然后执行操作。

二、对象到原始值的转换,是由许多期望以原始值作为值的内建函数和运算符自动调用的。

转换算法

ToPrimitive

一、在js中,想要将对象转换成原始值,必然会调用toPrimitive()内部函数。
二、下面是三个类型转换的变体,被称为 “hint”,在规范中有详细介绍(译注:当一个对象被用在需要原始值的上下文中时,例如,在alert或数学运算中,对象会被转换为原始值):
1、”string”:对于alert和其他需要字符串的操作
(1)对象到字符串的转换,当我们对期望一个字符串的对象执行操作时,如 “alert”:

// 输出
alert(obj);

// 将对象作为属性键
anotherObj[obj] = 123;

2、”number”:对于数学运算
(1)对象到数字的转换

| 【示例】当我们进行数学运算时:```javascript // 显式转换 let num = Number(obj);

// 数学运算(除了二进制加法) let n = +obj; // 一元加法 let delta = date1 - date2;

// 小于/大于的比较 let greater = user1 > user2;

 |
| --- |


3、"default":少数运算符<br />(1)在少数情况下发生,当运算符“不确定”期望值的类型时。<br />① 二进制加法+可用于字符串(连接),也可以用于数字(相加),所以字符串和数字这两种类型都可以。因此,当二元加法得到对象类型的参数时,它将依据"default" hint 来对其进行转换。<br />②如果对象被用于与字符串、数字或 symbol 进行==比较,这时到底应该进行哪种转换也不是很明确,因此使用"default"hint。
```javascript
// 二元加法使用默认 hint
let total = obj1 + obj2;

// obj == number 使用默认 hint
if (user == 1) { ... };

(2)像<和>这样的小于/大于比较运算符,也可以同时用于字符串和数字。不过,它们使用 “number” hint,而不是 “default”。这是历史原因。
(3)通常对于内建对象,”default”hint 的处理方式与”number”相同,因此在实践中,最后两个 hint 常常合并在一起。
三、实际上,我们没有必要记住这些奇特的细节,除了一种情况(Date对象)之外,所有内建对象都以和”number”相同的方式实现”default”转换。我们也可以这样做。
四、转换算法:为了进行转换,JavaScript 尝试查找并调用三个对象方法:
1、调用objSymbol.toPrimitive—— 带有 symbol 键Symbol.toPrimitive(系统 symbol)的方法,如果这个方法存在的话,
2、否则,如果 hint 是”string”—— 尝试obj.toString()和obj.valueOf(),无论哪个存在。
3、否则,如果 hint 是”number”或”default”—— 尝试obj.valueOf()和obj.toString(),无论哪个存在。

Symbol.toPrimitive

一、我们从第一个方法开始。有一个名为Symbol.toPrimitive的内建 symbol,它被用来给转换方法命名,像这样:

obj[Symbol.toPrimitive] = function(hint) {
  // 返回一个原始值
  // hint = "string"、"number" 和 "default" 中的一个
}

1、例如,这里user对象实现了它:

let user = {
  name: "John",
  money: 1000,

  [Symbol.toPrimitive](hint) {
    alert(`hint: ${hint}`);
    return hint == "string" ? `{name: "${this.name}"}` : this.money;
  }
};

// 转换演示:
alert(user); // hint: string -> {name: "John"}
alert(+user); // hint: number -> 1000
alert(user + 500); // hint: default -> 1500

2、从代码中我们可以看到,根据转换的不同,user变成一个自描述字符串或者一个金额。单个方法user[Symbol.toPrimitive]处理了所有的转换情况。

toString/valueOf

一、方法toString和valueOf来自上古时代。它们不是 symbol(那时候还没有 symbol 这个概念),而是“常规的”字符串命名的方法。它们提供了一种可选的“老派”的实现转换的方法。
二、如果没有Symbol.toPrimitive,那么 JavaScript 将尝试找到它们,并且按照下面的顺序进行尝试:

  • 对于 “string” hint,toString -> valueOf。
  • 其他情况,valueOf -> toString。

1、这些方法必须返回一个原始值。如果toString或valueOf返回了一个对象,那么返回值会被忽略(和这里没有方法的时候相同)。
三、默认情况下,普通对象具有toString和valueOf方法:

  • toString方法返回一个字符串”[object Object]”。
  • valueOf方法返回对象自身。

【示例1】

let user = {name: "John"};

alert(user); // [object Object]
alert(user.valueOf() === user); // true

1、所以,如果我们尝试将一个对象当做字符串来使用,例如在alert中,那么在默认情况下我们会看到[object Object]。
2、这里提到默认值valueOf只是为了完整起见,以避免混淆。正如你看到的,它返回对象本身,因此被忽略。别问我为什么,那是历史原因。所以我们可以假设它根本就不存在。
四、让我们实现一下这些方法。
1、这里的user执行和前面提到的那个user一样的操作,使用toString和valueOf的组合(而不是Symbol.toPrimitive):

let user = {
  name: "John",
  money: 1000,

  // 对于 hint="string"
  toString() {
    return `{name: "${this.name}"}`;
  },

  // 对于 hint="number" 或 "default"
  valueOf() {
    return this.money;
  }

};

alert(user); // toString -> {name: "John"}
alert(+user); // valueOf -> 1000
alert(user + 500); // valueOf -> 1500

(1)我们可以看到,执行的动作和前面使用Symbol.toPrimitive的那个例子相同。
五、通常我们希望有一个“全能”的方法来处理所有原始转换。在这种情况下,我们可以只实现toString,就像这样:

let user = {
  name: "John",

  toString() {
    return this.name;
  }
};

alert(user); // toString -> John
alert(user + 500); // toString -> John500

六、如果没有Symbol.toPrimitive和valueOf,toString将处理所有原始转换。

数组的toString

一、数组有自己的toString方法的实现,会返回以逗号隔开的元素列表。
【示例1】

let arr = [1, 2, 3];

alert( arr ); // 1,2,3
alert( String(arr) === '1,2,3' ); // true
此外,我们试试运行一下这个:


alert( [] + 1 ); // "1"
alert( [1] + 1 ); // "11"
alert( [1,2] + 1 ); // "1,21"

二、数组没有Symbol.toPrimitive,也没有valueOf,它们只能执行toString进行转换,所以这里[]就变成了一个空字符串,[1]变成了”1”,[1,2]变成了”1,2”。
三、当”+”运算符把一些项加到字符串后面时,加号后面的项也会被转换成字符串,所以下一步就会是这样:

alert( "" + 1 ); // "1"
alert( "1" + 1 ); // "11"
alert( "1,2" + 1 ); // "1,21"

返回类型

一、所有原始转换方法,不一定会返回 “hint” 的原始值。
二、没有限制toString()是否返回字符串,或Symbol.toPrimitive方法是否为 hint “number” 返回数字。
三、唯一强制性的事情是:这些方法必须返回一个原始值,而不是对象。
四、由于历史原因,如果toString或valueOf返回一个对象,则不会出现 error,但是这种值会被忽略(就像这种方法根本不存在)。这是因为在 JavaScript 语言发展初期,没有很好的 “error” 的概念。
1、相反,Symbol.toPrimitive必须返回一个原始值,否则就会出现 error。

进一步的转换

一 、我们已经知道,许多运算符和函数执行类型转换,例如乘法*将操作数转换为数字。
二、如果我们将对象作为参数传递,则会出现两个阶段:

  1. 对象被转换为原始值(通过前面我们描述的规则)。
  2. 如果生成的原始值的类型不正确,则继续进行转换。

【示例1】

let obj = {
  // toString 在没有其他方法的情况下处理所有转换
  toString() {
    return "2";
  }
};

alert(obj * 2); // 4,对象被转换为原始值字符串 "2",之后它被乘法转换为数字 2。

1、乘法obj 2首先将对象转换为原始值(字符串 “2”)。
2、之后”2”
2变为2 * 2(字符串被转换为数字)。
三、二元加法在同样的情况下会将其连接成字符串,因为它更愿意接受字符串:

let obj = {
  toString() {
    return "2";
  }
};

alert(obj + 2); // 22("2" + 2)被转换为原始值字符串 => 级联

对象之间的转换

set <—> 数组

一、set转换为数组有3种方式:Array.from、展开运算符、循环

| 【示例】```javascript const demo = new Set([1, 2, 3]); const arr = Array.from(demo); console.log(arr);

![image.png](https://cdn.nlark.com/yuque/0/2022/png/355497/1644587368259-968493ce-8c6e-4fd6-baa1-4a8b50b13c34.png#clientId=u7b6b9f1a-21ab-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=101&id=u9e3e3604&margin=%5Bobject%20Object%5D&name=image.png&originHeight=101&originWidth=273&originalType=binary&ratio=1&rotation=0&showTitle=false&size=13732&status=done&style=none&taskId=ud21d6e7d-a779-49b0-9220-2b753ed61cc&title=&width=273) |
| --- |

| 【示例】```javascript
const newSet = new Set(['a', 'b']);
const arr = [...newSet];

| | —- |

二、数组转为set的方式:new Set

| 【示例】javascript const arr = [1, 2, 3]; const newSet = new Set(arr); | | —- |