文章目录
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++一次生成一个栈内存,不利于运行,了解即可