icon
类型转换&运算符规则&表达式

类型转换&运算符规则&表达式

JavaScript 是弱类型语言,类型转换是自动进行的。理解类型转换规则对于避免 bug 非常重要。

类型转换

  1. 转换为字符串
    • String()
    • toString()
    • 使用 + ''(隐式转换)
String(123);        // "123"
String(true);       // "true"
String(null);       // "null"
String(undefined);  // "undefined"

(123).toString();   // "123"
true.toString();    // "true"

123 + '';           // "123"
true + '';          // "true"
  1. 转换为数字
    • Number()
    • parseInt()
    • parseFloat()
    • 使用 +(一元加运算符)
    • 使用 -(减法运算符触发转换)
Number('123');      // 123
Number('123abc');   // NaN
Number(true);       // 1
Number(false);      // 0
Number(null);       // 0
Number(undefined);  // NaN

parseInt('123');    // 123
parseInt('123abc'); // 123
parseInt('abc123'); // NaN

parseFloat('123.45'); // 123.45

+'123';             // 123
+true;              // 1
+false;             // 0
  1. 转换为布尔值
    • Boolean()
    • 使用 !!(双重取反)
Boolean(1);         // true
Boolean(0);         // false
Boolean('');        // false
Boolean('0');       // true
Boolean(null);      // false
Boolean(undefined); // false
Boolean([]);        // true
Boolean({});        // true

!!1;                // true
!!0;                // false
!!'';               // false

隐式类型转换

  1. 算术运算符
'1' + 2;            // "12" (字符串拼接)
'1' - 2;            // -1 (数字运算)
'1' * 2;            // 2 (数字运算)
'1' / 2;            // 0.5 (数字运算)
'1' % 2;            // 1 (数字运算)

true + 1;           // 2
false + 1;          // 1
null + 1;           // 1
undefined + 1;      // NaN
  1. 比较运算符
'1' == 1;           // true (类型转换后比较)
'1' === 1;          // false (严格相等,不转换类型)

null == undefined;  // true
null === undefined; // false

0 == false;         // true
0 === false;        // false

'' == false;        // true
'' === false;       // false
  1. 逻辑运算符
'hello' && 'world'; // "world" (返回最后一个真值)
'hello' || 'world'; // "hello" (返回第一个真值)

'' && 'world';      // "" (返回第一个假值)
'' || 'world';      // "world" (返回第一个真值)

0 && 1;             // 0
0 || 1;             // 1

== vs ===

==(相等运算符)

  • 会进行类型转换
  • 遵循复杂的转换规则
// == 的转换规则
null == undefined;  // true
null == 0;          // false
undefined == 0;     // false

'0' == 0;           // true
'' == 0;            // true
false == 0;         // true

[] == 0;            // true
[] == '';           // true
[] == false;        // true

[1] == 1;           // true
[1,2] == '1,2';     // true

===(严格相等运算符)

  • 不进行类型转换
  • 类型和值都必须相等
'0' === 0;          // false
'' === 0;           // false
false === 0;        // false

null === undefined; // false

运算符优先级

从高到低:

  1. 成员访问、函数调用、new
  2. 一元运算符(+、-、!、typeof、void、delete)
  3. 算术运算符(*、/、%、+、-)
  4. 关系运算符(<、>、<=、>=、in、instanceof)
  5. 相等运算符(==、!=、===、!==)
  6. 逻辑与(&&)
  7. 逻辑或(||)
  8. 三元运算符(?:)
  9. 赋值运算符(=、+=、-=等)
// 优先级示例
let a = 1;
let b = 2;
let c = 3;

console.log(a + b * c);        // 7 (先乘后加)
console.log((a + b) * c);      // 9 (括号改变优先级)

console.log(a || b && c);      // 1 (&& 优先级高于 ||)
console.log((a || b) && c);    // 3

console.log(a > b ? a : b);    // 2

表达式求值

  1. 逗号运算符
    • 返回最后一个表达式的值
let a = (1, 2, 3);  // a = 3
let b = (x = 1, y = 2, x + y); // b = 3

function test() {
  return (console.log('1'), console.log('2'), 'result');
}
test(); // 输出: 1, 2,返回 'result'
  1. void 运算符
    • 执行表达式并返回 undefined
void 0;             // undefined
void(1 + 2);        // undefined

// 常用于立即执行函数
void function() {
  console.log('IIFE');
}();
  1. typeof 运算符
typeof 123;         // "number"
typeof 'hello';     // "string"
typeof true;        // "boolean"
typeof undefined;   // "undefined"
typeof null;        // "object" (历史遗留问题)
typeof {};          // "object"
typeof [];          // "object"
typeof function(){};// "function"
  1. instanceof 运算符
    • 检查对象是否是某个构造函数的实例
[] instanceof Array;        // true
{} instanceof Object;       // true
[] instanceof Object;       // true

function Person() {}
const p = new Person();
p instanceof Person;        // true

类型转换陷阱

  1. 数组转换
[] + [];            // "" (转换为字符串后拼接)
[] - [];            // 0 (转换为数字后相减)
[1] + [2];          // "12"
[1,2] + [3,4];      // "1,23,4"

Number([]);         // 0
Number([1]);        // 1
Number([1,2]);      // NaN
  1. 对象转换
{} + {};            // "[object Object][object Object]"
{} + [];            // 0 (特殊情况)
[] + {};            // "[object Object]"

Number({});         // NaN
String({});         // "[object Object]"
  1. 布尔值转换
if ([]) {
  console.log('true');  // 执行
}

if ({}) {
  console.log('true');  // 执行
}

if (0) {
  console.log('false'); // 不执行
}

if ('') {
  console.log('false'); // 不执行
}

最佳实践

  1. 使用严格相等
// 好的做法
if (value === 0) { }
if (value === null) { }

// 避免
if (value == 0) { }
  1. 显式类型转换
// 好的做法
const num = Number(str);
const str = String(num);
const bool = Boolean(value);

// 避免隐式转换
const num = +str;
const str = num + '';
const bool = !!value; // 可以接受
  1. 使用类型检查
// 检查类型
if (typeof value === 'number') { }
if (Array.isArray(value)) { }
if (value instanceof Date) { }