JS常考知识点 | 青训营笔记

56 阅读4分钟

这是我参与「第四届青训营 」笔记创作活动的第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>

局部环境

  1. 全局作用域
function fun() { console.log(this); } fun(); // fun() 实际上是window.fun(), 所以this -> window
  1. 对象函数调用,哪个对象调用就指向哪个对象
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;
        }