jsbyte转string_原⽣JS的知识系统梳理
笔者最近在对原⽣JS的知识做系统梳理,因为我觉得JS作为前端⼯程师的根本技术,学再多遍都不为过。打算来做⼀个系列,⼀共分三次发,以⼀系列的问题为驱动,当然也会有追问和扩展,内容系统且完整,对初中级选⼿会有很好的提升,⾼级选⼿也会得到复习和巩固。敬请⼤家关注!
第⼀篇: JS数据类型之问——概念篇
1.JS原始数据类型有哪些?引⽤数据类型有哪些?
在 JS 中,存在着 7 种原始值,分别是:
boolean
null
undefined
number
string
symbol
bigint
引⽤数据类型: 对象Object(包含普通对象-Object,数组对象-Array,正则对象-RegExp,⽇期对象-Date,数学函数-Math,函数对象-Function)
2.说出下⾯运⾏的结果,解释原因。
function test(person) {
person.age = 26
person = {
name: 'hzj',
age: 18
}
return person
}
const p1 = {
name: 'fyq',
age: 19
}
const p2 = test(p1)
console.log(p1) // -> ?
console.log(p2) // -> ?
结果:
p1:{name: “fyq”, age: 26}
p2:{name: “hzj”, age: 18}
原因: 在函数传参的时候传递的是对象在堆中的内存地址值,test函数中的实参person是p1对象的内存地址,通过调⽤person.age = 26确实改变了p1的值,但随后person变成了另⼀块内存空间的地址,并且在最后将这另外⼀份内存空间的地址返回,赋给了p2。
3.null是对象吗?为什么?
结论: null不是对象。
解释: 虽然 typeof null 会输出 object,但是这只是 JS 存在的⼀个悠久 Bug。在 JS 的最初版本中使⽤的是 32 位系统,为了性能考虑使⽤低位存储变量的类型信息,000 开头代表是对象然⽽ null 表⽰为全零,所以将它错误的判断为 object 。
4.'1'.toString()为什么可以调⽤?
其实在这个语句运⾏的过程中做了这样⼏件事情:
var s = new Object('1');
s = null;
第⼀步: 创建Object类实例。注意为什么不是String ?由于Symbol和BigInt的出现,对它们调⽤new都会报错,⽬前ES6规范也不建议⽤new来创建基本类型的包装类。
第⼆步: 调⽤实例⽅法。
第三步: 执⾏完⽅法⽴即销毁这个实例。
整个过程体现了 基本包装类型的性质,⽽基本包装类型恰恰属于基本数据类型,包括Boolean, Number和String。
参考:《JavaScript⾼级程序设计(第三版)》P118
5.0.1+0.2为什么不等于0.3?
0.1和0.2在转换成⼆进制后会⽆限循环,由于标准位数的限制后⾯多余的位数会被截掉,此时就已经出现了精度的损失,相加后因浮点数⼩数位的限制⽽截断的⼆进制数字在转换为⼗进制就会变成0.30000000000000004。
6.如何理解BigInt?
什么是BigInt?
BigInt是⼀种新的数据类型,⽤于当整数值⼤于Number数据类型⽀持的范围时。这种数据类型允许我们安全地对 ⼤整数执⾏算术操作,表⽰⾼分辨率的时间戳,使⽤⼤整数id,等等,⽽不需要使⽤库。
为什么需要BigInt?
在JS中,所有的数字都以双精度64位浮点格式表⽰,那这会带来什么问题呢?
这导致JS中的Number⽆法精确表⽰⾮常⼤的整数,它会将⾮常⼤的整数四舍五⼊,确切地说,JS中的Number类型只能安全地表⽰-9007199254740991(-(2^53-1))和9007199254740991((2^53-1)),任何超出此范围的整数值都可能失去精度。
console.log(999999999999999); //=>10000000000000000
同时也会有⼀定的安全性问题:
9007199254740992 === 9007199254740993; // → true 居然是true!
如何创建并使⽤BigInt?
要创建BigInt,只需要在数字末尾追加n即可。
console.log( 9007199254740995n ); // → 9007199254740995n
console.log( 9007199254740995 ); // → 9007199254740996
另⼀种创建BigInt的⽅法是⽤BigInt()构造函数、
BigInt("9007199254740995"); // → 9007199254740995n
简单使⽤如下:
10n + 20n; // → 30n
10n - 20n; // → -10n
+10n; // → TypeError: Cannot convert a BigInt value to a number
-10n; // → -10n
10n * 20n; // → 200n
20n / 10n; // → 2n
23n % 10n; // → 3n
10n ** 3n; // → 1000n
const x = 10n;
++x; // → 11n
--x; // → 9n
console.log(typeof x); //"bigint"
值得警惕的点
1. BigInt不⽀持⼀元加号运算符, 这可能是某些程序可能依赖于 + 始终⽣成 Number 的不变量,或者抛出异常。另外,更改 + 的⾏为也
会破坏 asm.js代码。
2. 因为隐式类型转换可能丢失信息,所以不允许在bigint和 Number 之间进⾏混合操作。当混合使⽤⼤整数和浮点数时,结果值可能⽆
法由BigInt或Number精确表⽰。
10 + 10n; // → TypeError
1. 不能将BigInt传递给Web api和内置的 JS 函数,这些函数需要⼀个 Number 类型的数字。尝试这样做会报TypeError错误。
Math.max(2n, 4n, 6n); // → TypeError
1. 当 Boolean 类型与 BigInt 类型相遇时,BigInt的处理⽅式与Number类似,换句话说,只要不是0n,BigInt就被视为truthy的值。
if(0n){//条件判断为false
}
if(3n){//条件为true
}
1. 元素都为BigInt的数组可以进⾏sort。
2. BigInt可以正常地进⾏位运算,如|、&、<>和^
浏览器兼容性
caniuse的结果:
其实现在的兼容性并不怎么好,只有chrome67、firefox、Opera这些主流实现,要正式成为规范,其实还有很长的路要⾛。
我们期待BigInt的光明前途!
第⼆篇: JS数据类型之问——检测篇
1. typeof 是否能正确判断类型?
对于原始类型来说,除了 null 都可以调⽤typeof显⽰正确的类型。
typeof 1 // 'number'
typeof '1' // 'string'
typeof undefined // 'undefined'
typeof true // 'boolean'
typeof Symbol() // 'symbol'
但对于引⽤数据类型,除了函数之外,都会显⽰"object"。
typeof [] // 'object'
typeof {} // 'object'
typeof console.log // 'function'
因此采⽤typeof判断对象数据类型是不合适的,采⽤instanceof会更好,instanceof的原理是基于原型链的查询,只要处于原型链中,判断永远为true
const Person = function() {}
const p1 = new Person()
p1 instanceof Person // true
var str1 = 'hello world'
str1 instanceof String // false
var str2 = new String('hello world')js arguments
str2 instanceof String // true
2. instanceof能否判断基本数据类型?
能。⽐如下⾯这种⽅式:
class PrimitiveNumber {
static [Symbol.hasInstance](x) {
return typeof x === 'number'
}
}
console.log(111 instanceof PrimitiveNumber) // true
如果你不知道Symbol,可以看看MDN上关于hasInstance的解释。
其实就是⾃定义instanceof⾏为的⼀种⽅式,这⾥将原有的instanceof⽅法重定义,换成了typeof,因此能够判断基本数据类型。
3. 能不能⼿动实现⼀下instanceof的功能?
核⼼: 原型链的向上查。
function myInstanceof(left, right) {
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论