前端JS-Day26

作用域:规定了变量能够被访问的范围。

1.局部作用域:

① 函数作用域:在函数内部声明的变量只能在函数内部被访问,外部无法直接访问。

注意:Ⅰ函数的参数也是函数内部的局部变量。Ⅱ函数执行完毕,函数内部变量被清空(垃圾回收机制)。

② 块作用域:只要是被{}包裹的代码称为代码块,外部可能无法访问。只有当var声明的变量可以被访问。

注意:Ⅰlet和const声明的变量会产生块作用域,var不会产生。Ⅱ不同代码块之间的变量无法互相访问。Ⅲ推荐使用let和const

2.全局作用域:<script>标签和.js文件的最外层就是全局作用域,全局作用域中声明的变量,任何其他作用域都可以访问。

① 为window对象动态添加属性默认是全局的。② 函数中未用任何关键字声明的变量也是全局变量。 ③ 尽可能少的声明全局变量,防止全局变量被污染。

 

作用域链:本质是底层的变量查找机制。(就近原则)

① 在函数被执行时,会优先查找当前作用域中的变量。

② 若当前作用域查找不到,则会依次逐级查找父级作用域直到全局作用域。

嵌套关系的作用域串联起来形成了作用域链,相同作用域链按照从小到大的规则依次查找变量,子级作用域可以访问父级作用域,父级作用域无法访问子级作用域。

 

JS垃圾回收机制GC:JS中内存的分配和回收都是自动完成的,内存不使用的时候会被垃圾回收器自动回收。

不再用到的内存,没有及时释放,就叫做内存泄漏

内存生命周期:

1.内存分配:声明变量、函数、对象时,系统自动分配内存。

2.内存使用:即读写内存,就是使用变量和函数。

3.内存回收:使用完毕后,垃圾回收自动回收不再使用的内存。

注意:

① 全局变量一般不会回收(页面关闭再回收)② 局部变量不再使用才会被回收。

垃圾回收算法:

1.引用计数法:

① 跟踪每个值被引用的次数。

② 若被引用则值加一,多次引用会累加。

③ 减少一个引用就减一。

④ 如果引用次数为0则回收。

弊端:嵌套引用,如果两个对象互相引用,引用次数永远不会为0,尽管他们不再使用,垃圾回收器不会回收,造成内存泄漏。

function fn() {
            let o1 = {};
            let o2 = {};
            o1.a = o2;
            o2.a = o1;
            return '引用计数无法回收!';
        }
        fn();

 

2.标记清除法:引用计数法的改进,被大多数浏览器使用。

① 标记清除法将“不再使用的对象”定义为“无法达到的对象”。

② 就是从根部(在js中就是全局对象)出发定时扫描内存中的对象。凡是能从根部出发到达的对象,都是还需使用的。

③ 无法由根部出发触及到的对象被标记为不再使用,稍后就会被回收。

  嵌套引用标记清除无法找到,故直接清除。

 

变量提升:允许变量在声明之前即被访问。仅存在于var声明变量!

把var声明的变量提升到当前作用域的最前面,只提升声明,不提升赋值。

① 变量在var声明前被访问,变量值为undefined

② let/const的声明不存在变量提升

③ 变量提升出现在相同作用域中

 

函数提升:函数在声明前即可被调用

把所有函数声明提升到当前作用域的最前面,只提升声明,不提升调用。

fun();
var fun = function() {
      console.log(123);
}
// 报错 相当于只声明fun,由于只提升声明不提升赋值故fun此时不是函数

 

函数参数:

1.动态参数:arguments动态参数,只存在于函数中,是一个伪数组,用于动态获取传入的实参。

2.剩余参数:... 置于最末函数形参之前,用于获取多余实参。是真数组!

 

展开运算符:... 用于将一个数组进行展开

不会修改原数组

典型运用场景:

1.求数组最大值最小值:

Math.max(...arr);

之前使用apply的改变this指向:Math.max.apply(Array, arr);

2.合并数组:

const arr1 = [1,2,3,4];
const arr2 = [5,6,7,8];
const arr3 = [...arr1, ...arr2];

展开运算符和剩余参数的区别:① 展开运算符运用于数组,展开数组 ② 剩余参数在函数参数内使用,获取真数组

 

箭头函数(重要)

目的:引入箭头函数目的以更短的函数写法且不绑定this!语法更简洁

使用场景:适用于使用匿名函数的地方

① 基本形式:

const fn = () => {
            // 基本写法
  }
fn();

② 当只有一个形参的时候,括号可以省略:

const fun2 = x => {
            console.log(x);
        }
fun2(1);

③ 只有一行代码的时候,可以省略大括号:

const fun3 = x => console.log(x);
fun3(3);

④ 只有一行代码,可以省略return:

 const fun4 = x => x + x;
 fun4(3);

⑤ 可以直接返回一个对象:由于对象的大括号可能与函数的大括号冲突,故用小括号包裹对象

const fun5 = (uname) => ({ uname: uname })
fun5('lwh');

 

箭头函数的参数:箭头函数没有动态参数arguments   但是有剩余参数...

 

箭头函数的this:箭头函数不会创建自己的this,他只会从自己的作用域链的上一层沿用this!

const fn = () => {
      console.log(this);
  }
