前端面试题4(Javascript)

type
status
date
slug
summary
tags
category
icon
password

一、基础知识


1. JavaScript 的基本数据类型有哪些?请简要描述每种类型的特点。

回答:
js 的基本数据类型有:NumberStringBooleanNullUndefinedSymbol (ES6)Bigint (ES2020)
  • Number:数字类型,包括整数和浮点数,可以表示整数和浮点数,最大值为Number.MAX_VALUE,最小值为Number.MIN_VALUE,可以使用Number.isInteger()方法判断是否为整数。
  • String:字符串类型,用于表示文本数据,可以使用单引号、双引号、反引号表示字符串,可以使用+运算符进行字符串拼接。
  • Boolean:布尔类型,用于表示逻辑值,只有两个值:truefalse
  • Null:空值类型,表示一个空对象指针,使用null表示。
  • Undefined:未定义类型,表示一个未定义的值,使用undefined表示。
  • Symbol:符号类型,表示独一无二的值,用于对象属性的唯一标识符,使用Symbol()函数创建。
  • Bigint:大整数类型,用于表示任意精度的整数,可以表示任意长度的整数,使用BigInt()函数创建。

2. 如何判断数据类型。

回答:
JavaScript 中可以使用typeof运算符和instanceof运算符来判断数据类型。
  1. typeof运算符:typeof运算符可以返回一个值的数据类型,返回值为字符串类型。
可以看出,typeof运算符可以判断基本数据类型,但对于引用类型的数据,除了函数类型,都会返回"object"
  1. instanceof运算符:instanceof运算符可以判断一个对象是否是某个类型的实例,返回值为布尔类型。
所以 instanceof 运算符可以判断引用类型的数据。但是 instanceof 运算符有一个问题,就是无法判断基本数据类型。
  1. Object.prototype.toString方法:Object.prototype.toString方法可以返回一个对象的字符串表示,可以用来判断数据类型。

3. 解释 JavaScript 中的原始类型和引用类型的区别。

回答:
JavaScript 中的数据类型分为原始类型和引用类型两种。原始类型的数据是直接存储在栈内存中的,引用类型的数据是存储在堆内存中的,栈内存中存储的是变量的标识符和指向堆内存中实际数据的指针。

4. 什么是闭包?请举例说明其应用场景。

回答:
闭包是指函数可以记住定义时的作用域,即使函数在外部词法环境调用,仍然可以访问定义时的作用域。
应用场所:
  1. 模块化开发:使用闭包可以实现模块化开发,将变量和方法封装在闭包中,避免全局变量污染。(私有变量同理)
  1. 函数工厂:使用闭包可以实现函数工厂,动态生成函数。
  1. 回调函数和事件处理:使用闭包可以实现回调函数和事件处理。
  1. 惰性加载:使用闭包可以实现惰性加载,延迟加载资源。

5. 请解释 JavaScript 中的事件冒泡和事件捕获机制。

回答:
事件冒泡和事件捕获决定了事件从触发元素向父元素传播的顺序。
  1. 事件冒泡:事件从触发元素开始向父元素传播,直到根元素。即先触发子元素的事件,再触发父元素的事件。
  1. 事件捕获:事件从根元素开始向触发元素传播,直到触发元素。即先触发根元素的事件,再触发子元素的事件。
你可以通过addEventListener()方法的第三个参数来控制事件的传播方式,true表示事件捕获,false表示事件冒泡。

6. 请解释 JavaScript 中的 this 关键字。

回答:
this关键字是 JavaScript 中的一个特殊关键字,它指向当前函数的执行上下文,取决于函数的调用方式。
  1. 全局环境:在全局环境中,this指向全局对象window
  1. 函数调用:在函数中,this指向调用函数的对象。
  1. 对象方法:在对象方法中,this指向调用方法的对象。
  1. 构造函数:在构造函数中,this指向实例对象。
  1. 箭头函数:在箭头函数中,this指向定义时的词法环境,就是外部函数的this

7. 请解释 JavaScript 中的原型继承和原型链。

