一、js的数据类型有哪些
1、基本类型:
Boolean(布尔类型),String(字符串类型),Number(数字类型),Null,Undefined,Bigint还有一个es6新增的Symbol。
2、引用类型:
Object(对象),Function(函数),Array(数组)
二、js的内存存储的方式
1、栈内存:引擎执行代码时工作的内存空间,除了引擎,也用来保存基本类型数据和引用数据类型的地址
2、堆内存:用来保存一组无序且唯一的引用类型值。可以使用栈中的键名来获取
基本数据类型放在栈内存里面;
引用数据类型有一个占位在栈内存里,真实的数据在堆内存中,并且占位有一个指针指向对应的内存空间。这就是为什么const可以对原引用数据类型进行修改,而不能重新赋值一个新对象的原因。一是因为指针未发生改变,二是因为指针指向新的内存地址会报错。
如果,我们使用const声明的是一个对象的话是可以修改值的,因为这个常量不能修改指的是指向的地址不能修改,我只是修改里面的内容,堆空间地址是不变的,所以是可以修改的。
三、js中如何判断是不是一个数组
1. 通过 instanceof 判断
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在原型链中的任何位置,返回一个布尔值
let a=[ ];
a instanceof Array //true
let b={ }
b instanceof Array //false
2. 通过 constructor 判断
实例的构造函数属性 constructor 指向构造函数,那么我们通过 constructor 属性也可以判断是否为一个数组。
let a =[1,2,3,4]
a.constructor === Array //true
3. 通过 Array.isArray() 判断
Array.isArray() 用于确定传递的值是否是一个数组,返回一个布尔值。
let a =[1,2,3]
Array.isArray(a) //true
4. 通过 Object.prototype.toString.call() 判断
Object.prototype.toString.call() 可以获取到对象的不同类型
let a=[1,2,3]
Object.prototype.toString.call(a)=== '[object Array]' //true
它不仅仅可以检测是否是数组,还可以检测是否是一个函数或者数字等等
let a=function (){}
Object.prototype.toString.call(a)=== '[object Function]' //true
let b=3
Object.prototype.toString.call(b)=== '[object Number]' //true
四、let、const、var的区别
1. var声明的变量会挂载在window上,而let和const声明的变量不会
var a=1;
console.log(window.a) // 1
let b=1;
console.log(window.b) //undefined
const c=1;
console.log(window.c) //undefined
2. var声明变量存在变量提升,let和const不存在变量提升
console.log(a); //undefined
var a = 1;
let b = 1;
console.log(b); //1
console.log(b2) //报错
let b2 = 1;
console.log(c); //报错
const c = 1;
3. let 和 const 声明形成块级作用域
if () {
var a = 10;
let b = 10;
}
function fn() {
return {
a: 100,
};
}
fn();
console.log(a); //100
console.log(b); //报错:b is not defined
4. 同一作用域下 let 和 const 不能声明同名变量,而var可以
const a = 1;
const a = 4; //报错:标识符'a'已经声明
var b=1;
var b=2; //不会报错
let c=1;
let c=2; //报错:标识符'c'已经声明
5. const 声明时的事项
- 一旦声明必须赋值.
- 声明后不能在修改.
- 如果声明的是引用类型数据,可以修改.
五、 JS常见的设计模式有那些
单例模式,工厂模式,适配模式,观察者模式等
单例模式:就是保证一个类里面只有一个实例,实现的方法一般是先判断实例存在与否。如果存在就直接返回,不存在就创建了在返回。单例作为一个命名空间的提供者,从全局命名空间提供一个唯一访问点来访问该对象
观察者模式:观察者模式的工作就是在解耦。让耦合的双方都依赖于抽象,不是依赖于具体。从而使一方的变化不会影响到另外一方.
六、es6新增语法
let/const 箭头函数 模板字符串 解构赋值 等
let/const
Const声明一个常量
let声明一个变量不会变量提升
箭头函数
箭头函数没有this 他的this指向上一层
模板字符串
let a=18
console.log(`李磊${a}岁了`)//李磊18岁了
解构赋值
数组解构,函数参数解构 对象解构
七、阻止事件冒泡的方式
冒泡事件:比如说鼠标点击了一个按钮,同样的事件将会在那个元素的所有祖先元素中被触发。这一过程被称为事件冒泡。
阻止冒泡事件有三种方法:
1.event.stopPropagation()方法
$('.btn').click(function (even) {
even.stopPropagation();
alert('按钮被点击了');
})
这是阻止事件的冒泡方法,不让事件向documen上蔓延,但是默认事件任然会执行,当你掉用这个方法的时候,如果点击一个连接,这个连接仍然会被打开。
例如:
<a href="https://www.csdn.net/" class="box">
<button class="btn">按钮</button>
</a>
2.event.preventDefault()方法
$('.btn').click(function (even) {
even.preventDefault();
alert('按钮被点击了');
})
这是阻止默认事件的方法,调用此方法是,连接不会被打开,但是会发生冒泡,冒泡会传递到上一层的父元素;
3.return false ;
$('.btn').click(function (even) {
alert('按钮被点击了');
return false;
})
这个方法比较暴力,他会同事阻止事件冒泡也会阻止默认事件;写上此代码,连接不会被打开,事件也不会传递到上一层的父元素;可以理解为return false就等于同时调用了event.stopPropagation()和event.preventDefault()
八、==和===的区别
==是比较值相等即可
console.log(1=='1') //true
===不仅比较值是否相等还要比较数据类型是否相同
console.log(1==='1') //false
console.log(1===1)//true
九、 判断JS的数据类型
1. typeof
typeof主要用来判断基本数据类型 他返回的数据类型是字符串 (注意:typeof来判断null和引用数据类型 返回的结果都是 ‘object’)
typeof 1 //number
typeof 'a' //string
typeof true //boolean
typeof undefined //undefined
typeof null //object
typeof {} //object
typeof [1,2,3] //object
function Fn(){}
typeof new Fn() //object
typeof new Array() //object
2.instanceof
instanceof 后面一定要是对象类型,并且大小写不能错 (专门判断引用数据类型)
console.log(a instanceof Array) //true
console.log(b instanceof Date)
console.log(c instanceof function) //true
console.log(d instanceof function) //false
十、 js常见的创建方式
//1.实例化创建 new
var obj=new Obj();
obj.name="磊磊"
obj.age=18
obj.say=function(){
console.log(this.name)
}
//2.直接创建
let obj1={
name:"磊磊",
age:18
}
//3.自定义构造函数创建对象
let OBJ=new obj2("磊磊",18)
function obj2(name,age){
this.name=name;
this.age=age;
console.log(this.name);
}
十一、 map和forEach的区别
1.map()会分配内存空间储存新的数组并且返回 foreach()不会返回新的数据
2.foreach()允许callback改变原数组的内容。map()返回新的数组。
3.map多用于复杂的逻辑运算中 在react中循环多数用map
十二、 数组去重的方法
1.双重for循环去重
//数组去重
function disTinct(arr) {
var ans = []
for (var i = arr.length - 1; i >= 0; i--) {
var nb = 0 //没重复为0.有重复不为0
for (var j = i - 1; j >= 0; j--) {
if (arr[i] == arr[j]) {
nb = 1
break
}
}
if (nb == 0) {
ans.unshift(arr[i])
}
}
return ans
}
2. indexof去重
//数组去重(indexOf)
function unique(arr) {
var res = []
for (var i = 0; i < arr.length; i++) {
if (res.indexOf(arr[i]) == -1) {
res.push(arr[i])
}
}
return res
}
3. sort排序后循环数组去重
function unique(arr){
var arr2 = arr.sort();
for(var i=1;i<arr2.length;){
if(arr2[i] === arr2[i-1]){
arr2.splice(i,1);
}else{
i++;
}
}
return arr2;
}
十三、 number和parseint的区别
parseInt() 函数:
parseInt()函数用于解析字符串并将其转换为指定基数的整数。它需要两个参数,要解析的字符串和要使用的基数。基数是一个介于2和36之间的整数,表示数字的基数。
如果parseInt()在解析过程中遇到不符合指定基数的字符,它将忽略该字符和所有后续字符。然后它将解析到该点的值作为一个整数返回。在这种情况下,允许使用前导或尾随的空格。
如果parseInt()函数得到参数如果以数字开头,就会返回开头的合法数字部分;如果以非数字开头,则它将返回NaN。此NaN值不是任何基数的有效数字,不能用于任何数学计算。
语法:
parseInt(string, radix)
Number()函数:
Number()函数用于创建基本类型Number对象。它接受一个参数,即数字的值。此值可以使用字符串传递,Number函数将尝试将其表示为数字。如果参数无法转换为数字,则返回NaN值。此NaN值不是有效数字,不能用于任何数字计算。
语法:
Number(valueString)
parseInt()和Number()之间的区别
1、当转换的内容包含非数字的时候,Number() 会返回NaN(Not a Number);parseInt() 要看情况,如果以数字开头,就会返回开头的合法数字部分,如果以非数字开头,则返回NaN。
2、parseInt()仅返回整数值的区别,而Number()返回包括浮点的所有数字。
十四、 Eventloop机制
这个是js的一个底层运行的原理 因为js的单线程的。但是一些耗时的任务会影响到我们的执行效率。这样我们使用异步的时候 会单独开辟出来一个异步线程。将这些耗时的放在异步线程中。等主线程里面执行完毕之后,再从异步队列中取出一个到主线程中执行。执行完之后在在异步线程中取出第二个。这个过程就是eventloop循环机制
十五、防抖和节流
防抖是指我们在连续对一个事件进行操作的时候,这个事件只会按照固定每n秒执行一次的时间执行
(就是为了防止用户连续点击多长清除相同的数据 造成浏览器和服务器频繁的接收带来的压力)
节流大多用于搜索框等地方 是指我们在连续操作一个事件的时候,这个事件不会执行,只有等我们操作完成之和等n秒后自己执行
(也是减少浏览器和服务器的压力)