js数据类型很简单,却也不简单,成功收获美团,小米offer

const symbol1 = Symbol(‘Tusi’)

Symbol值是唯一的,所以下面的等式是不成立的。

Symbol(1) === Symbol(1) // false

对象类型


对象类型也叫引用类型,简单地理解呢,对象就是键值对key:value的集合。常见的对象类型有Object, Array, Function, Date, RegExp等。

除了这些,Javascript还有蛮蛮多的全局对象,具体见JavaScript 标准内置对象。但是全局对象并不意味着它就是一种对象类型,就比如JSON是一个全局对象,但是它不是一种类型,这一点要搞清楚。

前面说了,对象可以new出来,所以对象类型都有构造函数,Object类型对应的构造函数是Object()Array类型对应的构造函数是Array(),不再赘述。

var obj = new Object() // 不过我们一般也不会这么写一个普通对象

var arr1 = new Array(1) // 创建一个length是1的空数组

var arr2 = new Array(1, 2) // 创建数组[1, 2]

栈内存和堆内存


栈内存的优势是,存取速度比堆内存要快,充分考虑这一点,其实是可以优化代码性能的。

栈内存

原始类型是按值访问的,其值存储在栈内存中,所占内存大小是已知的或是有范围的;

对基本类型变量的重新赋值,其本质上是进行压栈操作,写入新的值,并让变量指向一块栈顶元素(大概意思是这样,但是v8等引擎有没有做这方面的优化,就要细致去看了)

var a = 1; // 压栈,1成为栈顶元素,其值赋给变量a

a = 2; // 压栈,2成为栈顶元素,并赋值给变量a(内存地址变了)

堆内存

而对象类型是按引用访问的,通过指针访问对象。

指针是一个地址值,类似于基本类型,存储于栈内存中,是变量访问对象的中间媒介。

而对象本身存储在堆内存中,其占用内存大小是可变的,未知的。

举例如下:

var b = { name: ‘Tusi’ }

运行这行代码,会在堆内存中开辟一段内存空间,存储对象{name: 'Tusi'},同时声明一个指针,其值为上述对象的内存地址,指针赋值给引用变量b,意味着b引用了上述对象。

对象可以新增或删除属性,所以说对象类型占用的内存大小一般是未知的。

b.age = 18; // 对象新增了age属性

那么,按引用访问是什么意思呢?

我的理解是:对引用变量进行对象操作,其本质上改变的是引用变量所指向的堆内存地址中的对象本身。

这就意味着,如果有两个或两个以上的引用变量指向同一个对象,那么对其中一个引用变量的对象操作,会影响指向该对象的其他引用变量。

var b = { name: ‘Tusi’ }; // 创建对象,变量b指向该对象

var c = b; // 声明变量c,指向与b一致

b.age = 18; // 通过变量b修改对象

// 产生副作用,c受到影响

console.log©; // {name: “Tusi”, age: 18}

考虑到对象操作的副作用,我们会在业务代码中经常使用深拷贝来规避这个问题。

数据类型的判断

==========================================================================

判断数据类型是非常重要的基础设施之一,那么如何判断数据类型呢?请接着往下看。

typeof


javascript本身提供了typeof运算符,可以辅助我们判断数据类型。

typeof操作符返回一个字符串,表示未经计算的操作数的类型。

typeof的运算结果如下,引用自MDN typeof

| 数据类型 | 运算结果 |

| — | — |

| Undefined | “undefined” |

| Null | “object” |

| Boolean | “boolean” |

| Number | “number” |

| String | “string” |

| Symbol | “symbol” |

| Function | “function” |

| 其他对象 | “object” |

| 宿主对象(由JS环境提供,如Nodejs有global,浏览器有window) | 取决于具体实现 |

可以看到,typeof能帮我们判断出大部分的数据类型,但是要注意的是:

  1. typeof null的结果也是"object"

  2. 对象的种类很多,typeof得到的结果无法判断出数组,普通对象,其他特殊对象

那么如何准确地知道一个变量的数据类型呢?

结合instanceof


instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

利用instanceof,我们可以判断一个对象是不是某个构造函数的实例。那么结合typeof,我们可以封装一个基本的判断数据类型的函数。

