作用域

局部作用域

局部作用域分为函数作用域和块作用域

  • 函数作用域
    • 在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。
    • 函数的参数也是函数内部的局部变量。
    • 不同函数内部声明的变量无法互相访问。
    • 函数执行完毕后,函数内部的变量实际被清空了。
  • 块作用域:在js中使用 {} 包裹的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问(var声明的可以)
  • let 声明的变量会产生块作用域,var 不会产生块作用域。
  • const 声明的常量也会产生块作用域。
  • 不同代码块之间的变量无法互相访问。
  • 推荐使用let 或 const。

全局作用域

写在script 标签 和 js 文件的最外层的 叫全局作用域。

作用域链

作用域链的本质上是底层的变量查找机制。

  • 在函数被执行时,会优先查找当前函数作用域中查找变量。
  • 如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域。

总结:

  • 嵌套关系的作用域串联起来形成了作用域链。
  • 相同作用域链中按着从小到大的规则查找变量【子 ->父】
  • 子作用域能访问父作用域,父作用域无法访问子级作用域。

垃圾回收机制

内存的生命周期

JS环境中分配的内存,一般有如下的生命周期:

  • 内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存。
  • 内存使用:即读写内存,也就是使用变量、函数等。
  • 内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存。

说明

  • 全局变量一般不会回收【关闭页面回收】
  • 一般情况下局部变量的值,不用了,会被自动回收掉

内存泄漏

  • 程序中分配的内存 由于某种原因程序未释放或无法释放 叫做内存泄漏。

堆栈空间分配区别

  • 栈:由操作系统自动分配释放函数的参数值、局部变量等,基本数据类型放到栈里面
  • 堆:一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收,复杂数据类型放到堆里面

垃圾回收算法

  • 引用计数法:【内存不再使用就回收,跟踪记录被引用的次数】
  • 标记清除法:【找不到就清除,从全局对象出发定期扫描内存中的对象,找得到就留着,找不到就回收】

闭包

闭包 = 内层函数 + 外层函数的变量【就是 里层函数+外层函数的变量】

  • 作用:外部也可以使用函数内部的变量。
  • 应用:实现数据的私有化。

变量和函数提升

变量提升

执行过程:在代码执行之前,他会把当前作用域下,所有var声明的,提升到当前作用域之前。【只提升声明,不提升赋值】

函数提升

  • 会把所有函数声明提升到当前作用域的最前面。【只提升函数声明,不提升函数调用 】
  • 函数表达式【 var fun = function(){} 】必须先声明和赋值,后调用,否则会报错。

arguments【动态参数】

arguments是函数内部内置的维数组变量,它包含了调用函数时传入的所有实参。【当不确定传递多少个实参的时候,就用它】

  • arguments是一个伪数组【不可以用数组的方法】只存在于函数中
  • arguments 的作用是动态获取函数的参数
  • 可以通过for 循环依次得到传递过来的实参

剩余参数

  • …是语法符号,用于获取多余的实参
  • 借助 … 获取的剩余参数,是个真数组
  • 使用的时候不需要…
  • 只存在于函数里面

展开运算符

  • 展开运算符(…),将一个数组、对象进行展开。
  • 他不会修改原数组。
  • 使用场景:求数组最大值、合并数组等【 Math.max(…arr) 、console.log(…arr1,…arr2) 】

箭头函数

  • 只有一个参数的时候可以省略()
  • 只有一行代码的时候可以省略 {} 和 return
  • const fn = () =>{}
  • 可以直接返回一个对象,但是必须加():const fn = uname =>({name:uname})
  • 箭头函数属于表达式函数,因此不存在函数提升。

参数

  • 普通函数有 arguments 动态参数
  • 箭头函数没有arguments 动态参数,只有剩余参数(…arr)

this

  • 箭头函数的this 是上一层作用域的this 指向
  • 对象方法中的箭头函数,this指向上一层作用域()

解构赋值

数组解构

数组解构就是将 数组的单元值快速批量赋值一系列变量的简介语法。

赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量。

案例:交换变量

  • 注意:第二行必须有 ;
  • js 前面必须加分号的两种情况:
    • 立即执行函数:(function t(){})(); 或者 ;(function t(){})()
    • 数组解构:;[b,a] = [a,b]【以数组开头的】

