深度剖析之由浅入深揭秘JavaScript类型转换(最全总结篇)(一)

简介: 深度剖析之由浅入深揭秘JavaScript类型转换(最全总结篇)(一)

深度剖析之由浅入深揭秘JavaScript类型转换(最全总结篇)

值类型转换

  • • 将值从一种类型转换为另一种类型通常称为类型转换,分为 隐式强制类型转换显示强制类型转换。两者的区别在于是否可直观看出。
  • • 如下代码:
var a = 42;
var b = a + "";         // 隐式强制类型转换
var c = String( a );    // 显式强制类型转换
b; // 42
c; // 42
  • • 上述代码中,对于 b 而言是隐式转换,而对于 c 而言是显示转换。

抽象值操作

  • • 在值类型转换前我们先来看看字符串、数字、布尔值之前的基本转换规则。

toString

  • • 该操作,负责处理非字符串到字符串的强制类型转换。
  • • 例如:null -> "null",undefined -> "undefined", true -> "true"
  • 对于普通对象来说,除非自定义,否则都会调用其内部的 toString() 方法。
  • • Array
  • 数组的toString() 方法经过了重定义,会将所有数组元素用 , 连接起来。
var a = [1,2,3];
a.toString(); // 1,2,3
  • • JSON
  • • 工具函数 JSON.stringify() 在将 JSON 对象序列化为字符串时也用到了 toString
  • • 对于大多数简单值来说,JSON 字符串与 toString() 的结果基本相同。但对于某一些值来说不同,例如:undefined, function, symbol, 循环引用(对象之间的相互引用,行程一个无限循环),JSON.stringify() 就无法处理它。
  • • 如下代码:
JSON.stringify(undefined); // undefined
JSON.stringify(function () {}); // undefined
JSON.stringify([1, undefined, function () {}, 4]); // "[1,null,null,4]"
JSON.stringify({ a: 2, b: function () {} }); // "{"a":2}"
JSON.stringify([undefined, Object, Symbol("")]);  // '[null,null,null]'
  • • 对于包含循环引用的对象执行 JSON.stringify() 会出错。但我们可以通过 toJSON() 方法进行重写。
  • • 如下代码:
// eg1:
var o = { };
var a = {
    b: 42,
    c: o,
    d: function(){}
};
// 在a中创建一个循环引用
o.e = a;
// 循环引用在这里会产生错误
// JSON.stringify( a ); // TypeError: Converting circular structure to JSON
// 自定义的JSON序列化
a.toJSON = function() {
    // 序列化仅包含b
    return { b: this.b };
};
JSON.stringify( a ); // "{"b":42}"
// eg2:
var a = {
    val: [1,2,3],
    // 可能是我们想要的结果!
    toJSON: function(){
        return this.val.slice( 1 );
    }
};
JSON.stringify( a ); // "[2,3]"
  • • 还有关于 JSON.stringify() 的不太为人知的功能:
  • • 可向 JSON.stringify() 中传递第二个参数 replacer, 可以是数组或函数
  • 如果 replacer 为数组, 那它必须为字符串数组,数组中包含了要序列化要处理的对象 key, 除此之外的属性则会被忽略
  • 如果 replacer 为函数,那它会对对象本身调用一次,然后对对象中的每个属性各调用一次,可传递两个参数,键和值。
  • • 如下代码:
var a = {
    b: 42,
    c: "42",
    d: [1,2,3]
};
// replacer 为数组
JSON.stringify( a, ["b","c"] ); // "{"b":42,"c":"42"}"
// replacer 为函数
JSON.stringify( a, function(k,v){
    if (k !== "c") return v;
} );
// "{"b":42,"d":[1,2,3]}"
  • 还有一个可选参数 space,用于指定缩进格式。
var a = {
    b: 42,
    c: "42",
    d: [1,2,3]
};
JSON.stringify( a, null, 3 );
// "{
//    "b": 42,
//    "c": "42",
//    "d": [
//       1,
//       2,
//       3
//    ]
// }"
  • • 总结:
  • 对于字符串,数字,布尔值和 null,结果与 toString() 基本相同。
  • 如果在 JSON.stringify() 的对象中重定义了 toJSON() 方法,那该方法会在字符序列化前调用。

toNumber

  • • 其中 true 转换为 1,false 转换为 0。undefined 转换为 NaN,null 转换为 0。
  • • 将值转换时会遵循以下规则:
  • 在使用 Number() 或 toNumber() 方法将一个字符串转换为数字时,如果字符串中出现非数字字符,则会返回 NaN。
let obj = {
    // 首先调用
    [Symbol.toPrimitive]() {
        return 200;
    },
    // 中间调用
    valueOf() {
        return 300;
    },
    // 最后调用
    toString() {
        return 'Hello';
    }
}
console.log(obj + 200); // 400

toBoolean

  • • 以下这些是假值:
• undefined
• null
• false
• +0、-0 和 NaN
• ""
// 假值的布尔强制类型转换结果为 false。
  • • 我们可以这么理解除了以上假值列表意外的值都是真值。