基本思想是:首先看typeof是不是返回"object",如果不是,说明是普通数据类型,那么直接返回typeof运算结果即可;如果是,则需要先把null这个坑货摘出来,然后依次判断其他对象类型。

function getType(val) {

const type = typeof val;

if (type === ‘object’) {

if (val === null) {

// null不是对象,所以不能用instanceof判断

return ‘null’

} else if (val instanceof Array) {

return ‘array’

} else if (val instanceof Date) {

return ‘date’

} else if (// 其他对象的instanceof判断) {

return ‘xxx’

} else if (val instanceof Object) {

// 所有对象都是Object的实例,所以放最后

return ‘object’

}

} else {

return type

}

}

// 测试下

getType(Symbol(1)) // “symbol”

getType(null) // “null”

getType(new Date()) // “date”

getType([1, 2, 3]) // “array”

getType({}) // “object”

但是,要把常用的对象类型都列举出来也是有点麻烦的,所以也不算一个优雅的方法。

终极神器toString


有没有终极解决方案?当然是有的。但是,不是标题中的toString,而是Object.prototype.toString。用上它,不仅上面的数据类型都能被判断出来,而且也可以判断ES6引入的一些新的对象类型,比如Map, Set等。

// 利用了Object.prototype.toString和正则表达式的捕获组

function getType(val) {

return Object.prototype.toString.call(val).replace(/[object\s(\w+)]/, ‘$1’).toLowerCase();

}

getType(new Map()) // “map”

getType(new Set()) // “set”

getType(new Promise((resolve, reject) => {})) // “promise”

为什么普通的调用toString不能判断数据类型,而Object.prototype.toString可以呢?

因为Object是基类,而各个派生类,如DateArray等在继承Object的时候,一般都重写(overwrite)了toString方法,用以表达自身业务,从而失去了判断类型的能力。

装箱和拆箱

========================================================================

首先解释一下什么是装箱和拆箱,把原始类型转换为对应的对象类型的操作称为装箱,反之是拆箱。

装箱


我们知道,只有对象才可以拥有属性和方法,但是我们在使用一些基本类型数据的时候,却可以直接调用它们的一些属性或方法,这是怎么回事呢?

var a = 1;

a.toFixed(2); // “1.00”

var b = ‘I love study’;

b.length; // 12

b.substring(2, 6); // “love”

其实在读取一些基本类型数据的属性或方法时,javascript会创建临时对象(也称为“包装对象”),通过这个临时对象来读取属性或方法。以上代码等价于:

var a = 1;

var aObj = new Number(a);

aObj.toFixed(2); // “1.00”

var b = ‘I love study’;

var bObj1 = new String(b);

bObj1.length; // 12

var bObj2 = new String(b);

bObj2.substring(2, 6); // “love”

临时对象是只读的,可以理解为它们在发生读操作后就销毁了,所以不能给它们定义新的属性,也不能修改它们现有的属性。

var c = ‘123’;

小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img
img
img
img

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频

如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注:前端)
img

专业技能

一般来说,面试官会根据你的简历内容去提问,但是技术基础还有需要自己去准备分类,形成自己的知识体系的。简单列一下我自己遇到的一些题

最近得空把之前遇到的面试题做了一个整理,包括我本人自己去面试遇到的,还有其他人员去面试遇到的,还有网上刷到的,我都统一的整理了一下,希望对大家有用。

其中包含HTML、CSS、JavaScript、服务端与网络、Vue、浏览器等等

由于文章篇幅有限,仅展示部分内容

[外链图片转存中…(img-Qgzw2EFq-1710823982759)]

专业技能

一般来说,面试官会根据你的简历内容去提问,但是技术基础还有需要自己去准备分类,形成自己的知识体系的。简单列一下我自己遇到的一些题

最近得空把之前遇到的面试题做了一个整理,包括我本人自己去面试遇到的,还有其他人员去面试遇到的,还有网上刷到的,我都统一的整理了一下,希望对大家有用。

其中包含HTML、CSS、JavaScript、服务端与网络、Vue、浏览器等等

由于文章篇幅有限,仅展示部分内容

  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值