前端面试题4(Javascript)
type
status
date
slug
summary
tags
category
icon
password
一、基础知识
1. JavaScript 的基本数据类型有哪些?请简要描述每种类型的特点。
回答:
js 的基本数据类型有:
Number
、String
、Boolean
、Null
、Undefined
、Symbol (ES6)
、Bigint (ES2020)
。Number
:数字类型,包括整数和浮点数,可以表示整数和浮点数,最大值为Number.MAX_VALUE
,最小值为Number.MIN_VALUE
,可以使用Number.isInteger()
方法判断是否为整数。
String
:字符串类型,用于表示文本数据,可以使用单引号、双引号、反引号表示字符串,可以使用+
运算符进行字符串拼接。
Boolean
:布尔类型,用于表示逻辑值,只有两个值:true
和false
。
Null
:空值类型,表示一个空对象指针,使用null
表示。
Undefined
:未定义类型,表示一个未定义的值,使用undefined
表示。
Symbol
:符号类型,表示独一无二的值,用于对象属性的唯一标识符,使用Symbol()
函数创建。
Bigint
:大整数类型,用于表示任意精度的整数,可以表示任意长度的整数,使用BigInt()
函数创建。
2. 如何判断数据类型。
回答:
JavaScript 中可以使用
typeof
运算符和instanceof
运算符来判断数据类型。typeof
运算符:typeof
运算符可以返回一个值的数据类型,返回值为字符串类型。
可以看出,
typeof
运算符可以判断基本数据类型,但对于引用类型的数据,除了函数类型,都会返回"object"
。instanceof
运算符:instanceof
运算符可以判断一个对象是否是某个类型的实例,返回值为布尔类型。
所以 instanceof 运算符可以判断引用类型的数据。但是 instanceof 运算符有一个问题,就是无法判断基本数据类型。
Object.prototype.toString
方法:Object.prototype.toString
方法可以返回一个对象的字符串表示,可以用来判断数据类型。
3. 解释 JavaScript 中的原始类型和引用类型的区别。
回答:
JavaScript 中的数据类型分为原始类型和引用类型两种。原始类型的数据是直接存储在栈内存中的,引用类型的数据是存储在堆内存中的,栈内存中存储的是变量的标识符和指向堆内存中实际数据的指针。
4. 什么是闭包?请举例说明其应用场景。
回答:
闭包是指函数可以记住定义时的作用域,即使函数在外部词法环境调用,仍然可以访问定义时的作用域。
应用场所:
- 模块化开发:使用闭包可以实现模块化开发,将变量和方法封装在闭包中,避免全局变量污染。(私有变量同理)
- 函数工厂:使用闭包可以实现函数工厂,动态生成函数。
- 回调函数和事件处理:使用闭包可以实现回调函数和事件处理。
- 惰性加载:使用闭包可以实现惰性加载,延迟加载资源。
5. 请解释 JavaScript 中的事件冒泡和事件捕获机制。
回答:
事件冒泡和事件捕获决定了事件从触发元素向父元素传播的顺序。
- 事件冒泡:事件从触发元素开始向父元素传播,直到根元素。即先触发子元素的事件,再触发父元素的事件。
- 事件捕获:事件从根元素开始向触发元素传播,直到触发元素。即先触发根元素的事件,再触发子元素的事件。
你可以通过
addEventListener()
方法的第三个参数来控制事件的传播方式,true
表示事件捕获,false
表示事件冒泡。6. 请解释 JavaScript 中的 this 关键字。
回答:
this
关键字是 JavaScript 中的一个特殊关键字,它指向当前函数的执行上下文,取决于函数的调用方式。- 全局环境:在全局环境中,
this
指向全局对象window
。
- 函数调用:在函数中,
this
指向调用函数的对象。
- 对象方法:在对象方法中,
this
指向调用方法的对象。
- 构造函数:在构造函数中,
this
指向实例对象。
- 箭头函数:在箭头函数中,
this
指向定义时的词法环境,就是外部函数的this
。
7. 请解释 JavaScript 中的原型继承和原型链。
回答:
JavaScript 中的原型链机制是对象继承的一种方式。每个 JavaScript 对象都有一个内部属性
[[Prototype]]
,指向它的原型对象。通过原型链,JavaScript 对象可以访问其原型对象上的属性和方法。具体来说,当你访问对象的某个属性或方法时,JavaScript 会按照以下步骤查找:
- 首先检查对象本身是否拥有该属性或方法。
- 如果没有,JavaScript 会查找对象的原型(即
[[Prototype]]
),看看原型是否有这个属性或方法。
- 如果原型没有,JavaScript 会继续查找原型的原型,这样逐级向上查找,直到找到该属性或方法,或者到达
Object.prototype
,这是原型链的顶端。如果还没有找到,返回undefined
。
例如:
这里,
obj
有一个 name
属性,但没有 toString
方法。toString
方法实际上是从 Object.prototype
上继承来的,因为所有对象最终都继承自 Object.prototype
。原型链的形成:
- 对象
obj
的[[Prototype]]
指向其构造函数Object
的原型。
Object.prototype
是原型链的终点。
8. 请解释 JavaScript 中的继承方式。
回答:
JavaScript 中有多种继承方式,包括原型链继承、构造函数继承、组合继承、寄生组合继承等。
- 原型链继承:通过将子类的原型指向父类的实例来实现继承。
- 构造函数继承:通过在子类构造函数中调用父类构造函数来实现继承。
- 组合继承:通过原型链继承和构造函数继承相结合的方式实现继承。
- 寄生组合继承:通过借用构造函数继承属性,通过原型链继承方法,实现继承。
这 4 种继承的优缺点如下:
- 原型链继承:简单易懂,但存在属性共享的问题。
- 构造函数继承:避免了属性共享的问题,但无法继承原型上的方法。
- 组合继承:结合了原型链继承和构造函数继承的优点,但存在调用两次父类构造函数的问题。
- 寄生组合继承:通过借用构造函数继承属性,通过原型链继承方法,实现继承。
9. 请解释 JavaScript 中的事件循环机制。
回答:
JavaScript 是单线程的,事件循环机制是 JavaScript 实现异步编程的核心机制。事件循环机制包括以下几个部分:
- 调用栈(Call Stack):用于存储函数调用的栈结构。
- 消息队列(Message Queue):用于存储异步任务的队列。
- 事件循环(Event Loop):用于控制消息队列中的任务何时进入调用栈执行。
- 微任务(Microtask):用于存储需要在当前任务执行完后立即执行的任务。
- 宏任务(Macrotask):用于存储需要在当前任务执行完后执行的任务。
事件循环机制的执行过程如下:
- 执行同步任务,将任务压入调用栈中执行。
- 执行完同步任务后,查看微任务队列,将微任务队列中的任务依次压入调用栈中执行。
- 执行完微任务后,查看宏任务队列,将宏任务队列中的任务依次压入调用栈中执行。
- 重复执行上述过程,直到调用栈和消息队列都为空。
上述代码的执行过程如下:
- 执行同步任务,输出 "script start"。
- 执行
setTimeout
,将setTimeout
回调函数压入宏任务队列。
- 执行
Promise.resolve().then()
,将promise1
和promise2
压入微任务队列。
- 执行同步任务,输出 "script end"。
- 执行完同步任务后,查看微任务队列,将
promise1
和promise2
压入调用栈中执行。
- 执行完微任务后,查看宏任务队列,将
setTimeout
回调函数压入调用栈中执行。
10. 请解释 JavaScript 中的事件委托。
回答:
事件委托是指将事件绑定到父元素,通过事件冒泡的机制,让父元素代理子元素触发事件。事件委托的优点是可以减少事件绑定的次数,提高性能。
上述代码中,我们将事件绑定到
ul
元素上,当点击 li
元素时,事件会冒泡到 ul
元素,触发 ul
元素的事件处理函数,从而实现事件委托。11. 请解释 JavaScript 中的异步编程方式,包括回调函数、Promise 和 async/await 的区别。
回答:
JavaScript 中的异步编程方式有多种,包括回调函数、Promise 和 async/await。
- 回调函数:回调函数是异步编程的一种方式,通过将函数作为参数传递给其他函数,实现异步操作。
- Promise:Promise 是异步编程的一种解决方案,用于处理异步操作。
- async/await:async/await 是 Promise 的语法糖,用于处理异步操作。
回调函数、Promise 和 async/await 的区别如下:
- 回调函数:回调函数是异步编程的一种方式,通过将函数作为参数传递给其他函数,实现异步操作。回调函数的缺点是容易出现回调地狱,难以维护。
- Promise:Promise 是异步编程的一种解决方案,用于处理异步操作。Promise 可以解决回调地狱的问题,但是需要链式调用,不够直观。
- async/await:async/await 是 Promise 的语法糖,用于处理异步操作。async/await 可以让异步代码看起来像同步代码,更加直观易懂。
12. 请描述 JavaScript 中的垃圾回收机制。
回答:
JavaScript 中的垃圾回收机制是自动管理内存的机制,用于回收不再使用的内存,防止内存泄漏。
JavaScript 中的垃圾回收机制主要有两种方式:
- 引用计数:引用计数是一种简单的垃圾回收机制,通过引用计数来判断对象是否可回收。当对象的引用计数为 0 时,表示对象不再被引用,可以回收。
- 标记清除:标记清除是一种常用的垃圾回收机制,通过标记对象是否可达来判断对象是否可回收。当对象不再可达时,表示对象不再被引用,可以回收。
初始状态:
对象 | 内容 | 引用变量 |
A | value: 10, next: b | a, c.next |
B | value: 20, next: a | b, d.next, a.next |
C | value: 30, next: a | c, e.next |
D | value: 40, next: b | d |
E | value: 50, next: c | e |
第一阶段:
e = null; c = null; d = null;
- 变量
e
、c
、d
不再指向任何对象,但 a 和 b 仍有效。
- 标记阶段:
- 根对象为
a
、b
(c
、d
、e
为null
)。 - 从
a
标记对象 A,A 的next
指向 B,标记 B。 - 从 B 的
next
回到 A(已标记),无新对象。 - 从
b
标记 B(已标记)。 - 结果:对象 A 和 B 被标记。
- 清除阶段:
- 未被标记的对象 C、D、E 被清除。
- 结果:对象 C、D、E 被清除。
此时,内存中只剩 A 和 B,状态如下:
- A:
{ value: 10, next: B }
- B:
{ value: 20, next: A }
- 由
a
和b
引用。
第二阶段:设置
a = null; b = null;
- 所有变量均为
null
,没有根对象指向任何内存。
- 标记阶段:
- 根对象全为
null
,无对象被标记。
- 清除阶段:
- 所有对象(A 和 B)未标记,全部被回收。
两者优缺点
- 引用计数:简单高效,但无法处理循环引用的情况。
- 标记清除:可以处理循环引用的情况,但需要遍历对象,性能较差。
13. 请解释 JavaScript 中的模块化机制,包括 CommonJS、AMD 和 ES6 模块的区别。
回答:
JavaScript 中的模块化机制是用于组织和管理代码的一种方式,主要包括 CommonJS、AMD 和 ES6 模块。
- CommonJS:CommonJS 是 Node.js 中使用的模块化规范,通过
require
和module.exports
实现模块化。
- AMD:AMD(Asynchronous Module Definition)是一种异步模块定义规范,通过
define
和require
实现模块化。
- ES6 模块:ES6 模块是 ECMAScript 6 中引入的模块化规范,通过
import
和export
实现模块化。
CommonJS、AMD 和 ES6 模块的区别如下:
- CommonJS:同步加载模块,适用于服务器端,不适用于浏览器端。
- AMD:异步加载模块,适用于浏览器端,通过 RequireJS 实现。
- ES6 模块:静态加载模块,适用于浏览器端和服务器端,通过 Babel 转换为 CommonJS 或 AMD。
- CommonJS 和 AMD 是动态加载模块,ES6 模块是静态加载模块。
什么是动态加载模块?什么是静态加载模块?
- 静态模块加载:使用 import 语句在文件顶部加载模块,代码运行前加载,适合总是需要的模块。
- 动态模块加载:使用 require.ensure 或 System.import 方法加载模块,代码运行时加载,适合按需加载的模块。
14. 请解释 JavaScript 中的 call、apply 和 bind 方法的区别,并举例说明。
回答:
JavaScript 中的
call
、apply
和 bind
方法是用于改变函数的 this
指向的方法。call
方法:call
方法用于调用函数,可以改变函数的this
指向,并且可以传递参数列表。
apply
方法:apply
方法用于调用函数,可以改变函数的this
指向,并且可以传递参数数组。
bind
方法:bind
方法用于创建一个新函数,可以改变函数的this
指向,并且可以传递参数列表。
call
、apply
和 bind
方法的区别如下:call
和apply
方法都是立即调用函数,bind
方法是创建一个新函数。
call
和apply
方法的区别在于参数的传递方式,call
方法是传递参数列表,apply
方法是传递参数数组。
call
和apply
方法都是改变函数的this
指向,bind
方法是创建一个新函数,不会改变原函数的this
指向。
15. 请解释 JavaScript 中的深拷贝和浅拷贝。
回答:
JavaScript 中的深拷贝和浅拷贝是用于复制对象的两种方式。
- 浅拷贝:浅拷贝是指复制对象的第一层属性,如果属性值是对象,只复制对象的引用。
- 深拷贝:深拷贝是指复制对象的所有属性,包括对象的嵌套属性。
深拷贝和浅拷贝的区别如下:
- 浅拷贝只复制对象的第一层属性,如果属性值是对象,只复制对象的引用。
- 深拷贝复制对象的所有属性,包括对象的嵌套属性。
16. 请解释 JavaScript 中的节流和防抖。
回答:
节流和防抖是用于控制函数执行频率的两种方式。
- 节流:节流是指控制函数的执行频率,让函数在一定时间间隔内只执行一次。
- 防抖:防抖是指控制函数的执行频率,让函数在一定时间间隔内不再执行,直到过了时间间隔才执行。
节流和防抖的区别如下:
- 节流是让函数在一定时间间隔内只执行一次,防抖是让函数在一定时间间隔内不再执行,直到过了时间间隔才执行。
- 节流是控制函数的执行频率,防抖是控制函数的执行时机。
17. 请解释 JavaScript 中的柯里化函数。
回答:
柯里化函数是指将接受多个参数的函数转换为接受一个参数的函数,并返回接受余下参数的函数的技术。
柯里化函数的优点是可以将多个参数的函数转换为接受一个参数的函数,方便函数的组合和复用。
18. 请描述 JavaScript 中的内存泄漏的常见原因,并说明如何避免。
回答:
JavaScript 中的内存泄漏是指不再使用的内存没有被及时释放,导致内存占用过高的问题。
常见的内存泄漏原因如下:
- 闭包:闭包中的变量没有被释放,导致内存泄漏。
- 全局变量:全局变量没有被释放,导致内存泄漏。
- 定时器:定时器没有被清除,导致内存泄漏。
- DOM 引用:DOM 元素没有被释放,导致内存泄漏。
- 事件绑定:事件绑定没有被解除,导致内存泄漏。
避免内存泄漏的方法如下:
- 及时清除定时器:使用
clearInterval
、clearTimeout
清除定时器。
- 及时解除事件绑定:使用
removeEventListener
解除事件绑定。
- 及时释放 DOM 引用:将 DOM 引用设置为
null
。
- 避免使用全局变量:使用模块化开发,避免使用全局变量。
- 避免使用闭包:避免在循环中使用闭包。
19. 请解释 JavaScript 中的 Promise 的原理,并举例说明其使用方法。
回答:
Promise 是 JavaScript 中用于处理异步操作的对象,用于解决回调地狱的问题。
Promise 的原理是通过
Promise
构造函数创建一个 Promise 对象,Promise 对象有三种状态:pending
、fulfilled
、rejected
。当异步操作执行成功时,Promise 对象的状态变为 fulfilled
,并执行 then
方法的回调函数;当异步操作执行失败时,Promise 对象的状态变为 rejected
,并执行 catch
方法的回调函数。上述代码中,
fetchData
函数返回一个 Promise 对象,当异步操作执行成功时,调用 resolve
方法,将 Promise 对象的状态变为 fulfilled
,并执行 then
方法的回调函数;当异步操作执行失败时,调用 reject
方法,将 Promise 对象的状态变为 rejected
,并执行 catch
方法的回调函数。20. 请解释 JavaScript 中的 Generator 函数的原理,并举例说明其使用方法。
回答:
Generator 函数是 JavaScript 中用于生成迭代器的函数,通过
function*
关键字定义 Generator 函数,通过 yield
关键字返回迭代器的值。上述代码中,
generator
函数返回一个 Generator 对象,通过 next
方法依次返回迭代器的值,当迭代器的值返回 undefined
时,表示迭代器结束。21. 请解释 JavaScript 中的 Proxy 对象的原理,并举例说明其使用方法。
回答:
Proxy 对象是 JavaScript 中用于创建代理对象的对象,通过
Proxy
构造函数创建 Proxy 对象,可以拦截对象的操作。上述代码中,
Proxy
构造函数创建一个代理对象,通过 get
方法拦截对象的读取操作,通过 set
方法拦截对象的写入操作。22. 请解释 JavaScript 中的 Reflect 对象的原理,并举例说明其使用方法。
回答:
Reflect 对象是 JavaScript 中用于操作对象的对象,通过
Reflect
对象可以调用对象的方法。上述代码中,
Reflect
对象的 get
方法用于获取对象的属性值,set
方法用于设置对象的属性值。其他还有很多方法,比如:
Reflect.apply(target, thisArg, args)
:调用函数。
Reflect.construct(target, args)
:创建实例。
Reflect.defineProperty(target, key, descriptor)
:定义属性。
Reflect.deleteProperty(target, key)
:删除属性。
Reflect.has(target, key)
:判断属性是否存在。
Reflect.ownKeys(target)
:获取对象的所有属性。
Reflect.setPrototypeOf(target, prototype)
:设置对象的原型。
Reflect.getPrototypeOf(target)
:获取对象的原型。
Reflect.isExtensible(target)
:判断对象是否可扩展。
23. 请解释 JavaScript 中的 Map 对象和 Set 对象的原理,并举例说明其使用方法。
回答:
Map 对象是 JavaScript 中用于存储键值对的对象,通过
Map
构造函数创建 Map 对象,可以存储任意类型的键和值。Set 对象是 JavaScript 中用于存储唯一值的对象,通过
Set
构造函数创建 Set 对象,可以存储任意类型的值。区别:
Map
和Set
都是数据结构,查找效率比Array
高,并且都有delete
、has
方法。
Map
结构类似于二维数组,存储键值对 (key: value
)。
Set
结构类似伪数组(更像对象),每个值都是唯一的。
Map
的key
不能重复,Set
的value
不能重复。
Map
使用get
获取数据,Set
需要遍历或转换为数组访问。
Map
添加数据用set()
方法,Set
用add()
方法。
24. 请解释 JavaScript 中的 WeakMap 对象和 WeakSet 对象的原理,并举例说明其使用方法。
回答:
WeakMap 对象是 JavaScript 中用于存储键值对的对象,通过
WeakMap
构造函数创建 WeakMap 对象,键是弱引用,键被垃圾回收时,值也会被垃圾回收。WeakSet 对象是 JavaScript 中用于存储唯一值的对象,通过
WeakSet
构造函数创建 WeakSet 对象,值是弱引用,值被垃圾回收时,值也会被垃圾回收。区别:
- 主要用于避免
Map
和Set
的内存泄漏问题。
WeakMap
的key
和WeakSet
的value
只能是对象。
WeakMap
和WeakSet
使用 弱引用,当对象被null
赋值时,垃圾回收机制会自动回收该对象。
25. 请解释 JavaScript 中的 setTimeout 和 setInterval 的区别,并说明如何清除它们。
回答:
setTimeout
和 setInterval
都是 JavaScript 中用于定时执行函数的方法。setTimeout
:setTimeout
方法用于在一定时间后执行函数,只执行一次。
setInterval
:setInterval
方法用于每隔一定时间执行函数,重复执行。
区别:
setTimeout
只执行一次,setInterval
重复执行。
setTimeout
的时间间隔是从函数执行完开始计时,setInterval
的时间间隔是从函数执行完开始计时。
清除方法:
setTimeout
:使用clearTimeout
方法清除定时器。
setInterval
:使用clearInterval
方法清除定时器。
26. 请描述 JavaScript 中的 eval 函数的作用和使用注意事项。
回答:
eval
函数是 JavaScript 中的一个全局函数,用于执行字符串中的 JavaScript 代码。eval
函数的作用是将字符串中的 JavaScript 代码执行,可以动态执行代码。使用注意事项:
eval
函数会将字符串中的 JavaScript 代码当作当前作用域执行,可能会污染当前作用域。
eval
函数会将字符串中的 JavaScript 代码当作代码执行,可能会存在安全风险。
eval
函数会将字符串中的 JavaScript 代码当作代码执行,可能会影响性能。
27. 请描述 JavaScript 中的 new 操作符的作用和实现原理。
回答:
new
操作符是 JavaScript 中用于创建对象的操作符,通过 new
操作符可以创建一个对象实例。new
操作符的实现原理如下:- 创建一个空对象。
- 将空对象的原型指向构造函数的原型。
- 将构造函数的
this
指向空对象。
- 执行构造函数。
- 返回空对象。
28. 请描述 JavaScript 中的 instanceof 运算符的原理。
回答:
instanceof
运算符是 JavaScript 中用于判断对象的原型链是否包含构造函数的原型。instanceof
运算符的原理如下:- 获取对象的原型。
- 获取构造函数的原型。
- 判断对象的原型是否等于构造函数的原型,如果是返回
true
,否则返回false
。
- 如果对象的原型链中有构造函数的原型,返回
true
,否则返回false
。
29. 如何判断两个对象相等。
回答:
JavaScript 中判断两个对象相等有多种方式,包括:
==
运算符:判断两个对象的值是否相等。
===
运算符:判断两个对象的值和类型是否相等。
JSON.stringify
方法:将对象转换为字符串,再比较字符串是否相等。
Object.is
方法:判断两个对象是否严格相等。
lodash
库:使用lodash
库的isEqual
方法判断两个对象是否相等。
30. ===
和 ==
的区别
回答:
===
和 ==
都是 JavaScript 中的比较运算符,用于比较两个值是否相等。===
运算符:严格相等运算符,比较两个值的类型和值是否相等。
==
运算符:相等运算符,比较两个值的值是否相等,会进行类型转换。
区别:
===
运算符比较两个值的类型和值是否相等,不会进行类型转换。
==
运算符比较两个值的值是否相等,会进行类型转换。
31. 类型转换
回答:
转 Boolean:
可以使用
Boolean()
函数将值转换为布尔值。转换规则如下:数据类型 | 转换为 true 的值 | 转换为 false 的值 |
Boolean | true | false |
String | 非空字符串 | 空字符串 |
Number | 非零数字 | 0 和 NaN |
Object | 任意对象 | null |
Undefined | ㅤ | undefined |
转 Number:
有 3 个函数可以将非数值转化为
Number
类型:Number()
、parseInt()
、parseFloat()
。Number()
:可以用于任何数据类型,规则如下:undefined
:转换为NaN
。null
:转换为0
。true
和false
:分别转换为1
和0
。- 字符串:遵循以下规则:
- 字符串中只包含数字(包括前面带正负号的情况):转换为十进制数值。因此,
Number('42')
、Number(042)
和Number('42.0')
都返回42
。 - 字符串中包含有效的浮点格式:转换为浮点数值。(同样会忽略前面的
0
) - 字符串中包含有效的十六进制格式:转换为十六进制整数。
- 字符串中包含字母:转换为
NaN
。 - 空字符串:转换为
0
。 - 对象:先调用
valueOf()
方法,如果返回的是原始值,则按照前面的规则转换;如果valueOf()
方法返回的还是对象,则调用toString()
方法,然后再次按照前面的规则转换。
parseInt()
:用于将字符串转换为整数。它会忽略字符串前面的空格,直至找到第一个非空格字符。如果第一个字符不是数字字符或者负号,parseInt()
会返回NaN
。否则,它会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个非数字字符。例如,parseInt('1234blue')
会返回1234
,而parseInt('0xA')
会返回10
。
parseFloat()
:用于将字符串转换为浮点数。它会忽略字符串前面的空格,直至找到第一个非空格字符。如果第一个字符不是数字字符、负号或者小数点,parseFloat()
会返回NaN
。否则,它会继续解析第二个字符,直到解析完所有后续字符或者遇到了一个无效的浮点数值字符。例如,parseFloat('1234blue')
会返回1234
,而parseFloat('0xA')
会返回0
。
转 String:
有两种方式可以将值转换为字符串:
String()
和 toString()
。toString()
:此方法用于数值、布尔值、对象、字符串,null
和undefined
没有toString()
方法。也可以接受底数参数,用于指定数值的进制。例如,num.toString(2)
返回二进制字符串,num.toString(8)
返回八进制字符串,num.toString(16)
返回十六进制字符串。
String()
:可以将任何类型的值转换为字符串。转换规则如下:undefined
:转换为"undefined"
。null
:转换为"null"
。true
和false
:分别转换为"true"
和"false"
。- 数字:转换为十进制字符串形式。
- 对象:调用对象的
toString()
方法,然后再根据前面的规则转换。
隐式转化:
在 JavaScript 中,有一些运算符可以将非预期的数据类型转换为数字或字符串。这种转换被称为隐式类型转换。规则如下:
+
:如果其中一个操作数是字符串,则将另一个操作数转换为字符串。否则,两个操作数都转换为数字。
- -、*、/ 和 %:如果其中一个操作数是字符串、布尔值、
null
或undefined
,则将其转换为数字。如果其中一个操作数是对象,则调用valueOf()
方法,然后再根据前面的规则转换。
==
:如果两个操作数类型相同,则直接比较。如果两个操作数类型不同,则尝试将它们转换为相同的类型,然后再比较。转换规则如下:- 如果一个操作数是布尔值,则将其转换为数字。
- 如果一个操作数是字符串,另一个操作数是数字,则将字符串转换为数字。
- 如果一个操作数是对象,另一个操作数不是对象,则调用对象的
valueOf()
方法,然后再根据前面的规则转换。 - 如果一个操作数是
null
,另一个操作数是undefined
,则相等。 - 如果一个操作数是
null
,另一个操作数是非空对象,则不相等。 - 如果一个操作数是
undefined
,另一个操作数是非空对象,则不相等。
Loading...