闭包 深拷贝浅拷贝 原型相关的 ajax 相关的
1.作用域:
作用域就是一个变量可以使用的范围,主要分为全局作用域和函数作用域
全局作用域就是Js中最外层的作用域
函数作用域是js通过函数创建的一个独立作用域,函数可以嵌套,所以作用域也可以嵌套
Es6中新增了块级作用域(由大括号包裹,比如:if(){},for(){}等)
2.自由变量:
当前作用域外的变量都是自由变量,作用域链就是 自己没有这个变量就从上一级作用域查找,直到找到为止,直到找到顶层window,没有的话就报错
3.变量提升:
每个var声明的变量,function声明的函数存在变量提升。变量和函数都有声明提升,let const不存在变量提升
会把声明语句提到代码的最顶端,赋值语句留在原地等待执行
Var a=10 var a会被提升 a=10会留在原地
(在js中声明之前未定义,会在js的最上方会形成一个预解析池,用来存储声明了但没有先定义的变量名)
简单的理解就是函数中套了一个函数,内层函数可以访问外层函数中的变量
有时候需要用到函数内的局部变量,在正常情况下是不能读取到的,这个时候就需要用到闭包。
闭包可以封装对象的私有属性和方法,vue 中的 data 就是一种闭包的形式。
闭包作为回调函数,可以实现函数的复用
优点:闭包因为长期驻扎在内存中。可以重复使用变量,不会造成变量污染
缺点:闭包会使函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,可能会导致内存泄露。解决方法是在退出函数之前,将不使用的变量全部删除。
在 js 中 this 不是固定不变的,它会随着执行环境的改变而改变。要注意的是 this 取什么值,是在执行时确认的,定义时无法确认。
this 的调用大概分为五种场景: 1.浏览器里,在全局范围内的 this 指向 window 对象; 2.在函数中,this 永远指向最后调用他的那个对象; 3.构造函数中,this 指向 new 出来的那个新的对象; 4.箭头函数中 this 比较特殊,箭头函数 this 为父作用域的 this,不是调用时的 this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的 this 指向是静态的,声明的时候就确定了下来;
有三个方法改变 this:
call:参数是单个使用的,
apply:参数是一个数组
call 和 apply 都会立刻调用这个函数
bind:只改变 this 不会让函数立刻调用
深拷贝和浅拷贝的区别
1.浅拷贝: 将原对象的引用直接赋给新对象,新对象只是原对象的一个引用,而不复制对象本身,新旧对象还是共享同一块内存
2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”,新对象跟原对象不共享内存,修改新对象不会改到原对象
为什么要使用深拷贝?
我们希望在改变新的数组(对象)的时候,不改变原数组(对象)
数组的深拷贝
let arr2 = arr.concat();
对象的深拷贝
第一种方法:
let obj2 = JSON.parse(JSON.stringify(obj));
第二种方法是递归
function deepcopy(obj) {
let obj2 = {};
for (let key in obj) {
if (obj[key] instanceof Object) {
obj2[key] = deepcopy(obj[key]);
} else {
obj2[key] = obj[key];
}
}
return obj2;
}
let obj2 = deepcopy(obj);
obj2.info.age = 25;
console.log(obj, obj2);
ES5中的继承 (组合继承:原型链继承 + 借用构造函数)
原型链继承:
父类的实例作为子类的原型
只能继承 原型上的方法 不能继承构造函数里的属性和方法
借用构造函数继承:
在子类内,使用call()调用父类方法,并将父类的this修改为子类的this.相当于是把父类的实例属性复制了一份放到子类的函数内.
只能继承构造函数里的属性和方法 不能继承原型上的
组合继承:
既能调用父类实例属性,又能调用父类原型属性
Es6的继承
Class cat extends 父类
然后在constructor中定义super 可以设置继承父类的哪些属性
(具体实现:
1.实例继承
父类的实例作为子类的原型
比如父类 是People 子类是Woman
Woman.prototype= new People();
(优点:简单易于实现,父类的新增实例与属性子类都能访问
缺点:
1).可以在子类中增加实例属性,如果要新增加原型属性和方法需要在new 父类构造函数的后面
2)无法实现多继承
3)创建子类实例时,不能向父类构造函数中传参数)
2.借用构造函数继承(伪造对象、经典继承)
比如父类 是People 子类是Woman
function Woman(name){
//继承了People
People.call(this); //People.call(this,'tom);
}
优点:
1)解决了子类构造函数向父类构造函数中传递参数
2)可以实现多继承(call或者apply多个父类)
缺点:
1)不能继承原型属性/方法,只能继承父类的实例属性和方法
3.原型链继承
Woman.prototype= People.prototype
优点:
1)不限制调用方式
2)简单,易实现
缺点:
只能继承 原型上的方法 不能继承构造函数里的属性和方法
4.组合式继承
调用父类构造函数,继承父类的属性,通过将父类实例作为子类原型,实现函数复用
function Woman(name,age){
People.call(this,name,age)
}
Woman.prototype =People.prototype
优点:
1)可以继承属性和方法,并且可以继承原型的属性和方法
Es6的继承
Class cat extends 父类
然后在constructor中定义super 可以设置继承父类的哪些属性
(ES5继承和ES6继承的区别:
es5继承首先是在子类中创建自己的this指向,最后将方法添加到this中
Child.prototype=new Parent() || Parent.apply(this) || Parent.call(this)
es6继承是使用关键字先创建父类的实例对象this,最后在子类class中修改this)
)
数据类型判断大概有四种typeof、instanceof、constructor、Object.prototype.toString.call()
比如说检测num=10的数据类型
1.Type:
typeof检测数据类型会返回对应的数据类型小写字符。
引用数据类型中的:Array,Object,Date,RegExp。不可以用typeof检测。都会返回小写的object
console.log(typeof num);
2 . instanceof
除了使用typeof来判断,还可以使用instanceof。instanceof运算符需要指定一个构造函数,或者说指定一个特定的类型,它用来判断这个构造函数的原型是否在给定对象的原型链上。
console.log(arr instanceof Array);
3.constructor
constructor是prototype对象上的属性,指向构造函数。我们可以用实例的隐式原型去找到构造函数的值。
console.log(num.proto.constructor);
4 . 使用Object.prototype.toString.call()检测对象类型
可以通过toString() 来获取每个对象的类型。每个对象都能通过 Object.prototype.toString() 来检测
console.log(Object.prototype.toString.call(num));
1.创建xhr 核心对象
var xhr=new XMLHttpRequest();
2.调用open 准备发送
参数一:请求方式
参数二: 请求地址
参数三:true异步,false 同步
xhr.open(‘post’,‘http://www.baidu.com/api/search’,true)
3.如果是post请求,必须设置请求头。
xhr.setRequestHeader(‘Content-Type’, ‘application/x-www-form-urlencoded’)
4.调用send 发送请求 (如果不需要参数,就写null)
xhr.send(‘user=tom&age=10&sex=女’)
5.监听异步回调 onreadystatechange
判断readyState 为4 表示请求完成
判断status 状态码 为 200 表示接口请求成功
responeseText 为相应数据。字符串类型。
xhr.οnlοad=function(){
if(xhr.readyState4){
if(xhr.status200){
console.log(xhr.responseText);
var res=JSON.parse(xhr.responseText);
console.log(res);
if(res.code==1){
modal.modal(‘hide’);
location.reload();
}
}
}
备注:如果是post请求,想要传json格式数据。
设置请求头
1.xhr.setRequestHeader(‘Content-Type’, ‘application/json’)
open发送数据
2.xhr.open({_id:xxx,user:xxxx,age:xxxx})
跟this指向的答案背一样就行
1.浏览器里,在全局范围内的this 指向window对象;
2.在函数中,this永远指向最后调用他的那个对象;
3.构造函数中,this指向new出来的那个新的对象;
4.Call、apply、bind中的this被强绑定在指定的那个对象上;
5.箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
6.apply、call、bind都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参。
JSONP原理:
ajax 请求受同源策略影响,不允许进行请求,我们利用 script 标签的 src 属性不受同源策略的约束,利用这个特性jsonp需要以下步骤:
1.动态创建添加到页面中执行 (body.appendChild(‘script’))
4.页面要提前定义好callback。
5.后端会返回回调函数执行并包裹参数callback(data)
备注:
服务端不再返回JSON格式的数据,而是返回回调函数包裹数据(fn({name:‘tom’,age:18}),在src中进行了调用,这样实现了跨域。
1.push() 可以添加一个或多个参数到数组的尾部,添加之后原来的数组会发生改变,返回的是添加后的数组的长度
2.pop() 从数组尾部删除一个元素,原数组会发生改变,返回数组中被删除的元素
3.unshift() 可以添加一个或多个参数到数组的头部,添加后原来的数组会发生改变,返回的是添加后的数组的长度
4.shift() 从数组头部删除一个元素,原数组会发生改变,返回数组中被删除的元素
5.slice() 从数组中截取,如果不传参,会返回原数组。返回截取的值,两个参数 一个是开始的位置,第二个是结束的位置,原数组不变,最多两个参数
6.splice()截取类 没有参数,返回空数组,原数组不变;一个参数,从该参数表示的索引位开始截取,直至数组结束,返回截取的 数组,原数组改变;两个参数,第一个参数表示开始截取的索引位,第二个参数表示截取的长度,返回截取的 数组,原数组改变;三个或者更多参数,第三个及以后的参数表示要从截取位插入的值。
7.reverse() 数组翻转
8.sort() 数组排序
9.join() 数组拼接
10.isArray() 判断是否是数组
11.toString() 数组转字符串
12.concat( ) 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组
遍历数组的方法 它们的参数都是回调函数
forEach 循环 没有return 对原数组发生改变
filter 返回所有满足条件的新数组 返回值就是新数组
map 遍历数组,可重新构建一个新的数组 返回值就是新数组
find 查找数组中满足条件的第一个数组项 返回这个数组项
findIndex 查找数组中满足条件的第一个数组项的索引 返回这个数组项的索引或者-1
some 遍历数组中,数组中至少有一个满足条件的数组项,返回true 否则false
every 遍历数组 所有的数组项都满足条件时 返回ture 否则 false
深拷贝拷贝的是值 浅拷贝拷贝的是地址
深拷贝和浅拷贝的区别 1.浅拷贝: 将原对象的引用直接赋给新对象,新对象只是原对象的一个引用,而不复制对象本身,新旧对象还是共享同一块内存
2.深拷贝: 创建一个新的对象和数组,将原对象的各项属性的“值”(数组的所有元素)拷贝过来,是“值”而不是“引用”,新对象跟原对象不共享内存,修改新对象不会改到原对象
基本数据类型存储在栈中
引⽤类型的对象存储于堆中
数据类型判断大概有四种 typeof、instanceof、constructor、Object.prototype.toString.call()
比如说检测 num=10 的数据类型
1.Type:
typeof 检测数据类型会返回对应的数据类型小写字符。
引用数据类型中的:Array,Object,Date,RegExp。不可以用 typeof 检测。都会返回小写的 object
console.log(typeof num);
2 . instanceof
除了使用 typeof 来判断,还可以使用 instanceof。instanceof 运算符需要指定一个构造函数,或者说指定一个特定的类型,它用来判断这个构造函数的原型是否在给定对象的原型链上。
console.log(arr instanceof Array);
3.constructor
constructor 是 prototype 对象上的属性,指向构造函数。我们可以用实例的隐式原型去找到构造函数的值。
console.log(num.proto.constructor);
4 . 使用 Object.prototype.toString.call()检测对象类型
可以通过 toString() 来获取每个对象的类型。每个对象都能通过 Object.prototype.toString() 来检测
console.log(Object.prototype.toString.call(num));