回答:
JavaScript 中的原型链机制是对象继承的一种方式。每个 JavaScript 对象都有一个内部属性 [[Prototype]],指向它的原型对象。通过原型链,JavaScript 对象可以访问其原型对象上的属性和方法。
具体来说,当你访问对象的某个属性或方法时,JavaScript 会按照以下步骤查找:
  1. 首先检查对象本身是否拥有该属性或方法。
  1. 如果没有,JavaScript 会查找对象的原型(即 [[Prototype]]),看看原型是否有这个属性或方法。
  1. 如果原型没有,JavaScript 会继续查找原型的原型,这样逐级向上查找,直到找到该属性或方法,或者到达 Object.prototype,这是原型链的顶端。如果还没有找到,返回 undefined
例如:
这里,obj 有一个 name 属性,但没有 toString 方法。toString 方法实际上是从 Object.prototype 上继承来的,因为所有对象最终都继承自 Object.prototype
原型链的形成:
  • 对象 obj[[Prototype]] 指向其构造函数 Object 的原型。
  • Object.prototype 是原型链的终点。

8. 请解释 JavaScript 中的继承方式。

回答:
JavaScript 中有多种继承方式,包括原型链继承、构造函数继承、组合继承、寄生组合继承等。
  1. 原型链继承:通过将子类的原型指向父类的实例来实现继承。
  1. 构造函数继承:通过在子类构造函数中调用父类构造函数来实现继承。
  1. 组合继承:通过原型链继承和构造函数继承相结合的方式实现继承。
  1. 寄生组合继承:通过借用构造函数继承属性,通过原型链继承方法,实现继承。
这 4 种继承的优缺点如下:
  • 原型链继承:简单易懂,但存在属性共享的问题。
  • 构造函数继承:避免了属性共享的问题,但无法继承原型上的方法。
  • 组合继承:结合了原型链继承和构造函数继承的优点,但存在调用两次父类构造函数的问题。
  • 寄生组合继承:通过借用构造函数继承属性,通过原型链继承方法,实现继承。

9. 请解释 JavaScript 中的事件循环机制。

回答:
JavaScript 是单线程的,事件循环机制是 JavaScript 实现异步编程的核心机制。事件循环机制包括以下几个部分:
  1. 调用栈(Call Stack):用于存储函数调用的栈结构。
  1. 消息队列(Message Queue):用于存储异步任务的队列。
  1. 事件循环(Event Loop):用于控制消息队列中的任务何时进入调用栈执行。
  1. 微任务(Microtask):用于存储需要在当前任务执行完后立即执行的任务。
  1. 宏任务(Macrotask):用于存储需要在当前任务执行完后执行的任务。
事件循环机制的执行过程如下:
  1. 执行同步任务,将任务压入调用栈中执行。
  1. 执行完同步任务后,查看微任务队列,将微任务队列中的任务依次压入调用栈中执行。
  1. 执行完微任务后,查看宏任务队列,将宏任务队列中的任务依次压入调用栈中执行。
  1. 重复执行上述过程,直到调用栈和消息队列都为空。
上述代码的执行过程如下:
  1. 执行同步任务,输出 "script start"。
  1. 执行 setTimeout,将 setTimeout 回调函数压入宏任务队列。
  1. 执行 Promise.resolve().then(),将 promise1promise2 压入微任务队列。
  1. 执行同步任务,输出 "script end"。
  1. 执行完同步任务后,查看微任务队列,将 promise1promise2 压入调用栈中执行。
  1. 执行完微任务后,查看宏任务队列,将 setTimeout 回调函数压入调用栈中执行。

10. 请解释 JavaScript 中的事件委托。

回答:
事件委托是指将事件绑定到父元素,通过事件冒泡的机制,让父元素代理子元素触发事件。事件委托的优点是可以减少事件绑定的次数,提高性能。
上述代码中,我们将事件绑定到 ul 元素上,当点击 li 元素时,事件会冒泡到 ul 元素,触发 ul 元素的事件处理函数,从而实现事件委托。

11. 请解释 JavaScript 中的异步编程方式,包括回调函数、Promise 和 async/await 的区别。

回答:
JavaScript 中的异步编程方式有多种,包括回调函数、Promise 和 async/await。
  1. 回调函数:回调函数是异步编程的一种方式,通过将函数作为参数传递给其他函数,实现异步操作。
  1. Promise:Promise 是异步编程的一种解决方案,用于处理异步操作。
  1. async/await:async/await 是 Promise 的语法糖,用于处理异步操作。
