说一下JavaScript中的数据类型有哪些?
- JavaScript的数据类型分为:基本数据类型、引用数据类型
- 基本数据类型:String,Number,Boolean,undefined,Null,Symbol
- 引用数据类型:Object,Date,Array,Math,Map,Set Function
- 区别:基本数据类型是存储于栈内存中,引用数据类型是存储于堆内存中
|| 和 && 操作符的返回值?
- || 和 && 首先会对第一个操作数执行条件判断,如果其不是布尔值就先强制转换为布尔类型,然后再执行条件判断
- 对于 || 来说,如果条件判断结果为 true 就返回第一个操作数的值,如果为 false 就返回第二个操作数的值
- && 则相反,如果条件判断结果为 true 就返回第二个操作数的值,如果为 false 就返回第一个操作数的值
null和undefined的区别?
- undefined 和 null 首先都是基本数据类型,undefined的意思是未定义,null的含义是空值[空对象]
- 一般我们在声明了变量但没有定义的时候就会报出undefined,null我们一般用于赋值给一些可能会返回的一些对象的变量作为初始化的值
== 操作符的强制类型转换规则
- 首先对于 == 运算符来说,如果比较双方的类型不同,就会进行类型转换
- 它的比较流程: 先进行比较判断两者的类型是否相同,相同的话就比较两者的大小,类型不同的话就进行类型的转换
如何判断一个对象是一个空对象?
- 使用 JSON.strtingify()方法进行判断
if(JSON.stringify(obj) == '{}') return console.log('是一个空的对象')
- 使用 ES6 的 Object.keys() 方法进行判断
const obj = {}
if (Object.keys(obj).length <= 0) return console.log('是一个空的对象')
说一说数组中常用的方法以及其特点
- push() 向数组末尾添加数据【返回值:追加以后的数组的长度】
- pop() 删除数组末尾元素的数据【返回值L被删除的数据】
- unshift(数据1,数据2,...) 从数组的头部插入数据【返回值:插入后的数组长度】
- shift() 删除数组中前面的数据【返回值:被删除的数据】
- reverse() 反转数组【返回值:反转后的数组】
- sort(function(a, b) { return a -b }) 数组排序【返回值:排序后的数组】【可以升序或降序】
- splice() 切割数组【截取】或 替换新内容【返回值:是一个新的数组】
-
- splice(开始索引, 截取的个数)
- splice(开始索引, 多少个, 替换的数据1, ...)
- concat() 拼接数组 【返回值:拼接好的数组】
- slice(开始索引, 结束索引) 获取数据里的某些数据【返回值:一个数组】
- join('连接符号') 把数组中的数据用连接符进行连接【返回值:String】
- indexOf(数据) 查看数组里面的数据的索引【返回值:数据的索引,没有就返回 -1】
- lastIndexOf(数据) 反向查看数组里面的数据索引【返回值:数据的索引,没有就返回 -1】
- forEach(function (item, index, arr) { }) 取代 for 循环 遍历数组
-
- item 表示数组的每一项
- index 表示数组的每一项索引
- arr 原始数组
- map(function (item, index, arr) { }) 映射数据 【返回值:一个新的数组】
-
- item 表示数组的每一项
- index 表示数组的每一项索引
- arr 原始数组
- filter(function (item, index, arr) { }) 过滤原始数组中的数据,把满足条件的放在新数组中【返回值:新数组】
-
- item 表示数组的每一项
- index 表示数组的每一项索引
- arr 原始数组
- every(function (item, index, arr) { }) 判断原始数组中的数据是不是每一个都满足条件【返回值:布尔类型】
-
- item 表示数组的每一项
- index 表示数组的每一项索引
- arr 原始数组
- some(function (item, index, arr) { }) 判断数组中是不是有某一个满足条件【返回值:布尔类型】
-
- item 表示数组的每一项
- index 表示数组的每一项索引
- arr 原始数组
- copyWithin(目标位置, 开始索引, 结束索引) 使用数组里面的内容替换数组里面的内容
-
- 目标位置:当你替内容的时候,从哪一个索引位置开始替换
- 开始索引:数组哪一个索引位置开始当做替换内容
- 结束索引:数组哪一个索引位置结束后当做替换内容
- fill(要填充的数据, 开始索引, 结束索引) 使用指定数据去填充数组【返回值:填充好的数组】
- includes(数据) 查看数组中是否有某一个数据 【返回值:布尔类型】
- flat(数字) 拍平数组 【返回值:拍平以后的数组】
-
- 数字:表示扁平化多少层【还可以写:Infinity】
- flatMap(function (item, index, arr) { }) 拍平数据,但是只能排一层【返回值:一个新的数组】
- find(function (item) { }) 根据条件找到数组里面满足条件的数据 【返回值:找到的那个数据】
- findIndex(function (item) { }) 根据条件找到数组里面满足条件的数据 【返回值:找到的那个数据的索引】
- reduce(function (prev, item, index, arr) { }, 初始值) 进行叠加累计
-
- 第一次参数 初始值 或 每一次叠加后的结果
- 第二个参数 每一项
- 第三个参数 索引
- 第四个参数 原始数组
实现一个冒泡排序 和 一个选择排序
const arr = [9, 2, 3, 4, 6, 5, 8, 7];
// 冒泡排序
for (let i = 0; i < arr.length - 1, i++) {
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] < arr[j + 1]) {
let temp arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
// 选择排序
for (let i = 0; i < arr.length; i++) {
for (let j = i - 1; j < arr.length; j++) {\
if (arr[i] > arr[j]) {
let temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
}
}
什么是事件冒泡和事件捕获?
- 事件冒泡:IE 最早提出的,事件开始时由最具体的元素接收,然后逐级向上传播到 DOM 最顶层节点的过程
- 事件捕获:网景最早提出,由DOM最顶层节点开始,然后逐级向下传播到最具体的元素接收过程
什么是闭包?
- 闭包【closure】指有权访问另一个函数作用域中变量的函数,简单点说就是:一个作用域可以访问另外一个函数内部的局部变量
- 闭包的作用:延伸了变量作用范围,不会立即被垃圾回收机制所清理
- 闭包的缺点:由于闭包会使得函数中的变量保存在内部中,不会立即消失,就会导致内存消耗很大,存在内存泄露的问题发生,所以不能滥用闭包,【所以在退出函数之前,需要将不再使用的变量全部删除掉】
- 案例演示: 利用闭包为每一个元素绑定单击事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<ul class="nav">
<li>苹果</li>
<li>香蕉</li>
<li>橘子</li>
<li>橙子</li>
</ul>
<script>
// 闭包 【closure】指有权访问另一个函数作用域中变量的函数
// 闭包的主要作用就是延伸了变量的作用范围
var lis = document.querySelector('.nav').querySelectorAll('li');
/* for (var i = 0; i < lis.length; i++) {
lis[i].index = i;
lis[i].onclick = function () {
console.log(this.index);
}
} */
// 利用 闭包的方法 【会导致内存泄露】
for (var i = 0; i < lis.length; i++) {
(function (i) {
lis[i].onclick = function () {
console.log(i);
}
})(i);
}
</script>
</body>
</html>
let、const、var 关键字的区别?
- let和const具有块级作用域,var不存在块级作用域
- var 关键字存在变量的提升, let、const不存在变量提升,即变量只能在声明之后使用,否在会报错
- var声明的变量为全局变量,并且会将该变量添加为全局对象的属性,但是let和const不会
- var可以重复声明变量,后声明的同名变量会覆盖之前声明的变量, const和let不允许重复声明变量
- let、const 存在暂时性死区,而 var 声明的变量是没有的
- var和let不需要赋初始值,只声明就可以,而 const 是不可以的
- let创建的变量是可以更改指针指向(可以重新赋值),而 const 声明的则不可以【值不允许修改】
箭头函数与普通函数的区别?
- 箭头函数比普通函数更加简洁
- 箭头函数没有自己的this
- call()、apply()、bind()等方法不能改变箭头函数中this的指向
- 箭头函数不能作为构造函数使用
- 箭头函数没有自己的arguments
- 箭头函数没有prototype
- 箭头函数不能用作Generator函数,不能使用yield关键字
const 对象属性可以修改么?
- 了解一个概念: const 关键字保证的不是变量得到值不能改变,而是变量指向的内存地址不能进行改变
- 因此使用 cosnt 关键字声明的 量,我们一般称之为是 常量、
如果 new 一个箭头函数会如何?
- 箭头函数是没有 prototype,也没有自己的 this,更不可以使用 arguments 参数,所以不能 new 一个箭头函数,如果 new 是不会执行的
扩展运算符的使用场景以及其作用
- 对象扩展运算符: 用于取出参数对象中所有可以变量的属性,拷贝到当前对象中【浅拷贝】
- 数组扩展运算符: 可以将一个数组转为用逗号分隔的参数序列,且每次只能展开一层数组
new 的实现原理
持续更新中,如果对你有所帮助,请点个赞吧 感谢~