Skip to content

数据类型

数组的常用操作有哪些?

  1. 添加删除等
  • push(): 在数组末尾添加一个或多个元素,并返回新数组的长度。
  • pop(): 移除并返回数组末尾的元素。
  • unshift(): 在数组开头添加一个或多个元素,并返回新数组的长度。
  • shift(): 移除并返回数组开头的元素。
  • concat(): 合并两个或更多数组,并返回新的合并后的数组,不会修改原始数组。
  • slice(): 从数组中提取指定位置的元素,返回一个新的数组,不会修改原始数组。
  • splice(): 从指定位置删除或替换元素,可修改原始数组。
  1. 查找
  • indexOf(): 查找指定元素在数组中的索引,如果不存在则返回-1。
  • lastIndexOf(): 从数组末尾开始查找指定元素在数组中的索引,如果不存在则返回-1。
  • includes(): 检查数组是否包含指定元素,返回一个布尔值。
  1. 遍历
  • filter(): 创建一个新数组,其中包含符合条件的所有元素。

  • map(): 创建一个新数组,其中包含对原始数组中的每个元素进行操作后的结果。

  • reduce(): 将数组中的元素进行累积操作,返回一个单一的值。

  • forEach(): 对数组中的每个元素执行提供的函数。

  • join(): 将数组中的所有元素转为字符串,并使用指定的分隔符连接它们。

  • reverse(): 颠倒数组中元素的顺序,会修改原始数组。

  • sort(): 对数组中的元素进行排序,默认按照字母顺序排序,会修改原始数组。

字符串的常用操作有哪些

charAt() 方法获取到的是指定位置的字符; charCodeAt()方法获取的是指定位置字符的 Unicode 值。 indexOf() 从左向右查找某个字符,有则返回第一次匹配到的位置,否则返回-1

JS 变量类型分为几种,区别是什么?

JS 数据类型分为两种: 基本类型和引用类型。

基本类型存储在栈中,引用类型存储在堆中,在栈中存储了该变量在堆中的地址。

基本类型分为 6 种:

  • String
  • Null
  • Undefined
  • Boolean
  • Number
  • Symbol

引用类型:

  • Object

数据类型分别存在哪里

分别存放在堆和栈中。

栈和堆的区别, 栈和堆具体怎么存储

堆和栈都是运行时内存中分配的一个数据区,其存储的数据类型和处理速度不同。

  • 堆(heap)用于给复杂数据类型(引用类型)分配空间,如对象、数组等等,其运行时动态分配内存,所以存取速度较慢。

  • 栈(stack)用于存放基本类型变量和引用类型的地址,其优势就是存取数据比堆块,并且栈里的数据是可共享的,缺点是分配给栈中数据的大小是确定的。

Array 是 Object 类型吗

是的,其也是一个引用类型

Array 和 Object 的区别

类型不同

  • Array 存放的是一个有序数据的集合 , 其数据没有名称 'name'
  • Object 存放的是一个无序数据的集合, 其数据有名称 'name', 我们也叫它 关联数组

判断方式不同

  1. Array.isArray()
  2. instanceof 判断其是否属于对应的构造函数对象
  3. isPrototypeOf() 判断一个对象是否存在于另一个对象的原型链中。
ts
console.log(Array.prototype.isPrototypeOf([])) // true
console.log(Array.prototype.isPrototypeOf({})) // false
console.log(Object.prototype.isPrototypeOf([])) // true
console.log(Object.prototype.isPrototypeOf({})) // true
  1. constructor 判断
ts
console.log([].constructor === Array)
console.log({}.constructor === Object)
  1. toString()
ts
console.log(Object.prototype.toString.call([]))   // [object Array]
console.log(Object.prototype.toString.call({}))   // [object Object]

关联数组

具有命名索引的数组被称为关联数组(或散列)。

JavaScript 不支持命名索引的数组。 所以我们不能使用 arr["xxx"] 去访问一个名称下标的数据

var a = {b: 1}存放在哪里

a 变量存放在 栈中, a 的值存放在 堆中

var a = {b: {c: 1}}存放在哪里

数组里面有 10 万个数据,取第一个元素和第 10 万个元素的时间相差多少

没有时间差。

时间复杂度都是 O(1),即按照索引去查找数组中的数据时间差是没有的