fn();

const obj = {
      say: () => console.log(this)
   }
obj.say();

 const obj2 = {
       say: function () {
                return () => console.log(this);
            }
        }
obj2.say()();    

函数fn结果为window:箭头函数本身没有this故向上查找到this指向对象window

函数obj.say结果也为window:由于obj的箭头函数没有this故无法指向obj本身,所以从obj上一层找到this指向window

函数obj2.say结果为obj2:由于say函数是匿名函数包裹箭头函数,箭头函数向上查询this,找到了匿名函数的this故指向的是obj2对象。

 

解构赋值:

数组解构:将数组的单元值快速批量赋值给一系列变量的语法。

语法:① 赋值运算符 = 左侧的 [ ] 用于批量声明变量。  ② 变量的顺序对应数组单元值的位置依次进行赋值操作。

eg:交换两个数的值:[a, b] = [b, a]

JS必须加分号情况:

① 立即执行函数前必须有:

(function t(){})();
(function n(){})()

② 数组前必须有:

let a = 1
let b = 2;
[a, b] = [b, a];

变量多 单元值少的情况:多余变量会被赋值为undefined(防止undefined传递要给变量赋初值)

 

 const [a, b, c = 0] = [1, 2];
 console.log(a);
 console.log(b);
 console.log(c);

 

变量少 单元值多的情况:按顺序赋值

剩余参数解决变量少单元值多的情况:以真数组形式存储剩余的值

 

多维数组解构:按照原有规则进行

const arr = [1, 2, [3, 4]]; 
const [one, two, [three, four]] = arr;
console.log(one);
console.log(two);
console.log(three);
console.log(four);

 

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

语法:① 赋值运算符 = 左侧的 { } 用于批量声明变量。  ② 变量名必须和对象属性名相对应。③ 对象中找不到与变量名相同会赋值为undefined!

对象解构需要变量和属性值名相同,但变量名可以修改!

语法:旧变量名:新变量名

const obj = {
            uname: 'lwh',
            say: function () {
                console.log(123);
            }
        }
const { uname: username, say: says } = obj;
console.log(username);
console.log(says);

数组对象的解构:

const arr = [{
            uname:'lwh'
        }]
const [{uname}] = arr;
console.log(uname);

多级对象解构:解构多级对象前要加对象名和冒号

const pigs = {
            names: 'abc',
            goods: {
                g1: 1,
                g2: 2,
                g3: 3
            },
            age: 6
        }
 const { names, goods: { g1, g2, g3 }, age } = pigs;

 

基本包装类型:JS底层会把简单数据类型包装为引用数据类型,所以字符串,数值等简单类型可以具有属性和方法。

内置构造函数:

引用类型:Object、Array、RegExp、Date等

包装类型:String、Number、Boolean等

1.Object:内置构造函数,用于创建普通对象

① Object.keys:用于获取对象中所有属性名(键)返回值为数组

② Object.values:用于获取对象中的所有属性值,返回值为数组。

③ Object.assign(浅拷贝):用于拷贝对象。参数为拷贝对象,原对象。

Object.assign经常用于给对象添加属性:

const o = {
            uname: 'lwh',
            age: 18
    };
Object.assign(o, {gender: 'man'});

2.Array: 内置构造函数,用于创建数组

① forEach:遍历数组,不返回值,不改变值,经常用于查找打印输出值。

② filter:过滤数组,筛选数组元素,生成新数组。

③ map:迭代数组,返回新数组,新数组元素是处理后的值,经常用于处理数据。

④ reduce:累计器,返回函数累计处理的结果,经常用于求和。

 

reduce函数的说明:

arr.reduce(fuction(累计值,当前元素[,索引号][,源数组]){},起始值)

① 如果有起始值,则以起始值为准开始累计,累计值=起始值。

② 如果没有起始值,则累计值以数组的第一个数组元素作为起始值开始累计。

③ 后面每次遍历就会用后面的数组元素,累计到累计值里面(类似求和sum)

 

find(callback,this对象):返回数组中满足提供测试函数的第一个元素的值,否则返回undefined。

find函数一般用于寻找出符合需求的JSON数据。

every函数与前期学过的some函数类似,都返回布尔值。但some是只要有一个符合就返回true,every则是需要所有元素都符合才返回true。

伪数组转化为真数组:Array.from(数组名) 伪数组没有push、pop等方法故转化。

 

3.String:内置构造函数,用于创建字符串。

① split(字符):用于将字符串以括号内的字符分割为数组。join是将数组组合为字符串。

② substring(indexStart [,indexEnd]):用于截取字符串。indexStart代表需要截取的第一个字符索引,indexEnd为结束索引号但不包含本身,若省略则默认截取至最后。

③ startsWith(子字符串 [,position]):检测是否以某字符为开头,返回值为布尔型。position可选,为开始查询位置。

④ includes(字符串 [,position]):判断一个字符串是否在另一个字符串中,返回布尔值,且区分大小写。(与Array中的some类似)

 

4.Number:内置构造函数,用于创建数值。

① toFixed(长度值):设置数字保留小数位的长度。若不填值则默认保留整数。(四舍五入)

posted @ 2022-09-11 09:06  HM-7  阅读(39)  评论(0)    收藏  举报