总结:

  • 变量多,单元值少:最后一个变量undefined
  • 变量少,单元值多:const[a,b] = [1,2,3],a和b的值为 1,2【可以利用剩余参数解决,但只能置于最末位】
  • 防止 undefined 传递:const[a=0,b=0] = []
  • 按需导入,忽略某些值:const[a,b,,d] = [1,2,3,4]【d是4,位置空下来了,要留位置】
  • 多维数组解构:const [a,b,[c,d]] = [1,2,[3,4]]

对象解构

  • const {uanme,age} = {uname:’j’,age:1}【这种方式前后属性名必须一致】

  • const {uanme:name,age} = {uname:’j’,age:1}【旧变量名:新变量名】
  • 数组对象解构:
    • const [{name,age}] = [{name:’q’,age:9}]

    • 多级对象解构:

      const pp = {nam:'佩奇',family:{mother:'mama',father:'baba',sister:'乔治'},ag:6} const {nam,family:{mother,father,sister},ag} = pp

forEach

  • forEach() 方法用于遍历数组对象的每个元素,并将元素传递给回调函数
  • 语法:
    const aa = [1,2,3,4,5]aa.forEach(function(item,index){console.log(item)})

创建对象

  • const p = {name:’k’}【利用字面量】

  • const p = new Object({name:’k’})【利用new object】

  • 利用(自定义)构造函数来创建对象

    • 实例化过程:

      • 创建空对象

      • 构造函数this 指向新对象

      • 执行构造函数代码

      • 返回新对象(构造函数里面不需要写return)

Object

  • object.key() 获得所有属性名
  • object.value() 获得所有属性值
  • object.assign(拷贝给谁,要拷贝谁) 常用于对象拷贝

Array常见方法

  • forEach : 不返回数组,经常用于查找遍历数组元素。
  • filter:返回新数组,返回的是筛选满足条件的数组元素。
  • map :返回新数组,返回的是出路之后的数组元素。
  • reduce :返回累计处理的结果,经常用于求和
    • 语法:arr.reduce(function(上一次的值,当前值){},初始值)。
    • 如果有初始值,则把初始值累加到里面。
  • join :数组元素拼接为字符串,返回字符串。
  • find :查找元素,返回复测的第一个数组元素值,如果没有符合的就返回undefined。
    •  const arr = [{name:'小米',price:100},{name:'苹果',price:1000}]// 找小米并且返回这个对象 const a = arr.find(item =>item.name === "小米") console.log(a);
  • every:检测数组所有元素都符合(必须每一个都是)指定条件,如果所有元素都通过检测,返回true,否则false 。
  • some:检测数组中的元素是否满足指定条件,如果数组中有元素满足条件返回true,否则false。(只要有一个满足
  • concat:合并两个数组,返回生成新数组。
  • sort:对原数组单元值排序。
  • splice:删除或替换原数组单元。
  • reverse:翻转数组。
  • findIndex:查找元素的索引值。
  • Array.from():把伪数组转换为真数组。

字符串常见方法

  • length:获取字符串长度。
  • split(‘分隔符’):用来将字符串拆分成数组。(通过分割符,来分割)
     // 把字符串转换为数组 let a = 'red,pick,kil,kkk' console.log(a.split(','))
  • substring():字符串的截取。(开始,结束),左包右不包、结束可以省
     let b = 'redpickikkk' console.log(b.substring(0,4))//redp
  • startsWith():检测是否以某字符串开头
    let b = 'redpickikkk' console.log(b.startsWith('a'))//false console.log(b.startsWith('r'))//true
  • includes():判断一个字符串是否包含在另一个字符串中
    let b = 'redpickikkk'console.log(b.includes('dpick'));//trueconsole.log(b.includes('dik'));//false
  • toUpperCase:将字母转换成大写。
  • toLowerCase:转换成小写。
  • indexOf:检测是否包含某字符。
  • endsWith:检测是否以某字符串结尾。
  • replace:用于替换字符串。(支持正则)
  • match :用于查找字符串(支持正则)。

原型

  • 原型是什么?:一个对象,我们也称为prototype 为原型对象
  • 作用:共享方法。可以把那些不变的方法,直接定义在prototype对象上。
  • 构造函数和原型里面的this ,指向实例化对象

constructor