JS进阶-零碎知识点记录
1.作用域:
局部作用域(函数作用域、块作用域{})
- let声明的变量会产生块作用域,var不回产生块作用域
- const声明的常量也会产生块作用域
- 推荐使用let或const
全局作用域
- 为window对象动态添加的属性默认为全局,不推荐
- 函数中未使用任何关键字声明的变量为全局,不推荐
- 尽可能少的声明全局变量,防止全局变量被污染
2.作用域链:优先查当前函数作用域,没有的话依次逐级查找父级作用域直至全局作用域
3.垃圾回收机制:全局变量一般不会受。
算法说明:
引用计数:IE采用的引用计数算法, 定义“内存不再使用”,就是看一个对象是否有指向它的引用,没有引用了就回收对象。(但存在致命问题:嵌套引用,如果两个对象相互引用,尽管他们已不再使用,却不会被垃圾回收器回收,导致内存泄露)
标记清除:现代浏览器通用的大多是基于标记清除算法的某些改进算法,其核心如下:
1.标记清除算法将“不再使用的对象”定义为“无法达到的对象”
2.就是从根部出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要的。
3.那些无法由根部出发触及到的对象被标记被不再使用,稍后进行回收
4.闭包:一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域。(闭包=内层函数+外层函数的变量)
作用:封闭数据,提供操作,外部也可以访问函数内部的变量。
应用场景: 1.封装私有变量和函数 2.维护变量的生命周期(可以使变量的生命周期长于函数的声明周期) 3.模拟块级作用域 4.实现高阶函数 5.实现回调函数 6.实现模块化

生命周期理解:fn是fun的父函数,fun被赋给了一个全局变量,fun始终存在内存中,fun的存在依赖fn,因此fn也始终存在内存中,不会在调用结束后,被垃圾回收机制回收。
优点:1.避免全局变量的污染 2.能够读取函数内的变量 3.可以在内存中维护一个变量
缺点:2.闭包会常驻内存,容易造成内存泄露,解决方法是,将不使用的局部变量全部删除 (设置为null)
5.变量提升:允许变量在声明之前被访问(仅存在于var声明变量,不推荐)
优点:
- 便于代码阅读:可以先声明变量或函数,然后在代码中进行使用。
- 函数可以在调用前声明:函数声明被提升后,可以在代码中的任何位置调用。
- 可以在函数内部声明局部变量,使得变量只在该函数内部可用。
缺点:
- 可能会导致不可预期的行为:变量提升可能会导致在代码中声明的变量无法达到预期的结果。
- 难以调试:由于变量和函数的声明在代码中的位置不同于它们的实际执行位置,因此可能会导致调试代码时的困难。
- 可能会影响代码性能:在代码中声明变量和函数的过多使用可能会影响代码的性能。
6.函数参数
动态参数arguments:函数内部内置的伪数组变量,包含了调用函数时传入的所有实参,可以通过for循环依次得到实参
剩余参数:function getSum(baseNum,...other),允许将一个不定数量的参数表示为一个数组,借助...获取的剩余实参,是个真数组(推荐)
7.真数组和伪数组的区别:
- 伪数组是一个对象(Object),而真实的数组是一个数组(Array)
- 拥有length属性,且
必须是number类型,其它属性(索引)为字符串不具有数组所具有的方法,forEach()等,不过有Object的方法 - 伪数组
长度不可变,真数组长度可以变 - 可以通过
for in遍历
8.箭头函数:引入箭头函数的目的是更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁
使用场景:箭头函数更适用于那些本来需要匿名函数的地方
函数参数:没有动态参数arguments,有剩余参数...args
this:不会创建自己的this,只会从自己作用域链上一层沿用this
9.解构赋值:一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值
数组解构:将数组的单元值快速批量赋值给一系列变量的简洁语法


对象解构:将对象属性和方法快速批量赋值给一系列变量的简洁语法。

10.filter 筛选数组:返回的是新数组,不会影响原数组。
11.创建对象的三种方式

12.构造函数:一种特殊的函数,主要用来初始化对象。

两个约定:1.命名以大写字母开头 2.只能由“new" 操作符来执行(实例化)
13.实例成员&静态成员:
通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员,构造函数的属性和方法被称为静态成员。
14.内置构造函数:
引用类型:Object、Array、RegExp、Date等
包装类型:String、Number、Boolean等
15.原型:一个对象,prototype(prototype的诞生初衷是为了节约内存)
- 构造函数通过原型分配的函数是所有对象所共享的
- 这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
- 可以通过原型对构造函数的属性和方法进行扩展
- 我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
- 构造函数和原型对象中的this都指向 实例化的对象

16.constructor 属性:每个原型对象都有constructor属性,该属性指向该原型对象的构造函数
17._proto_ 属性:指向构造函数的prototype 原型对象,(其对象原型中也有constructor属性,指向创建该实例对象的构造函数)
18.深拷贝常用方法:1.递归 2.lodash/cloneDeep 3.JSON.stringify()
19.Error对象配合throw使用,能够设置更详细的错误信息 throw new Error('xxxx!')
20.this指向
普通函数:谁调用this值指向谁;没有明确时,this值为window;严格模式下指向undefined
箭头函数:本身不存在this,绑定的是外层this的值;事件回调函数使用箭头函数时,this为window;dom事件函数、构造函数、原型函数都不推荐使用箭头函数,需要使用上层this的地方推荐使用。
21.改变this指向
call():使用call方法调用函数,同时指定被调用函数中的this的值。 ----了解
语法:fun.call(thisArg,arg1,...)
apply():使用apply方法调用函数,同时指定被调用函数中this的值。 ----理解
语法:fun.apply(thisArg,[argsArray])
bind():不调用函数,但是能改变函数内部this指向 -----重点
语法:fun.bind(thisArg,arg1,...) ,返回由指定this值和初始化参数改造的原函数拷贝(新函数)
相同点:都可以改变函数内部this指向
区别点:
- call、apply会调用函数,并且改变函数内部this指向
- call、apply传递参数不通,apply必须数组形式
- bind不会调用函数,可以改变函数内部this指向
主要应用场景:
- call调用函数并且可以传递参数
- apply经常跟数组有关系
- bind不调用函数,但是还想改变this指向,比如改变定时器内部的this指向
22.性能优化:
节流:连续触发事件但是在n秒内只执行一次。场景:鼠标移动,页面尺寸变化,滚动条等开销较大情况使用。
防抖:触发事件后n秒内只能执行一次,如果n秒内又触发了事件,则会重新计算函数执行时间。场景:搜索框输入。

浙公网安备 33010602011771号