前端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(长度值):设置数字保留小数位的长度。若不填值则默认保留整数。(四舍五入)

浙公网安备 33010602011771号