回调函数、Promise 和 async/await 的区别如下:
  • 回调函数:回调函数是异步编程的一种方式,通过将函数作为参数传递给其他函数,实现异步操作。回调函数的缺点是容易出现回调地狱,难以维护。
  • Promise:Promise 是异步编程的一种解决方案,用于处理异步操作。Promise 可以解决回调地狱的问题,但是需要链式调用,不够直观。
  • async/await:async/await 是 Promise 的语法糖,用于处理异步操作。async/await 可以让异步代码看起来像同步代码,更加直观易懂。

12. 请描述 JavaScript 中的垃圾回收机制。

回答:
JavaScript 中的垃圾回收机制是自动管理内存的机制,用于回收不再使用的内存,防止内存泄漏。
JavaScript 中的垃圾回收机制主要有两种方式:
  1. 引用计数:引用计数是一种简单的垃圾回收机制,通过引用计数来判断对象是否可回收。当对象的引用计数为 0 时,表示对象不再被引用,可以回收。
  1. 标记清除:标记清除是一种常用的垃圾回收机制,通过标记对象是否可达来判断对象是否可回收。当对象不再可达时,表示对象不再被引用,可以回收。
初始状态:
对象
内容
引用变量
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;
  • 变量 ecd 不再指向任何对象,但 a 和 b 仍有效。
  • 标记阶段:
    • 根对象为 abcdenull)。
    • 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 }
  • ab 引用。
第二阶段:设置 a = null; b = null;
  • 所有变量均为 null,没有根对象指向任何内存。
  • 标记阶段:
    • 根对象全为 null,无对象被标记。
  • 清除阶段:
    • 所有对象(A 和 B)未标记,全部被回收。
两者优缺点
  • 引用计数:简单高效,但无法处理循环引用的情况。
  • 标记清除:可以处理循环引用的情况,但需要遍历对象,性能较差。

13. 请解释 JavaScript 中的模块化机制,包括 CommonJS、AMD 和 ES6 模块的区别。

回答:
JavaScript 中的模块化机制是用于组织和管理代码的一种方式,主要包括 CommonJS、AMD 和 ES6 模块。
  1. CommonJS:CommonJS 是 Node.js 中使用的模块化规范,通过 requiremodule.exports 实现模块化。
  1. AMD:AMD(Asynchronous Module Definition)是一种异步模块定义规范,通过 definerequire 实现模块化。
  1. ES6 模块:ES6 模块是 ECMAScript 6 中引入的模块化规范,通过 importexport 实现模块化。
CommonJS、AMD 和 ES6 模块的区别如下:
  • CommonJS:同步加载模块,适用于服务器端,不适用于浏览器端。
  • AMD:异步加载模块,适用于浏览器端,通过 RequireJS 实现。
  • ES6 模块:静态加载模块,适用于浏览器端和服务器端,通过 Babel 转换为 CommonJS 或 AMD。
  • CommonJS 和 AMD 是动态加载模块,ES6 模块是静态加载模块。
什么是动态加载模块?什么是静态加载模块?
  • 静态模块加载:使用 import 语句在文件顶部加载模块,代码运行前加载,适合总是需要的模块。
  • 动态模块加载:使用 require.ensure 或 System.import 方法加载模块,代码运行时加载,适合按需加载的模块。

14. 请解释 JavaScript 中的 call、apply 和 bind 方法的区别,并举例说明。

回答:
JavaScript 中的 callapplybind 方法是用于改变函数的 this 指向的方法。
  1. call 方法:call 方法用于调用函数,可以改变函数的 this 指向,并且可以传递参数列表。
  1. apply 方法:apply 方法用于调用函数,可以改变函数的 this 指向,并且可以传递参数数组。
  1. bind 方法:bind 方法用于创建一个新函数,可以改变函数的 this 指向,并且可以传递参数列表。
callapplybind 方法的区别如下:
  • callapply 方法都是立即调用函数,bind 方法是创建一个新函数。
  • callapply 方法的区别在于参数的传递方式,call 方法是传递参数列表,apply 方法是传递参数数组。
  • callapply 方法都是改变函数的 this 指向,bind 方法是创建一个新函数,不会改变原函数的 this 指向。

15. 请解释 JavaScript 中的深拷贝和浅拷贝。

