JavaScript面试题整理(二)

2023-09-20 20:18:39

数据类型篇

13、其他值到字符串的转换规则?

  • Null和Undefined类型,null转换为‘null’,undefined转换为‘undefined’
  • Boolean类型,true转换为‘true’,false转换为‘false’
  • Number类型的值直接转换,不过那些极小和极大的数字会使用指数形式
  • Symbol类型的值直接转换,但是只允许显式强制类型转换,使用隐式强制类型转换会产生错误
  • 对普通对象来说,除非自行定义toString()方法,否则会调用toString()(Object.prototype.toString())来返回内部属性[[Class]]的值,如‘[object Object]’。如果对象有自己的toSting()方法,字符串化时就会调用该方法并使用其返回值。

14、其他值到数字值的转换规则?

  • Undefined类型的值转换为NaN

  • Null类型的值转换为0

  • Boolean类型的值,true转换为1,false转换为0

  • String类型的值转换如同使用Number()函数进行转换,如果包含非数字值则转换为NaN,空字符串为0

  •  Symbol类型的值不能转换为数字,会报错

  • 对象(包含数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。

为了将值转换为相应的基本类型值,抽象操作ToPrimitive会首先(通过内部操作DefaultValue)J检查该值是否有valueOf()方法。如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用toString()的返回值(如果存在)来进行强制类型转换。

如果valueOf()和toString()均布返回基本类型值,会产生TypeError错误。

15、JS字符串转数字的方法

通过函数parseInt(t),可以解析一个字符串,并返回一个整数,语法为parseInt(tsring,radix)

string:被解析的字符串

radix:表示要解析的数字的基数,默认是十进制,如果radix<2或者>36,则返回NaN

16、其他值到布尔类型的值的转换规则?

以下这些是假值:

  • undefined
  • null
  • false
  • +0、-0、NaN
  • ''、""

假值的布尔强制类型转换结果都为false,从逻辑上说,假值列表以外的都应该是真值。

17、|| 和&& 操作符的返回值?

|| 和 && 首先会对第一个操作数执行条件判断,如果其不是布尔值就先强制转换为布尔类型,然后再执行条件判断。

  • 对于||来说,如果条件判断结果为true就返回第一个操作数的值,如果为false就返回第二个操作数的值
  • &&则相反,如果条件判断结果为true就返回第二个操作数的值,如果为false就返回第一个操作数的值

|| 和 &&返回它们其中一个操作数的值,而非条件判断的结果 

18、Object.is()与比较操作符'==='、‘==’的区别?

‘==’:不全相等,只比较数据,不比较类型,如果两边的类型不一致,则会进行强制类型转换后再进行比较

‘====’:全等,既要比较数据,也比较数据类型,如果两边的类型不一致时,不会做强制类型转换,直接返回false

(1)==主要存在:强制转换成number,null==undefined

" " == 0 //true
"0" == 0 //true
" " != '0' //true
123 == '123' //true
null == undefined //true

(2)Object.is():一般情况下和三等好的判断相同,它处理了一些特殊的情况,比如-0和+0不再相等,两个NaN是相等的

主要的区别就是 +0  != -0  而 NaN==NaN

19、什么时候JavaScript中的包装类型?

在JavaScript中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性和方法时JavaScript会在后台隐式地将基本类型的值转换为对象,例如:

const a = 'abc';

a.length; //3

a.toUpperCase(); //ABC

在访问‘abc’.length时,JavaScript将‘abc’在后台转换成String('abc'),然后再访问其length属性。

JavaScript也可以使用Object函数显式地将基本类型转换为包装类型:

let a = 'abc'

Object(a)  //String{'abc'} 

也可以使用valueOf方法将包装类型倒转成基本类型:

let a = 'abc'

let b = Object(a)

let c = b.valueOf() //abc 

看看如下代码会打印出什么:

let a = new Boolean(false);
if(!a){
    console.log('Oops');
}

 答案是什么都不会打印出来,因为虽然包裹的基本类型是false,但是false被包裹成包装类型后就成了对象,所以其非值为false,所以循环体中的内容不会运行。

20、JavaScript中如何进行隐式类型转换?

首先看ToPrimitive方法,这是JavaScript中每个值隐含的自带的方法,用来将值(无论是基本类型值还是对象)转换为基本类型值。如果值为基本类型,则直接方法会值本身;如果值为对象,看起来就如下所示:

ToPrimitive(obj,type)

type的值为number或者string

(1)当type为number时规则如下:

  • 调用obj的valueOf方法,如果为原始值,则返回,否则下一步
  • 调用obj的toString方法,后续同上
  • 抛出TypeError异常

(2)当type为string时规则如下:

  • 调用obj的toString方法,如果为原始值,则返回,否则下一步
  • 调用obj的valueOf方法,后续同上
  • 抛出TypeError异常 

可以看出两者的主要区别在于调用toString和valueOf的先后顺序。默认情况下:

  • 如果对象为Date对象,则type默认为string
  • 其他情况下,type默认为number

总结上面的规则,对于Date以外的对象,转换为基本类型的大概规则可以概括为一个函数:

let objToNumber = value => Number(valueOf().toString())

objToNumber([]) === 0

objToNumber({}) === NaN

而JavaScript中的隐式类型转换主要发生在+、-、*、/以及==、>、<这些运算符之间。而这些运算符只能操作基本类型值,所以在进行这些运算前的第一步就是将两边的值用ToPrimitive转换成基本类型,再进行操作。

一下是基本类型的值在不同操作符的情况下隐式转换的规则(对于对象,其会被ToPrimitive转换成基本类型,所以最终还是要应用基本类型转换规则)

1.+操作符  

+操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。

1+'23' //'123'

1+false //1

1+Symbol() //  Cannot convert a Symbol value to a number

'1'+false //'1false'

false+true // 1

2.-、*、\操作符

NaN也是一个数字

1*‘23’   //23

1*false //0

1/'aa  //NaN 

3.==操作符

操作符两边的值都尽量转成number

3 == true //false  3转为number为3,true转为number为1

‘0’ == false //true  ‘0’转为number为0 false转为number为0 

‘0’ == 0 //true  ‘0’转为number为0

4.>和<比较符

如果两边都是字符串,则会比较字符顺序

 'ca'<'bd'  //false

'a' < 'b' //true

其他情况下,转换为数字再比较:

'12' < 13 //true

false > -1 //true 

以上都是基本类型的隐式转换,而对象会被ToPrimitive转换为基本类型再进行转换:

let a = {}

a > 2 //false 

对比过程如下:

a.valueOf()  //{}  ToPrimitive默认type为number,所以先valueOf,结果还是个对象

a.toString() // '[object Object]'

Number(a.toString())  //NaN  根据上面<和>操作符的规则,要转换成数字

NaN > 2  //false   得出比较结果 

 再或者

let a = {name:'Jack'}

let b = {age:18}

a+b  //"[object Object][object Object]"

 运算过程如下:
a.valueOf() // {},上⾯提到过,ToPrimitive默认type为number,所以先
valueOf,结果还是个对象,下⼀步
a.toString() // "[object Object]"
b.valueOf() // 同理
b.toString() // "[object Object]"
a + b // "[object Object][object Object]"

21、+操作符什么时候用于字符串的拼接?

根据ES5规范,如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+将进行拼接操作。如果其中一个操作数是对象(包括数组),则首先对其调用ToPrimitive抽象操作,该抽象操作再调用[[DefaultValue]],以数字作为上下文。如果不能转换为字符串,则会将其转换为数字类型来进行计算。

简单来说就是,如果+的其中一个操作数是字符串(或者通过以上步骤最终得到了字符串),则执行字符串拼接,否则就执行数字加法。

那么对于除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转为数字。

22、为什么会有BigInt的提案?

JavaScript中Number.MAX_SAFE_INTEGER表示最大安全数字,计算结果是9007199254740991,即在这个数范围内不会出现精度丢失(小数除外)。但是一旦超过这个范围,JavaScript就会出现计算不准确的情况,这在大数计算的时候,不得不依靠一些第三方库进行解决,因此官方提出了BigInt来解决此问题。

23、object.assign和扩展运算法是深拷贝还是浅拷贝,两者有什么区别?

扩展运算符:

let outObj = {
    inObj:{a:1,b:2}
}
let newObj = {...outObj}
newObj.inObj.a = 2
console.log(outObj);  //{ inObj: { a: 2, b: 2 } }

Object.assign()

let outObj = {
    inObj:{a:1,b:2}
}
let newObj = Object.assign({},outObj)
newObj.inObj.a = 2
console.log(outObj);  //{ inObj: { a: 2, b: 2 } }

可以看出,两个都是浅拷贝。

  • Object.assign()方法接收的第一个参数作为目标对象,后面的所有参数作为源对象。然后把所有的源对象合并到目标对象中。它会修改了一个对象,因此会触发ES6 setter。
  • 扩展操作符(...)使用它时,数组或对象中的每一个值都会被拷贝到一个新的数组或对象中。它不复制继承的属性或类的属性,但是它会复制ES6的symbols属性。

更多推荐

【数据结构】平衡二叉搜索树(AVL树)——AVL树的概念和介绍、AVL树的简单实现、AVL树的增删查改

文章目录平衡二叉搜索树(AVL树)1.AVL树的概念和介绍2.AVL树的简单实现2.1AVL树的插入2.2AVL树的旋转2.2.1左旋2.2.2右旋2.2.3右左双旋2.2.4左右双旋全部源码平衡二叉搜索树(AVL树)为什么要引入平衡二叉搜索树?在之前我们学习了二叉搜索树,二叉搜索树的结构类似于一个倒置的树,而左子树的

GaussDB数据库SQL系列-子查询

目录一、前言二、GaussDBSQL子查询表达式1、EXISTS/NOTEXISTS2、IN/NOTIN3、ANY/SOME4、ALL三、GaussDBSQL子查询实验示例1、创建实验表2、EXISTS/NOTEXISTS示例3、IN/NOTIN示例4、ANY/SOME示例5、ALL示例四、注意事项及建议五、小结一、前

新装机电脑网速特别慢

老主机最近有些问题,我一直没能解决,也用了5年了,索性出给闲鱼二道贩子,又自己新配置了一台主机。具体表现为:主机插网线后,跟之前主机比,浏览网页或者下载资源速度特别慢,打开百度浏览器都要转上一会,不管下载什么资源,下载速度最快只有100-200kb,让我梦回05年,重新体验了一把当年的感觉,实在抓狂。主板带有WIFI功

3D WEB引擎HOOPS Commuicator助力Naval Architect Jumpstart快速启动船舶信息建模平台开发

行业:造船业挑战:新公司希望将创新的船舶信息建模产品推向市场-基于浏览器的产品需要支持高级可视化和强大的数据转换,以处理大型、复杂的造船项目-小型开发团队的任务是雄心勃勃的平台发布计划。解决方案:TechSoft3D提供领先的SDK,可加速强大的工程Web应用程序的开发。结果:利用第三方组件进行3DWeb轻量化、数据转

负载均衡中间件---Nginx

一.nginx的好处学习Nginx对于一个全栈开发者来说是非常有价值的,下面是一些学习Nginx的原因和好处:反向代理和负载均衡:Nginx是一个高性能的反向代理服务器,可以用于将客户端请求转发给多个后端服务器,实现负载均衡。学习Nginx可以让您了解如何配置和管理反向代理和负载均衡,以提高应用程序的性能和可靠性。静态

layui框架学习(45: 工具集模块)

layui的工具集模块util支持固定条、倒计时等组件,同时提供辅助函数处理时间数据、字符转义、批量事件处理等操作。util模块中的fixbar函数支持设置固定条(2.7版本的帮助文档中叫固定块),是指固定在页面一侧的工具条元素,不随页面滚动条滚动,默认在页面右下角位置。fixbar函数的原型为util.fixbar(

Docker vs. Podman: 选择容器技术的智慧之选

嗨,各位亲爱的程序员小伙伴们!当我们步入容器技术的世界,往往会在众多选择中迷茫。两个备受瞩目的容器工具,Docker和Podman,都在业界掀起了一股风潮。今天,我将带你深入探索,为什么在Docker和Podman之间做出选择,以及如何根据自身需求来做出明智的决策。就让我们一同踏上这个容器之旅吧!容器技术简介:为何容器

初识Docker

文章目录Docker安装Docker简介1.什么是虚拟化、容器化?2.为什么需要虚拟化、容器化?3.虚拟化的实现方式主机虚拟化的实现方式容器虚拟化实现4.虚拟机和Docker的区别Docker安装基于Centos7进行安装1.确认系统版本和CPU架构,Centos7的x86_64架构#cat/etc/*release*

大数据之Hive(三)

分区表概念和常用操作将一个大表的数据按照业务需要分散存储到多个目录,每个目录称为该表的一个分区。一般来说是按照日期来作为分区的标准。在查询时可以通过where子句来选择查询所需要的分区,这样查询效率会提高很多。①创建分区表hive(default)>createtabledept_partition(deptnoint

MySQL学习系列(4)-每天学习10个知识

目录1.InnoDB和MyISAM2.SQL调优3.数据一致性问题的解决4.MySQL的存储引擎5.MySQL的内存使用问题6.索引比全表扫描慢的情况7.行级锁和表级锁8.MySQL的复制功能9.数据库性能测试10.数据库管理和优化👍点赞,你的认可是我创作的动力!⭐️收藏,你的青睐是我努力的方向!✏️评论,你的意见是

2023年的深度学习入门指南(27) - CUDA的汇编语言PTX与SASS

通过前面的学习,我们了解了在深度学习和大模型中,GPU的广泛应用。可以说,不用说没有GPU,就算是没有大显存和足够先进的架构,也没法开发大模型。有的同学表示GPU很神秘,不知道它是怎么工作的。其实,GPU的工作原理和CPU是一样的,都是通过指令来控制硬件的。只不过,GPU的指令集和CPU不一样。下面我们就走进GPU的内

热文推荐