前端基础学习笔记 作用域 JS执行顺序 闭包

作用域

  • es5 作用域

作用域: 变量生效的限定环境

  1. 全局/顶层作用域 存在于script标签以及js文件

    全局作用域内声明的变量称之为全局变量,全局变量,可以在整个作用域内使用.

    所有的全局的环境都是互通的

  2. 函数作用域

    1.函数作用域内声明的变量,只能在当前函数作用域内使用,在别的作用域内访问不到.

    2.每个函数,都会生成一个独立的函数作用域

    3.函数作用域内的函数作用域,属于包含关系,不存在交集的函数作用域,则互不干扰

    4.函数使用全局变量,会改变全局变量的值

    ​ !!!作用域链 多个作用域相互嵌套

! 当我们处于某一个作用域里面使用变量时,先从自身作用域里面找该变量,如果找不到,就往父级作用域里面查找,直到script作用域,,还是没有就报错

! 当我们处于某一个作用域里面,修改某个变量的值时,先修改自己的,如果没有,就修改父级,直到script作用域都找不到,默认设置全局变量

! 无论什么环境下,没有声明就直接赋值的变量都会泄露成为window的属性,类似全局变量,window下面的属性 比全局还要高 var 和 function声明的全局变量,也会挂载到window的属性 let const不会

挂载上去的属性 可以delete删除 声明的全局变量不行

a = 1; delete a;
  • es6新增 块作用域

if for内的 var 声明 如果 if 在 全局作用域内 那么在if内用var 声明的变量则为全局变量.

 //认{}为域 
if(true){ var a = 1 let b = 2 } 
console.log(a)// 1
console.log(b)// not defined

for循环内let 声明的块作用域 let具备块作用域 因此for一共有10个块作用域,每个作用域内的i值不一样 每次触发使用的是 块作用域内存的 i 值

for(var i = 0 ; i < 10 ; i++){ 
    box[i].onclick = function (){ 
        console.log(i) //点击只输出 10 } 
    } 
for(let i = 0 ; i < 10 ; i++){ 
    box[i].onclick = function (){ 
        console.log(i) //输出当前点击的i值 } 
    }
  • 垃圾回收机制

JavaScript是具有自动垃圾收集机制的。通常情况下,程序在执行的过程中,会存储各种变量以及环境(作用域)。如果不对不需要的内容定时清理,就会使得页面的内存占用越来越多,使得浏览器越来越卡影响用户体验,所以,需要对不需要的变量或者没有使用的作用域进行定期清理。定时删除不需要无影响的内容。

​ 这种清理是自动的,无需手动管理,这是依赖优秀的垃圾回收机制。

​ 在我们全局里面的就是全局变量,浏览器关闭之后才会自动回收,当我们浏览器打开,会自动开辟一个空间来放它的值,所以我们要减少全局变量的使用.在局部里面声明的变量就是局部变量,局部变量里面的变量没有使用的时候,自动就会回收

var obj = document.getElementById("box"); 
obj.style.color = "blue"; 
obj = null;//清空指向

临时作用域 函数()形参内 在函数运行瞬间执行

案例 1

let x = 1 
function fn (y = x) { 
    let x = 2 
    console.log(y) } 
fn() //1 编译 x fn 执行fn() 瞬间 编译 :无 瞬间 执行:y = 1 内部编译 : x 执行 x = 2 con y => 1

案例二

let x = 1 
function fn(x = 2,y = function(){x = 2}){ console.log(x) x = 3 y() console.log(x) } 
fn() /* 编译阶段 x fn 执行 fn() => 瞬间 编译 y x = 2 y = fun 函数内部编译:无 内部执行: con x => 2 x = 3 y() x = 2 重新赋值 con x =>2 */

js执行

1.浏览器中配备 js解释器,用于执行js代码

2.js是解释性语言,js需要工具翻译成对应的机器底层码,可以被识别

3.js解释器并没有一个统一的规范 (造成存在的兼容的问题)

4.v8引擎放到服务器,js就可以在服务器环境执行

var function 声明存在提升的问题,因此 es5 js的执行有两个阶段 一个是编译 一个是执行

js执行流程: 面试常客

​ 编译:找变量 找函数 对代码进行静态分析 检查语法是否符合规范 无关启动函数与否 (编译阶段发现语法错误,直接报错不执行)

​ 执行:运行js代码 赋值等操作

//编译时期 抛出错误 演示 无关执行与否 在编译期就直接终止 
function fn(){ var a + b = 2 }

alert(a) 
var a = 1 
function a(){
    console.log(a)
} 
alert(a) 
//编译阶段 : 找声明 var a function a(){} 由于function权重大 所以 可以覆盖var a 
//执行阶段: alert(a) => function a a = 1 alert(a) => 1
//练习1 
function f(){ var g = 1; alert(g) }

function f() { var g = 2 alert(g) } 
alert(f) 
f() 
var f = 5 
f()

编译阶段: function f 第一个 =>pass function f 第二个 =>ok var f =>pass 执行阶段: alert(f) =>function f 2 f() => funtion 第二个 => 编译 :var g 执行 :g = 2 alert(g) => 2 f = 5 f() => 报错 5 不是函数 ```
//练习2 
fn() 
alert(s) 
var s = 0; 
alert(s) 
function fn() { var a = 1 }

编译阶段: var s fn function 执行阶段 : fn() => 编译:var a 执行 a = 1 alert(s) =>undefined s = 0 alert(s) => 0 ```

闭包

由于垃圾回收机制的存在,所以一个作用域内声明的变量是不被存储的,因此不能再前一次的基础上使用.只能重头再来,

function fn(){ let a = 2; a++ console.log(a) } 
fn() // 3 
fn() // 3 
//不能在前一次的基础上,进行运算,因为函数执行完毕,变量没有用处之后,会被回收

//函数可以保留自己的作用域并可以访问它的作用域就产生了闭包

// 闭包的条件 : 一个函数里面嵌套一个函数 ,内部函数引用外部函数的变量或者参数 ​ // 闭包的作用 : 使局部变量不会被销毁,得以存储

function fn(){ 
    var a = 1 
    return function fn1(){ 
        a++ return a 
        } 
    }
let b = fn() 
//保留了函数fn1 函数fn1可以访问fn的作用域里面的a 并且对它进行改变,这意味着 a的作用域在fn执行完成之后保留了下来,保留在函数fn1中 
b()//2 
b()//3

作用 小案例

// 1 
function money(){ 
    var ATM = { "money": 100 } 
    console.log("你的钱是:"+ ATM.money) 
    return { 
        "add":function(){
            //存钱 
            ATM.money += 10;
            //每次存十元 
            console.log("你的钱是:"+ ATM.money); },
         "lost":function()
            {
            //消费 
            ATM.money-=5;
            //每次消费5元 
            console.log("你的钱是:"+ ATM.money); }, 
         "get":function(){ 
            return ATM.money; } } } 
            var xx = money();
            //"你的钱是:100" 初始钱 
            xx.add();//"你的钱是:110" 
            xx.lost();//"你的钱是:105"
//2 
function fn(){ 
    var ss = 123 
    function A(){ console.log(ss) } 
    window.$ = A;
    //将foo作用域里面的A存储到全局window下的$中也是形成闭包。 
} 
fn(); 
window.$()

闭包坏处:: ​ 闭包使用的父级函数的变量或者参数,会被永久保存,直到窗口关闭,使用过多会导致ie内存泄漏(可分配的内存的资源减少) ​ 占内存 非常杂乱 找东西慢 效率低 生命周期和全局变量一样

你可能感兴趣的:(前端基础学习笔记-JS)