回答:
JavaScript 中的深拷贝和浅拷贝是用于复制对象的两种方式。
  1. 浅拷贝:浅拷贝是指复制对象的第一层属性,如果属性值是对象,只复制对象的引用。
  1. 深拷贝:深拷贝是指复制对象的所有属性,包括对象的嵌套属性。
深拷贝和浅拷贝的区别如下:
  • 浅拷贝只复制对象的第一层属性,如果属性值是对象,只复制对象的引用。
  • 深拷贝复制对象的所有属性,包括对象的嵌套属性。

16. 请解释 JavaScript 中的节流和防抖。

回答:
节流和防抖是用于控制函数执行频率的两种方式。
  1. 节流:节流是指控制函数的执行频率,让函数在一定时间间隔内只执行一次。
  1. 防抖:防抖是指控制函数的执行频率,让函数在一定时间间隔内不再执行,直到过了时间间隔才执行。
节流和防抖的区别如下:
  • 节流是让函数在一定时间间隔内只执行一次,防抖是让函数在一定时间间隔内不再执行,直到过了时间间隔才执行。
  • 节流是控制函数的执行频率,防抖是控制函数的执行时机。

17. 请解释 JavaScript 中的柯里化函数。

回答:
柯里化函数是指将接受多个参数的函数转换为接受一个参数的函数,并返回接受余下参数的函数的技术。
柯里化函数的优点是可以将多个参数的函数转换为接受一个参数的函数,方便函数的组合和复用。

18. 请描述 JavaScript 中的内存泄漏的常见原因,并说明如何避免。

回答:
JavaScript 中的内存泄漏是指不再使用的内存没有被及时释放,导致内存占用过高的问题。
常见的内存泄漏原因如下:
  1. 闭包:闭包中的变量没有被释放,导致内存泄漏。
  1. 全局变量:全局变量没有被释放,导致内存泄漏。
  1. 定时器:定时器没有被清除,导致内存泄漏。
  1. DOM 引用:DOM 元素没有被释放,导致内存泄漏。
  1. 事件绑定:事件绑定没有被解除,导致内存泄漏。
避免内存泄漏的方法如下:
  1. 及时清除定时器:使用 clearIntervalclearTimeout 清除定时器。
  1. 及时解除事件绑定:使用 removeEventListener 解除事件绑定。
  1. 及时释放 DOM 引用:将 DOM 引用设置为 null
  1. 避免使用全局变量:使用模块化开发,避免使用全局变量。
  1. 避免使用闭包:避免在循环中使用闭包。

19. 请解释 JavaScript 中的 Promise 的原理,并举例说明其使用方法。

回答:
Promise 是 JavaScript 中用于处理异步操作的对象,用于解决回调地狱的问题。
Promise 的原理是通过 Promise 构造函数创建一个 Promise 对象,Promise 对象有三种状态:pendingfulfilledrejected。当异步操作执行成功时,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 对象,可以存储任意类型的值。
区别:
  • MapSet 都是数据结构,查找效率比 Array 高,并且都有 deletehas 方法。
  • Map 结构类似于二维数组,存储键值对 (key: value)。
  • Set 结构类似伪数组(更像对象),每个值都是唯一的。
  • Mapkey 不能重复,Setvalue 不能重复。
  • Map 使用 get 获取数据,Set 需要遍历或转换为数组访问。
  • Map 添加数据用 set() 方法,Setadd() 方法。

24. 请解释 JavaScript 中的 WeakMap 对象和 WeakSet 对象的原理,并举例说明其使用方法。

回答:
WeakMap 对象是 JavaScript 中用于存储键值对的对象,通过 WeakMap 构造函数创建 WeakMap 对象,键是弱引用,键被垃圾回收时,值也会被垃圾回收。
WeakSet 对象是 JavaScript 中用于存储唯一值的对象,通过 WeakSet 构造函数创建 WeakSet 对象,值是弱引用,值被垃圾回收时,值也会被垃圾回收。
区别:
  • 主要用于避免 MapSet 的内存泄漏问题。
  • WeakMapkeyWeakSetvalue 只能是对象
  • WeakMapWeakSet 使用 弱引用,当对象被 null 赋值时,垃圾回收机制会自动回收该对象。

25. 请解释 JavaScript 中的 setTimeout 和 setInterval 的区别,并说明如何清除它们。

回答:
setTimeoutsetInterval 都是 JavaScript 中用于定时执行函数的方法。
  1. setTimeoutsetTimeout 方法用于在一定时间后执行函数,只执行一次。
  1. setIntervalsetInterval 方法用于每隔一定时间执行函数,重复执行。
