这是我参与「第四届青训营 」笔记创作活动的第3天,以下内容就是我关于JS常考知识点的一些总结
解构赋值
数组的解构赋值
用法:用于实现数值的快速交换
let [a,b]=[10,20]
[a,b]=[b,a];
对象的解构赋值:
作用:直接根据属性名将对象提取出来
let a={name:'小明',age:12};
let {name,age}=a
//此时name和age都是一个变量
//当一个函数返回的对象很复杂
funtion createObject(){...};
let {name}=createObject();
箭头函数和普通函数的区别
- this指向不同。 普通函数是谁调用指向谁,而箭头函数没有this,只会往定义该函数的外层去找
- 普通函数可以是匿名函数,也可以是具名函数。箭头函数只能是匿名函数。
- 普通函数可以用作于构造函数,箭头函数不可以。
- 普通函数可以通过new Function()方式创建实例,箭头函数不可以。
- 箭头函数也不可以super,不可以new.target。箭头函数也不存在原型链,即prototype。
- 普通函数表现为function关键字,箭头函数表现为=>。
let obj={
name:'小明',
age:2,
sayName(){
setTimeout(function(){
console.log("我是"+this.name)},500)
//无法输出,因为this是window窗口
}
}
闭包
特点:
-
让外部访问函数内部变量成为可能
-
局部变量会常驻在内存中
-
可以避免使用全局变量,防止全局变量污染
-
会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
let module=(function(){
let a=10;
let b=20;
function add(){
return a+b;
}
function sub(){
return a-b;
}
return{
add,
sub
}
})
//此时就不会造成变量相互重名,报错等情况
防抖和节流
防抖
概念:在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
实现方法
let t=null;
ipt.oninput=function(){
if(t!==NULL){
clearTimeout(t);
}
//如果在0.5s内间隔仍在打字,那么就删除上一次的事件;
t=setTimeout(()=>{console.log(this.value)},500);
}
封装逻辑+防抖
function debounce(fn,delay){
let t=null;
return function(){
if(t!=null){
clearTimeout(t);
}
t=setTimeout(()=>{fn.call(this);},delay);
}
}
inp.oninput=debounce( (){console.log(this)},500)
//debounce返回的是一个函数,回调函数中含有一个this,而这个this是谁调用它
节流:减少执行次数
定义:指定时间间隔内只会执行一次任务。
window.onscroll=throttle()
function throttle(fn,delay){
let flag=true;
return function(){
if(flag){
setTimeout(()=>{fn.call(this);flag=true;},delay)
}
flag=false;
}
}
二者区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。
this关键词
定义:表示对当前对象的一个引用,this不是固定不变的,根据上下文改变和改变
this在不同位置所指的对象
全局环境
<script> console.log(this); // 全局环境,即window对象下,this -> window </script>
局部环境
- 全局作用域
function fun() { console.log(this); } fun(); // fun() 实际上是window.fun(), 所以this -> window
- 对象函数调用,哪个对象调用就指向哪个对象
var obj1 = { a: 1, fun1: function() { console.log(this); }, obj2: { fun2: function() { console.log(this); } } } obj1.fun1(); // fun1由obj调用,所以this -> obj1 obj1.obj2.fun2(); // fun2由obj2调用,所以this -> obj2
Tips:
- setTimeout()是在window对象中调用的方法
- 箭头函数没有this,只会在定义的地方找this,找不到就往上找
new关键词
作用:创建了一个新的对象
for in 和for of的区别
for in
- 一般用于遍历对象,遍历对象(数组)中所有可枚举的属性,包括原型方法和原型属性
- in遍历的是属性名
for of
- 一般用于遍历数组,或者一些集合,并且必须有Symbol.iterator属性才能进行迭代,否则不行
- of遍历的是属性值
对象拷贝的实现
原始类型和引用类型
原始类型:变量指向的就是数值,在栈内存中
引用类型:变量指向的就是地址,在堆内存中
let a=20;
let b=a;
a=10;
console.log(a);//10
console.log(b);//20
//原始类型
//引用类型
let a={name:'lisa'}
let b=a;
b.name='hh'
console.log('b.name');//hh
浅拷贝:
原理:重新建立一个对象,把属性值都copy给一个新对象,但对象都是引用对象
//封装成方法
function copy(obj){
let newObj={};
for(let i in obj){
newObj[i]=obj[i];
}
return newObj;
}
深拷贝:
原理:利用递归的方法,把引用类型也复制进去
let xm = {
name: '小明',
age: '12',
girlfriend: {
name: '小美'
}
}
function copy(obj) {
let newObj = {};
for (let i in obj) {
if (obj[i] instanceof Object) {
newObj[i] = copy(obj[i]);
}
else {
newObj[i] = obj[i];
}
}
return newObj;
}
let xh = copy(xm);
xh.name = '小红'
xh.girlfriend.name = '小花'
console.log(xh);
console.log(xm);
通过JSON来拷贝
方法:先把对象解析成json格式的字符串,然后把再把字符串解析成对象
function copy(obj) {
let str=JSON.stringify(obj);
let newObj=JSON.parse(str);
return newObj;
}