1、基础深入
js数据类型有哪些
数据类型分为两种:基本数据类型与引用数据类型。
基本数据类型有:number、string、boolean、null、undefined。
引用数据类型有:array、function等(除了基本数据类型都是引用数据类型)
基本数据类型的主要特点是赋值方式是传值,并且值存在栈中。
引用数据类型的主要特点是赋值方式是传址,并且值存在堆中。
js数据类型判断
JavaScript 中常用的数据类型判断方法有以下 5 种:
1.typeof 操作符:可以返回一个字符串,用于表明所操作数的类型。
2.instanceof 操作符:可以判断一个对象是否属于某个类(或其子类)。
3.Object.prototype.toString.call() 方法:可以返回一个表示调用它的对象所属类的字符串。
4.constructor 属性:可以返回对创建该对象的数组函数的引用。
5.Array.isArray() 方法:可以判断一个值是否为数组。
6.===也可以做全等的类型判断
这些方法的区别如下:
1.typeof 只能区分基本数据类型,不能区分具体的对象类型。
2.instanceof 只能用于判断对象类型,无法判断基本数据类型
3.Object.prototype.toString() 方法可以返回对象类型的具体字符串
4.constructor 属性可以返回对象所属类的构造函数
5.Array.isArray() 可以判断一个值是否为数组
let obj = {
name: 'dawn',
age: 21
}
let fn = function () {
console.log('我是 function 类型');
}
console.log(Object.prototype.toString.call(1)); // [object Number]
console.log(Object.prototype.toString.call('Hello tomorrow')); // [object String ]
console.log(Object.prototype.toString.call(true)); // [object Boolean]
console.log(Object.prototype.toString.call(undefined)); // [object Undefined]
console.log(Object.prototype.toString.call(fn)); // [object Function]
console.log(Object.prototype.toString.call(new Date)); // [object Date]
console.log(Object.prototype.toString.call(null)); // [object Null]
console.log(Object.prototype.toString.call([1, 2, 3])); // [object Array]
console.log(Object.prototype.toString.call(obj)); // [object Object]
如何判断是否是一个数组
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
var arr = [1,2,3];
arr instanceof Array // true
var obj = {};
obj instanceof Array // false
Array.isArray()
Array.isArray([1,2,3]);
constructor 在其对应对象的原型下面,是自动生成的。
var arr = [1,2,3];
arr.constructor === Array
Object.prototype.toSrtring.call([ ])
在任何值上调用Object原生的toString()方法,都会返回一个[Object NativeConstructorName]格式的字符串。每个类在内部都一个[[class]]属性,这个属性中指定了上述 字符串中的构造函数名。
var value = [1,2,3];
alert(Object.prototype.toString.call(value)); // "[object Array]"
Object.prototype.toString.call([1, 2, 3])
Array.isArray(). 返回值:true,false
js的运行机制是什么
js运行机制,即事件循环机制。js是单线程执行的,这意味着同一时间内只能做一件事,但这并不是说单线程就会阻塞,而要实现单线程且非阻塞的方法就是事件循环机制。
在js中,会把任务分为同步和异步,这两者的执行环境不同,同步任务会进入主线程,异步任务会进入事件队列(EventQueue),当主线程代码执行完毕后,会去事件队列中读取对应的异步任务,并推到主线程中执行,不断重复过程,称为事件循环机制(EventLoop) 。
undefined和null有什么区别
null表示为空,代表此处不应该有值的存在,⼀个对象可以是null,代表是个空对象,⽽null本身也是对象。
undefined表示『不存在』,JavaScript是⼀⻔动态类型语⾔,成员除了表示存在的空值外,还有可能根本就不存在(因为存不存在只在运⾏期才知道),这就是undefined的意义所在。
==和===有什么区别
双等仅仅是看值是否相等,值相等即可无需比较类型。三等是值类型与数据类型进行双层比较。
js中布尔值为false的六种情况
undefined(未定义找不到值时出现)、
null(代表空值)
NaN(无法计算时候出现表示非数值,typeof(NaN)是number类型)
false(布尔值的false,注意:‘false’的布尔值为true(''这是字符串))
0(数字)
空串 ''、""、``(单双引号,注意中间有空格是true)
null typeof为什么是一个object
因为在javaScript中,不同的对象都是使用二进制存储的,如果二进制前三位都是0的话,系统会判断为是Object类型,而null的二进制全是0,自然也就判断为Object
js中的this指向有哪些
函数直接调用,this是window
函数是作为对方的方法调用,this是调用方法的对象
new构造函数时,this是实例对象
call (),apply(),bind()可以改变this的指向
事件函数中,this指向事件源
定时器(setTimeout setInterval)环境this指向window
箭头函数中没有自己的this,它指向其外层作用域的this
改变this指向的方法有哪些,区别是什么
共同点:
call、apply、bind都是用来改变函数的this对象的指向的,第一个参数都是this要指向的对象,都可以参加后续参数传参
不同点:
bind是返回对应函数,不会执行,需要手动去调用;
apply、call则是立即调用调用
apply和call功能一样,只是传入的参数列表形式不同,call 需要把参数按顺序传递进去,而 apply 则是把参数放在数组里。
构造函数中的new做了什么
1、创建了一个新的空对象;
2、将构造函数的原型对象赋值到实例对象的原型链上;
3、改变了构造函数的this指向,指向新的实例对象;
4、依次执行代码,赋值
5、将实例对象返回(return);
arguments的特点
JavaScript中,arguments对象是比较特别的一个对象,实际上是当前函数的一个内置属性,(与this一样,都是内置属性)。也就是说所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。arguments是一个伪数组,因此可以进行遍历,并且有length属性。
arguments只是伪数组,并不是真正的数组,因此不能调用数组的方法。
contiune/break/return区别
return关键词,用于结束循环语句,函数执行过程遇到return,则直接结束函数执行(即剩下部分不再执行),将return后的值作为函数调用的返回值
continue结束当次循环,继续执行下次循环
break表示跳出本轮循环,注意只能结束离break最近一层循环
数组有哪些方法
push()、unshift、shift()、pop()、splice()、join()、reverse()
map()、filter()、some()、every()、findindex()、reduce()等
map()对比forEach()
map有返回值,可以开辟新空间,return出来一个length和原数组一致的数组,即便数组元素是undefined或者是null。
forEach默认无返回值,返回结果为undefined,可以通过在函数体内部使用索引修改数组元素。
map的处理速度比forEach快,而且返回一个新的数组,方便链式调用其他数组新方法
数组转字符串字符串转数组
join() 方法可以把数组转换为字符串
split() 方法可以把字符串转换为数组
阻止事件冒泡和默认事件的方法
e.stopPropagation()来阻止事件冒泡。作用当然是阻止我们触发它上级的事件
e.preventDefault()阻止默认行为事件的方法,例如:超链接不跳转
return false ;这个方法比较暴力,他会同时阻止事件冒泡也会阻止默认事件,针对:on事件绑定的情况
innerHTML innerText区别
innnerHTML用来获取标签元素或设置标签元素,包含文本和Html标签。在读取元素的时候,会将文本和Html标签一起读取出来;在设置元素的时候,会覆盖掉原来的元素中文本和标签,如果新的内容包含标签,会解析Html标签,只显示文本,而不将标签显示出来。
innerText用来设置或获取标签内文本内容, 但它去除Html标签。在读取元素的时候,只会读取文本;在设置元素的时候,会覆盖掉原来的元素中文本和标签,如果新的内容包含标签,不会解析Html标签,也就是说,里面的标签并不是html中的标签,而只是一个文本。
js事件代理(事件委托)
把事件处理任务添加到上一级的元素中,这样就避免了把事件添加到多个子集元素上,底层原理是利用了事件冒泡机制
优点:
减少注册时间,节约内存
简化dom节点更新,相应事件的更新
对于新增的节点,可以不用再次绑定事件
缺点:
对于不冒泡的事件不给予支持
层级太多肯能会被中间的某层阻止掉
理论上会导致浏览器会频繁的调用处理函数,虽然可能不需要处理
本地存储的方法及特点
sessionStorage,localStorage,cookie
sessionStorage仅在当前会话下有效,关闭页面或浏览器后被清除,内存较小,单页面内共享数据
localStorage 用于长久保存整个网站的数据,保存的数据没有过期时间,直到手动去删除;内存较大;多页面可以共享数据
数组去重有哪些方法
1.利用新旧数组遍历对比法
arr=[1,5,1,3,5,4,3,9,8]
let newArr = [];
/*
indexOf用于查找数组元素第一次出现的位置,没找到则返回值为-1,
参数有两个,第一个为元素项目,参数二(可选)需要查找的位置,负数从-1往前面加
*/
for (let i=0;i<arr.length;i++) {
if (newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i]);
}
}
console.log(newArr);//[1, 5, 3, 4, 9, 8]
2.利用新语法 new Set()
arr=[1,5,1,3,5,4,3,9,8]
let mySet = new Set(arr); // 非重复的类数组
console.log(mySet,'mySet');//{{1, 5, 3, 4, 9,8}
// let newArr = Array.from(mySet); // set转数组
let newArr = [...mySet]; // 或者是这种解构方法
console.log(newArr);//[1, 5, 3, 4, 9, 8]
3.filter与indexOf结合
/* 这个过滤就很巧妙,利用索引与每一项出现的首次位置(indexOf作用)进行对比,
当符合条件的时候返回出去
*/
arr=[1,5,1,3,5,4,3,9,8]
var newArr = arr.filter((item, index) => {
return arr.indexOf(item) === index;
})
console.log(newArr);//[1, 5, 3, 4, 9, 8]
4.includes()的妙用
arr=[1,5,1,3,5,4,3,9,8]
let newArr = [];
for (let i=0;i<arr.length;i++) {
if (!newArr.includes(arr[i])) {
newArr.push(arr[i]);
}
}
console.log(newArr);//[1, 5, 3, 4, 9, 8]
5.利用对象属性来进行判断
arr=[1,5,1,3,5,4,3,9,8]
let obj = {}; // 对象的key值是唯一的
let newArr = [];
for (let i=0;i<arr.length;i++) {
if (!obj[arr[i]]) {
obj[arr[i]] = arr[i];
}
}
console.log(obj)//{1: 1, 3: 3, 4: 4, 5: 5, 8: 8, 9: 9}
事件三要素
事件是有三部分组成事件源事件类型事件处理程序这就是所谓的时间三要素。
事件源:事件被触发的对象例如一个按钮
事件类型: 如何触发 什么事件 比如鼠标点击(onclick) 还是鼠标经过 还是键盘按下
事件处理程序: 通过一个函数赋值的方式 完成
dom事件流
定义:
事件流指的是从页面中接受事件的顺序,事件发生时会在元素节点之间按照特定的顺序传播,这个传播过程即为DOM事件流。
阶段:
1.捕获阶段:事件从Document节点自上而下向目标节点传播的阶段
2.当前目标阶段:真正的目标节点正在处理事件的阶段
3.冒泡阶段:事件从目标节点自上而下向Document节点传播的阶段
作用域预解析
作用域是变量起作用和效果的范围,目的是提高程序的可靠性,为了减少命名冲突。JavaScript中有两种作用域(ES6之前没有块级作用域):全局作用域和局部作用域。
JavaScript 解析器在运行 JavaScript 代码的时候分为两步:预解析和代码执行。
预解析:JS 代码执行之前,浏览器会默认把var 和 function 声明的变量在内存中进行提升到当前作用域的最前面进行声明。
代码执行:从上到下执行JS语句。