概念
区别:
总结:undefined 和 null 从本质上是不同的。undefined定义而未赋值,但null主要是指空对象指针
二、 面试题:
a) null:
var person = null;//定义了一个引用类型,没有指向。
alert(person); //输出null。
alert(typeof person);//输出object,person的数据类型是Object,值是null
b) undefined:
var a; //JavaScript中定义一个变量,没有赋值时,默认为undefined
alert(typeof a); // undefined
alert(b); // 报错,因为b没有定义。所有,在浏览器的控制台中会报 b is not defined
==可以理解为等同,会尝试进行类型转换
1、如果两个值类型相同,进行 === 比较。
2、如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较:
1)如果一个是null、一个是undefined,那么[相等]。
2)如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。
3)如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
4)任何其他组合,都[不相等]。
===可以理解为绝对等或恒等,是数据和类型都相等
1、如果类型不同,就[不相等]
2、如果两个都是数值,并且是同一个值,那么[相等]。
3、如果两个都是字符串,每个位置的字符都一样,那么[相等];否则[不相等]
4、如果两个值都是true,或者都是false,那么[相等]。
5、如果两个值都引用同一个对象或函数,那么[相等];否则[不相等]。
6、如果两个值都是null,或者都是undefined,那么[相等]。
在switch结构中,是==还是===。
答: ===
this是什么?
this是函数的内置对象,this是代词,顾名思义this代表哪个对象,要看函数属于哪种情况。
this指向有四种情况:
1)、当this所在函数是事件处理函数时,this代表触发该事件的元素;
2)、当this所在函数是构造函数时,this代表new出来的对象;
3)、当this所在函数是类的方法时,this代表调用该方法的对象;
4)、当this所在函数没有明确的所属对象或指向时,this代表window对象。
箭头函数根本没有自己的this,他内部的this就是外层代码块的this
ps:注意,this具体表示什么意思,更多要看调用,要看运行,因外在调用时,有可能this的指向会被改变。
ps:this指向需要注意:es5,是谁调用this,this指向谁;es6中,不管谁调用this,this指向定义他的对象。
call和apply的区别待完善?
区别
1)写法格式上不同;
2)箭头函数不能作为构造函数使用;
3)箭头函数中没有this和arguments;arguments详解
4)箭头函数不具有prototype原型对象
5)箭头函数不具有super;super是什么?
箭头函数解决了哪些问题?
1)箭头函数使函数表达更加简洁
2)解决了this指向的问题
ps:使用场景:
1.简单的函数表达式,内部没有this引用,没有递归,事件绑定,解绑定
2.内层函数表达式,需要调用this,且this应与外层函数一致时(保证指向vue实例)
不要问什么是重点,重点就是全部
//1)、创建一个XMLHttpRequest对象;
let xhr = new XMLHttpRequest();
//2)、规划一个请求;
//get方式
xhr.open("get", "url?username=kalrry&userpass=123", true);
//post方式
xhr.open("post", "url", true);
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded")
//3)、发送请求
//get方式
xhr.send();
//post方式
xhr.send("name=kalrry&age=18");
//4)、接收来自服务端的响应;
xhr.onreadystatechange = function () {
if (xhr.readystate == 4 && xhr.status == 200){
xhr.responseText//后端响应的内容
}
}
老版本浏览器(IE5、IE6)的兼容写法:
//1、创建ActiveXObject()对象
//var xml = new ActiveXObject("Microsoft.XMLHTTP");
val xml;
if (window.XMLHttpRequest){
xml = new XMLHttpRequest();
}else{
xml = new ActiveXObject("Microsoft.XMLHTTP");
}
onreadystatechange事件
//当向服务器发送数据请求过程中,readyState的值发生改变时触发onreadystatechange事件
//readyState存有XMLHttpRequest的状态,从0~4发生变化
//0:代表请求未初始化
//1:代表已经与服务器建立连接
//2:服务器收到请求
//3:请求正在处理
//4:请求已完成,且响应已就绪
status的常见两种状态
//200:代表ok,数据响应完成并成功返回
//404:代表前端地址错误
function ajax2110UseObj(obj){
let defaultObj = {
method:"get",
url:"#",
params:"",
callback:null,
isAsync:true
}
for(let key in defaultObj){
// 把obj里没有传入的属性使用defaultObj的对应属性。
if(obj[key]==undefined){
obj[key]=defaultObj[key];
}
}
// 1、创建XMLHttpRequest对象
let xhr = new XMLHttpRequest();
// 2、设置请求相关信息
let urlAndParams = obj.url;
if(obj.method.toLowerCase()=="get"){
urlAndParams += "?"+obj.params
}
xhr.open(obj.method,urlAndParams,obj.isAsync);
// 3、设置回调函数(后端响应时,调用的函数)
xhr.onreadystatechange = function(){
if(xhr.readyState==4 && xhr.status==200){
obj.callback && obj.callback(xhr.responseText);
}
}
if(obj.method.toLowerCase()=="get"){
// 4、发送请求
xhr.send();
}else if(obj.method.toLowerCase()=="post"){
// 如果是post方式,必须设置请求头。
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(obj.params);
}
}
0:表示刚创建好XMLHttpRequest对象
1:open函数调用完毕后,
2:表示后端接收到了响应
3:表示后端正在处理
4:表示后端处理完毕(即:请求响应的过程结束了)
// readyState==4:表示请求响应的过程完毕
HTTP请求响应系列02_响应报文的详解
深浅拷贝特指引用类型
深浅拷贝的区别:
深拷贝: 把引用类型的地址及其它的数据都拷贝一份;
浅拷贝: 只拷贝了引用类型的地址;
如何进行深拷贝,并举例
如何进行深拷贝:
深拷贝的思路:
创建空对象,循环原对象的每个键,一一 赋值给空对象,并使用递归的方式,把对象属性也进行复制,以下为示例代码:
例一:
// 功能:封装一个深拷贝的函数
// 参数:被拷贝的对象
// 返回值:拷贝的对象
function copyObj(obj){
let newObj ={};
for(let key in obj){
if(typeof obj[key] == "object"){ //如果说当前属性是对象的话,那么再做深拷贝
newObj[key] = copyObj(obj[key]);
}else{
newObj[key] = obj[key];
}
}
return newObj;
}
var obj1= {
name:"张三疯",
sex:"男",
address:{
province:"陕西",
city:"西安"
}
}
let obj2 = copyObj(obj1);
例2:待修改
//json方式实现深拷贝
var obj={
"id":"00001",
"name":"奚大官人",
"age":"31",
"sex":"female",
}
var deepObj=JSON.parse(JSON.stringify(obj))//JSON.stringify,将对象转化成字符串,字符串是基本的数据类型,意味着此时在开辟空间区存这个字符串,我们在存好的这个空间中,将字符串转换为对象
deepObj.sex="male"
console.log(obj)
console.log(deepObj)
深浅拷贝详解
then方法:
功能:把then方法的参数传给resolve和reject。 promise对象.then(resolve回调函数,reject回调函数);
参数:
then方法的第一个参数是resolve
then方法的第二个参数是reject
返回值:promise对象本身,所以,then调用完毕后,还可以继续调用then(即:链式调用)
catch
catch方法:
它和then的第二个参数一样,用来指定reject的回调,
5)类方法: all、race
all方法:
功能: Promise.all可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据。返回的数据与传的参数数组的顺序是一样的。当所有的异步操作都成功才表示成功 。
参数:数组。数组里是若干个返回promise对象的函数(异步操作);
返回值:promise对象。promise对象的then方法的回调函数的参数是 所有promise对象的resolve的参数(数组形式)
race方法:
功能:也是并发,但是,与all不同之处时,当一个异步操作完成(resolve或reject)时,就调用方法了。即:多个异步操作,同时执行,谁快就用谁的结果,所以,结果不再是数组。
new Promise(function(resolve,reject){undefined
异步代码
})
//promise(reject,resolve,pending)
new Promise(function(resolve){
setInterval(()=>{
resolve(1)
},1000)
}).then((num)=>{
console.log(num*3)
// alert(1*3)
return num*3
}).then((num)=>{
console.log(num*3)
// alert(1*3)
})
点击跳转至大佬级理解
function unique(arr) {
var arr1 = [];
for (var i = 0; i < arr.length; i++) {
if (arr1.indexOf(arr[i]) == -1) {
arr1.push(arr[i]);
}
}
return arr1;
}
console.log(unique([1,1,2,2,3,3,3,4,5,6,6,6,7]));//1,2,3,4,5,6,7
// 第一种:
function unique(arr){
return [...new Set(arr)]
}
console.log(unique([1,2,1,2,2,3,2,1]));
// 第二种
let arr = [1,2,3,1,2,5,5,3,4];
let set = new Set(arr);
arr = Array.from(set);
console.log(arr);
1、push 尾增
2、pop 尾删
3、unshift 头增
4、shift 头删
5、concat 数组拼接
6、join 数组转字符串
7、reverse 逆序
8、sort 按字符串UniCode码排序
9、map 对数组的每个元素做某个处理,参数是回调函数,并且有返回值
10、slice 数组截取,在vue中与计算属性搭配,返回截取的内容用来渲染页面
11、indexOf 查找数组中的元素,找到返回该元素下标, 没找到返回-1
12、splice 截取,会改变原数组
13、filter 根据回调函数过滤相应内容并返回过滤后的数组
14、every 对数组中的每一项进行判断,若都符合则返回true,否则返回false
15、some 对数组中的每一项进行判断,若都不符合则返回false,否则返回true
16、reduce:将数组所有数值进行叠加返回
18、forEach 对数组的每个元素做某个处理,参数是回调函数
const array1 = [5, 12, 8, 130, 44];
const found = array1.find(element => element > 10);
console.log(found);//12
filter:主要是用来过滤数组内容,返回一个新数组 是原数组中符合回调函数条件的所有元素。
什么是闭包?
闭包: 从结构上看,闭包的实质就函数嵌套函数,也就是定义在函数内部的函数,并且这个内部函数能够访问到外层函数中定义的局部变量,内部函数也可以当作外层函数的返回值被调用,当其中一个内部函数在包含他们的外部函数之外被调用时,就形成了闭包。
解释一下就是:外层函数被调用后,外层函数的作用域对象无法被释放,被内层函数继续引用着,就形成了闭包
何时使用闭包: 即想要重用一个变量,又想保护变量不被污染时,在此种情况下使用
如何使用,分三步走:
1)用外层函数包裹要保护的变量和内层函数
2)外层函数将内层函数返回到外部
3)调用外层函数,获得内层函数的对象,保存在外部变量中–形成了闭包
闭包的作用及特点
1)函数嵌套函数
2)函数内部可以引用外部的参数和变量
3)局部变量会常驻内存
4)使用过后的参数和变量不会被垃圾回收机制回收垃圾回收机制
5)
闭包的优点
1)变量长期驻扎在内存中
2)避免全局变量的污染,仅函数内可用,不会被污染
3)私有成员的存在(待解释…)
闭包的缺点?如何解决?
缺点:比普通函数占用更多内存空间,过多使用会影响性能,易造成内存泄漏
解决:闭包不在使用时,要及时释放,将引用的内存函数对象的变量赋值为null。
// 没有进行空间的开辟
var obj = {
a: "1",
b: "2",
c:{
id:"0001"
}
}
var newobj={
...obj
}
newobj.c.id="kalrry"
console.log(obj)
console.log(newobj)
NaN概念:NaN不是一个数字且数据类型为number,而且不等于自身
如何判断
function isNaN(n){
if(n!=n){
return true;
}else{
returu false;
}
}
var a = NaN;
console.log(a == a);
//false;
console.log(Object.is("a",NaN));
console.log(Object.is(1,NaN));
console.log(Object.is(NaN,NaN));