区别:
  • 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 操作符的实现原理如下:
  1. 创建一个空对象。
  1. 将空对象的原型指向构造函数的原型。
  1. 将构造函数的 this 指向空对象。
  1. 执行构造函数。
  1. 返回空对象。

28. 请描述 JavaScript 中的 instanceof 运算符的原理。

回答:
instanceof 运算符是 JavaScript 中用于判断对象的原型链是否包含构造函数的原型。
instanceof 运算符的原理如下:
  1. 获取对象的原型。
  1. 获取构造函数的原型。
  1. 判断对象的原型是否等于构造函数的原型,如果是返回 true,否则返回 false
  1. 如果对象的原型链中有构造函数的原型,返回 true,否则返回 false

29. 如何判断两个对象相等。

回答:
JavaScript 中判断两个对象相等有多种方式,包括:
  1. == 运算符:判断两个对象的值是否相等。
  1. === 运算符:判断两个对象的值和类型是否相等。
  1. JSON.stringify 方法:将对象转换为字符串,再比较字符串是否相等。
  1. Object.is 方法:判断两个对象是否严格相等。
  1. lodash 库:使用 lodash 库的 isEqual 方法判断两个对象是否相等。

30. ===== 的区别

回答:
===== 都是 JavaScript 中的比较运算符,用于比较两个值是否相等。
  1. === 运算符:严格相等运算符,比较两个值的类型和值是否相等。
  1. == 运算符:相等运算符,比较两个值的值是否相等,会进行类型转换。
区别:
  • === 运算符比较两个值的类型和值是否相等,不会进行类型转换。
  • == 运算符比较两个值的值是否相等,会进行类型转换。

31. 类型转换

回答:
转 Boolean:
可以使用Boolean()函数将值转换为布尔值。转换规则如下:
数据类型
转换为 true 的值
转换为 false 的值
Boolean
true
false
String
非空字符串
空字符串
Number
非零数字
0NaN
Object
任意对象
null
Undefined
undefined
转 Number:
有 3 个函数可以将非数值转化为Number类型:Number()parseInt()parseFloat()
  • Number():可以用于任何数据类型,规则如下:
    • undefined:转换为NaN
    • null:转换为0
    • truefalse:分别转换为10
    • 字符串:遵循以下规则:
      • 字符串中只包含数字(包括前面带正负号的情况):转换为十进制数值。因此,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():此方法用于数值、布尔值、对象、字符串,nullundefined没有toString()方法。也可以接受底数参数,用于指定数值的进制。例如,num.toString(2)返回二进制字符串,num.toString(8)返回八进制字符串,num.toString(16)返回十六进制字符串。
  • String():可以将任何类型的值转换为字符串。转换规则如下:
    • undefined:转换为"undefined"
    • null:转换为"null"
    • truefalse:分别转换为"true""false"
    • 数字:转换为十进制字符串形式。
    • 对象:调用对象的toString()方法,然后再根据前面的规则转换。
隐式转化:
在 JavaScript 中,有一些运算符可以将非预期的数据类型转换为数字或字符串。这种转换被称为隐式类型转换。规则如下:
  • +:如果其中一个操作数是字符串,则将另一个操作数转换为字符串。否则,两个操作数都转换为数字。
  • -、*、/ 和 %:如果其中一个操作数是字符串、布尔值、nullundefined,则将其转换为数字。如果其中一个操作数是对象,则调用valueOf()方法,然后再根据前面的规则转换。
  • ==:如果两个操作数类型相同,则直接比较。如果两个操作数类型不同,则尝试将它们转换为相同的类型,然后再比较。转换规则如下:
    • 如果一个操作数是布尔值,则将其转换为数字。
    • 如果一个操作数是字符串,另一个操作数是数字,则将字符串转换为数字。
    • 如果一个操作数是对象,另一个操作数不是对象,则调用对象的valueOf()方法,然后再根据前面的规则转换。
    • 如果一个操作数是null,另一个操作数是undefined,则相等。
    • 如果一个操作数是null,另一个操作数是非空对象,则不相等。
    • 如果一个操作数是undefined,另一个操作数是非空对象,则不相等。

Loading...

© Charlie Chan 2021-2025