== 和 ===的区别,什么情况下用==

  • == 如果类型不同会进行类型的转换再比较值是否相等

  • === 即比较值也比较类型

特殊的数字

js
11     // 11  ==> 数字
11.    // 11  ==> 省略小数点后面的
.11    // 11  ==> 省略小数点前面的0
011    // 9   ==> 0开头的当做8进制
080    // 80  ==> 0开头的当做8进制,但是8进制最大为7,所以自动变成十进制
0o80   // 无法理解的数字  ==> 0o 开头的当做8进制且8进制最大为7,然后0o开头强制为八进制,所以数字错误
0o11   // 9
0b11   // 3
0x11   // 17
11e2   // 1100  ==> 科学计数法
11.toString()   //  无法理解的数字 ==> 11. 认为这是数字,出现t 导致错误
11 .toString()  // 11  ==> 加了一个空格,所以装换成字符串类型的 '11'.toString()
11_111 // 11111 ==> JS中的为了可以方便的认识数字,所以可以添加_来分隔,

为什么不能直接使用 undefined

js
// 这是错误的
const a = undefined

// 这是正确的
const a = void 0

在 JS 中 undefined 不是一个关键字,其实际上是 window 对象的一个属性 ,即window.undefined === undefined,所以我们上面 const a = undefined 相当于 const a = window.undefined;这时候看来我们是否是可以去修改 window.undefined 的值?实际上是不可以的,在 window.undefined 属性是一个只读属性,不能被修改。那么这就没有问题。

但是注意上面 undefined 不是一个关键字,所以其可以作为一个变量,即

js
function func() {
  const undefined = 1
  const b = undefined // 这时候 b === 1
}

,所以不能直接使用 undefined 进行赋值,太坑了.

Object.prototype.toString.call() , instanceof, Array.isArray()的区别和优劣

  1. Object.prototype.toString.call()

每一个继承 Object 的对象都有 toString 方法,如果 toString 方法没有重写的话,会返回 [Object type],其中 type 为对象的类型。但当除了 Object 类型的对象外,其他类型直接使用 toString 方法时,会直接返回都是内容的字符串,所以我们需要使用 call 或者 apply 方法来改变 toString 方法的执行上下文。

  1. instanceof

instanceof 的内部机制是通过判断对象的原型链中是不是能找到类型的 prototype

使用 instanceof 判断一个对象是否为数组,instanceof 会判断这个对象的原型链上是否会找到对应的 Array 的原型,找到返回 true,否则返回 false。

问题: 对于 iframe 中的 Array 此方法会判断错误

  1. Array.isArray()

功能:用来判断对象是否为数组

  • instanceof 与 isArray

当检测 Array 实例时,Array.isArray 优于 instanceof ,因为 Array.isArray 可以检测出 iframes

js
var iframe = document.createElement("iframe")
document.body.appendChild(iframe)
xArray = window.frames[window.frames.length - 1].Array
var arr = new xArray(1, 2, 3) // [1,2,3]

// Correctly checking for Array
Array.isArray(arr) // true
Object.prototype.toString.call(arr) // true
// Considered harmful, because doesn't work though iframes
arr instanceof Array // false
  • Array.isArray() 与 Object.prototype.toString.call()

Array.isArray()是 ES5 新增的方法,当不存在 Array.isArray() ,可以用 Object.prototype.toString.call() 实现。

js
if (!Array.isArray) {
  Array.isArray = function (arg) {
    return Object.prototype.toString.call(arg) === "[object Array]"
  }
}

Math.random()为什么是不安全的

为了保证足够的性能,Math.random() 随机数并不是实时生成的,而是直接生成一组随机数(64 个),并放在缓存中。当这一组随机数取完之后再重新生成一批,放在缓存中。

由于 Math.random() 的底层算法是公开的(xorshift128+ 算法),V8 源码可见,因此,是可以使用其他语言模拟的,这就导致,如果攻击者知道了当前随机生成器的状态,那就可以知道缓存中的所有随机数,那就很容易匹配与破解。

  1. Crypto.getRandomValues()

Crypto.getRandomValues() 方法返回的也是伪随机数,不是真随机, 且底层实现是没有缓存的,随机数都是实时生成的