js进阶--let,上级作用域,闭包03

es6中的let

  • es6没有变量提升,但是在代码执行之前会有一个词法检测,来看你的代码是不是会有语法错误,如果有直接报错
//直接打印报错,不执行console  
//Identifier 'a' has already been declared
console.log(1);
let a=1;
var a=2;
  • 阻断了window的关系
let a=1;
"a" in window;//false
  • 不能重复声明
//直接打印报错,不执行console  
//Identifier 'a' has already been declared
console.log(1);
let a=1;
var a=2;
  • 暂时性死区:在声明变量之前的那个区域是不允许访问变量的,一旦访问就报错
console.log(a);//a is not defined
let a=2;
小练习
let a=10;
let b=10;
let fn=function(){
    console.log(a);//报错Cannot access 'a' before initialization
    //let a是私有变量,所以会在自身作用域查找,但是在let前面使用,所以报错
    let a=b=20;
    console.log(a,b);
}
fn();
console.log(a,b);
var a=12,b=13,c=14;
function(a){
console.log(a,b,c);//12,undefined,14
var b=a=c=20;
console.log(a,b,c);//20,20,20
}
fn(a);
console.log(a,b,c);//12,13,20
var ary=[12,13];
function fn(ary){
   console.log(ary);//[12,13]
   ary[0]=100;
   ary=[100];
   ary[0]=0;
   console.log(ary);//[0]
}
fn(ary);
console.log(ary);//[100,13] 
上级作用域

上级作用域是谁,跟在哪执行没有关系,跟这个函数在哪定义有关系

function A() {
    function B() {
        function C() {

        }
    }
}
//C的上级作用域是B,B的上级作用域是A,A的上级作用域是window
小练习
var a=3;
function fn(){
console.log(n);
}
function sum(){
var a=6;
fn();
}
fn();//3
sum();//3
var n=10;
function fn(){
    var n=20;
    function f(){
        n++;
        console.log(n);
    }
    f();
    return f;
}
var x=fn();//21    赋值 x=f(){n++;console.log(n)}的空间地址
x();//22 
x();//23
console.log(n);//10

图解
在这里插入图片描述

堆栈内存的释放问题

我们每次给变量存储值或者执行函数的时候都会占用内存空间,如果一直这样下去,电脑会装不下,所以内存是需要释放的

堆内存的释放

让所有引用这个堆内存的变量赋值为null,堆内存地址不被占用,浏览器在空闲时就会把堆内存释放 ,例如

var obj=[1,2,3];
var obj2=obj;
obj=null;
obj2=null;
常见的浏览器释放主要有两种:
  • 谷歌浏览器是标记方式,每隔一段时间就会检测以下当前作用域中的内存,是否被占用,如果没有被占用,就会释放掉。
  • ie和火狐等浏览器采用的是计数方式,当前作用域中如果一个空间地址被占用一次,就会累加一次,如果减少一次占用会减1,直到0的时候,说明已经没有被占用了,就释放了
栈内存的释放
  • 1、 全局栈内存,当页面关闭才会销毁
  • 2、函数执行的栈内存,当函数执行完毕一般情况下会销毁
  • 3、函数执行的栈内存还有一种情况不会被销毁,函数内的引用数据类型的值被外面的变量占用了,所以就不销毁,例如:
//不销毁,return的函数被外面的f占用
var function fn(){
    var num=2;
    return function(){
       console.log(num);
    };
};
var f=fn();

//不销毁,因为函数内的ary地址被外面的占用
var ary=[];
function fn(){
ary=[1,2,3];
}
fn();
  • 4、不立即销毁,等待内部全部执行完毕销毁
//等待return的函数执行完销毁
function fn(){
	return function(){
		console.log(1);
	}
}
fn()();
function fn(i) {
    return function (n) {
        console.log(n + (++i));
    }
}
var f = fn(2);//f= function(n){console.log(n+(++i))}的地址  
f(3);//6
fn(5)(6);//12
fn(7)(8);//16
f(4)//8

闭包

  • 当一个函数执行,形成了一个私有作用域,保护里面的私有变量不受外界的干扰,这种机制就叫做闭包;
  • 在市场上大部分人口中的闭包:当一个函数执行的时候,里面有一个引用数据类型被外界占用了,形成了不销毁的作用域,例如:
function fn(){
	return function(){};
}
var res=fn();
闭包的作用
  • 保护:保护私有作用域中的变量不被外界的干扰
  • 保存:因为形成了不销毁的作用域,可以保存里面的私有变量
引伸–工作中闭包的应用(不用记)
  • 两个人开发一个项目,到合并代码时防止变量冲突,可以用闭包
  • JQuery
(function(){
    function jquery(){
    }
    //把jquer 这个方法通过window添加属性暴露到全局
    window.jquery=window.$=jquery;
})()
//在使用的时候: jquery() 或者$()
  • 把一些东西暴露在外面
var utils = (function () {
    var num = 0;
    function fn1() {
        console.log(1)
    }
    return {
        fn1: fn1
    }
}
)()
utils.fn1();//调用utils里面的fn1函数
练习,闭包实现选项卡

html,css部分

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        ul,
        ol {
            list-style: none;
            font-size: 0;
        }

        #main {
            width: 500px;
            margin: 0 auto;
        }

        li {
            width: 100px;
            height: 50px;
            line-height: 50px;
            font-size: 16px;
            display: inline-block;
            margin-left: 20px;
            border: 1px solid red;
            position: relative;
            text-align: center;
            top: 1px;
        }

        li:nth-child(1) {
            margin-left: 0;
        }

        #main div {
            height: 200px;
            text-align: center;
            line-height: 200px;
            border: 1px solid red;
            display: none;
        }

        #main li.appear {
            background: red;
            border-bottom-color: transparent;
        }

        #main div.appear {
            display: block;
            background: red;
        }
    </style>
</head>

<body>
    <div id="main">
        <ul>
            <li class="appear">1</li>
            <li>2</li>
            <li>3</li>
        </ul>
        <div class="appear">1</div>
        <div>2</div>
        <div>3</div>
    </div>
</body>

闭包实现选项卡方法1

    var main = document.querySelector('#main');
    var lis = main.querySelectorAll("li");
    var divs = main.querySelectorAll("div");
    for (var i = 0; i < lis.length; i++) {
    (function(i){
        lis[i].onclick=function(){
        for(var j=0;j<lis.length;j++){
            console.log(j);
            divs[j].className="";
            lis[j].className="";
        }
        lis[i].className="appear";
        divs[i].className="appear";
    }
    })(i)}

第二种

    var main = document.querySelector('#main');
    var lis = main.querySelectorAll("li");
    var divs = main.querySelectorAll("div");
      for (var i = 0; i < lis.length; i++) {
        lis[i].onclick = (function (i) {
            return function () {
                lis[i].onclick = function () {
                    for (var j = 0; j < lis.length; j++) {
                        console.log(j);
                        divs[j].className = "";
                        lis[j].className = "";
                    }
                    lis[i].className = "appear";
                    divs[i].className = "appear";
                }
            }
        })(i)
    }

在这里插入图片描述

第三种

for (let i = 0; i < lis.length; i++) {
        lis[i].onclick = function () {
            for (var j = 0; j < lis.length; j++) {
                divs[j].className = "";
                lis[j].className = "";
            }
            lis[i].className = "appear";
            divs[i].className = "appear";
        }
    }

方法总结,都是让他每i++一次生成一个栈内存,不利于运行,了解即可

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值