// eg1:
var a = new Boolean(false);
var b = new Number(0);
var c = new String("");
console.log(!!(a && b && c)); // true
// eg2:
var a = 'false';
var b = '0';
var c = "''";
console.log(!!(a && b && c)); // true

toPromitive

  • • 转换规则:
  • • 如果检查该值是否有 valueOf 方法,看是否会返回原始值,如果返回值是原始值,则直接使用。否则,就使用 toString 方法,如果 toString 方法返回的是原始值,则直接使用,否则抛出 TypeError 错误。
"0" == false; // true
false == 0; // true
false == ""; // true
false == []; // true
"" == 0; // true
"" == []; // true
0 == []; // true

显示强制类型转换

  • ~(非) 运算符
  • • 对于非运算符的理解:我们可理解为 ~ 会返回 2 的补码
  • • 如下:
// ~x 大致等于 -(x + 1)。
~42; // -(42 + 1) ==> -43
  • 在 -(x + 1) 中唯一能够得到 0 的 x 值是 -1。也就是如果 x 为 -1 时,~ 与其他一些数字值会返回 false 值,否则返回 true 值。
// before
var a = "Hello World";
if (a.indexOf( "lo" ) >= 0) {   // true
    // 找到匹配!
}
if (a.indexOf( "lo" ) != -1) {  // true
    // 找到匹配!
}
if (a.indexOf( "ol" ) < 0) {    // true
    // 没有找到匹配!
}
if (a.indexOf( "ol" ) == -1) {  // true
    // 没有找到匹配!
}
// after
var a = "Hello World";
~a.indexOf( "lo" );         // -4   <-- 真值!
if (~a.indexOf( "lo" )) {   // true
    // 找到匹配!
}
~a.indexOf( "ol" );         // 0    <-- 假值!
!~a.indexOf( "ol" );        // true
if (!~a.indexOf( "ol" )) {  // true
    // 没有找到匹配!
}
  • • 显示转换为布尔值
// before
var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;
Boolean( a ); // true
Boolean( b ); // true
Boolean( c ); // true
Boolean( d ); // false
Boolean( e ); // false
Boolean( f ); // false
Boolean( g ); // false
// after
var a = "0";
var b = [];
var c = {};
var d = "";
var e = 0;
var f = null;
var g;
!!a;    // true
!!b;    // true
!!c;    // true
!!d;    // false
!!e;    // false
!!f;    // false
!!g;    // false
  • • 在if() 判断中,如果没有使用 Boolean() 和 !!, 就会自动隐式进行 toBoolean 转换。
相关文章
|
7月前
|
JavaScript 前端开发
JavaScript基础语法(类型转换)
JavaScript基础语法(类型转换)
53 0
|
2月前
|
JavaScript 前端开发 安全
如何处理 JavaScript 中的类型转换错误?
【10月更文挑战第9天】处理类型转换错误需要综合运用多种方法和策略,同时要保持对潜在问题的警惕性。通过合理的错误处理,可以提高程序的健壮性,减少因类型转换错误带来的负面影响。
35 0
|
2月前
|
JavaScript 前端开发
JS隐式类型转换规则
【10月更文挑战第9天】 不同的 JavaScript 引擎可能在隐式类型转换的具体实现上存在一些细微差别。理解这些隐式类型转换规则对于正确处理数据和避免错误非常重要。
20 0
|
3月前
|
JavaScript 前端开发
JavaScript 类型转换
JavaScript 类型转换
27 4
|
5月前
|
开发框架 JavaScript 前端开发
JavaScript框架比较与选择:技术深度剖析
【7月更文挑战第23天】选择正确的JavaScript框架是项目成功的关键。React.js、Vue.js、Angular和Svelte等前端框架各有千秋,分别适用于不同的项目需求。同时,Node.js及其后端框架为服务器端开发提供了强大的支持。开发人员应根据项目的复杂性、性能要求、开发周期以及团队技能等因素综合考虑,选择最适合的框架。随着技术的不断发展,未来还将涌现更多优秀的JavaScript框架,为开发者带来更多选择和可能性。
|
4月前
|
JavaScript 前端开发
JS:类型转换(四)从底层逻辑让你搞懂经典面试问题 [ ] == ![ ] ?
JS:类型转换(四)从底层逻辑让你搞懂经典面试问题 [ ] == ![ ] ?
|
5月前
|
JavaScript
js【详解】自动类型转换
js【详解】自动类型转换
28 0
|
5月前
|
JavaScript 前端开发
|
7月前
|
JavaScript 前端开发 Python
javascript中的强制类型转换和自动类型转换
javascript中的强制类型转换和自动类型转换
|
7月前
|
存储 JavaScript 前端开发
深度剖析JavaScript中的变量世界:概念、用例与避坑指南
【4月更文挑战第3天】探索JavaScript变量:了解var、let、const的差异,掌握数据类型、用例及避免错误的策略。声明变量时注意作用域和可变性,如var的函数作用域,let和const的块级作用域。理解基本数据类型(Number、String等)和对象类型。示例包括用户输入、计算、控制流程和函数参数。警惕未声明、作用域混淆、类型不匹配和未初始化的错误,遵循最佳实践,如明确命名、避免冗余和适时复用,利用类型检查工具提升代码质量。
167 1