Appearance
数据类型
数组的常用操作有哪些?
- 添加删除等
- push(): 在数组末尾添加一个或多个元素,并返回新数组的长度。
- pop(): 移除并返回数组末尾的元素。
- unshift(): 在数组开头添加一个或多个元素,并返回新数组的长度。
- shift(): 移除并返回数组开头的元素。
- concat(): 合并两个或更多数组,并返回新的合并后的数组,不会修改原始数组。
- slice(): 从数组中提取指定位置的元素,返回一个新的数组,不会修改原始数组。
- splice(): 从指定位置删除或替换元素,可修改原始数组。
- 查找
- indexOf(): 查找指定元素在数组中的索引,如果不存在则返回-1。
- lastIndexOf(): 从数组末尾开始查找指定元素在数组中的索引,如果不存在则返回-1。
- includes(): 检查数组是否包含指定元素,返回一个布尔值。
- 遍历
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', 我们也叫它 关联数组
判断方式不同
- Array.isArray()
- instanceof 判断其是否属于对应的构造函数对象
- 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- constructor 判断
ts
console.log([].constructor === Array)
console.log({}.constructor === Object)- 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()的区别和优劣
- Object.prototype.toString.call()
每一个继承 Object 的对象都有 toString 方法,如果 toString 方法没有重写的话,会返回 [Object type],其中 type 为对象的类型。但当除了 Object 类型的对象外,其他类型直接使用 toString 方法时,会直接返回都是内容的字符串,所以我们需要使用 call 或者 apply 方法来改变 toString 方法的执行上下文。
- instanceof
instanceof 的内部机制是通过判断对象的原型链中是不是能找到类型的 prototype。
使用 instanceof 判断一个对象是否为数组,instanceof 会判断这个对象的原型链上是否会找到对应的 Array 的原型,找到返回 true,否则返回 false。
问题: 对于 iframe 中的 Array 此方法会判断错误
- 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 源码可见,因此,是可以使用其他语言模拟的,这就导致,如果攻击者知道了当前随机生成器的状态,那就可以知道缓存中的所有随机数,那就很容易匹配与破解。
- Crypto.getRandomValues()
Crypto.getRandomValues() 方法返回的也是伪随机数,不是真随机, 且底层实现是没有缓存的,随机数都是实时生成的
