JS基础学习(5)

111 阅读3分钟

作用域、闭包基础

  • [[scope]] --隐式属性域

  • 函数创建时生成的一个JS内部的隐式属性。

  • 函数存储作用域链的容器,作用域里面的存储的是 AO,GO,

    • AO ,函数执行期上下文
    • GO,全局的执行期上下文
  • 当函数执行完成以后,AO是要销毁的,再次执行这个函数时候AO重新生成一个新的AO,AO是一个即使的存储容器。

  • 作用域链就是把,AO,GO形成链式关系从上到下排列起来。

  • 每一个函数在被定义的时候就已经包含了GO。

ddd1.png

  • 生成自己AO一定是排列在作用链最顶端的,把GO挤到下面去。

2.png

  • a函数执行的时候b函数被定义
  • 再被定义的时候我在上级环境之中,所以和a函数执行的时候一样。
  • GO只有一个,拿的都是堆函数的地址,指向同一个东西

3.png

4.png

  • 这个时候,b函数被销毁的只是自身的AO作用域现在还在。

5.png

6.png

  • a函数执行完毕后,这个时候b函数整个作用域被销毁,整个函数就不存在了

7.png

  • 只要函数定义就生成相应的作用域,作用域链,然后GO放进去,被执行前一刻生成自己的AO。

  • 结束

8.png

闭包

9.png

10.png

  • 这里的test3存的就是test2的引用 11.png

  • 结束后会销毁自己的AO,test2的AO还有 12.png

  • 当内部函数被返回到外部并保存,一定会产生闭包,闭包会产生原来的作用域链不释放。

  • 闭包其实就是一种现象。

立即执行函数 IIFE - immediately-invoked function expression

  • GO的函数不会释放,手动执行函数
  • 要满足自动执行,执行完成后立即释放
  • 立即执行函数 - 初始化函数
  • 执行完毕之后就销毁了
  • 立即执行函数是支持返回值,需要一个变量来接收保存。
  • 括号里面写函数声明 -- 也变成表达式了
  • ()括号包裹起来的,数字,变量,函数都会变成表达式。

(function(){})();

(function(){}());// w3c 建议

(function (a,b){
    console.log(a+b);
})(1,3);

// 拿到这个值
var num = (function(a,b){
    return a + b;
})(1,2);

// 一定是表达式才能被执行符号执行。
var test2 = function (){
    console.log(2);// 可以执行
}();

(function(a,b){
    return a + b;
})(1,2);


function test() {
        var arr = [];
        for (var i = 0; i < 10; i++) {
            (function (j) {
                arr[i] = function () {
                    console.log(j);
                };
            })(i);
        }
        return arr;
    }

    var test1 = test();

    for (var j = 0; j < 10; j++) {
        test1[j]();
    }
    
<body>

    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
    </ul>

</body>

</html>
<script>
    var op = document.querySelectorAll("li")

    for (var i = 0; i < op.length; i++) {
        (function (j) {
            op[j].onclick = function () {
                console.log(j);
            }
        })(i);
    }
</script>
var fn = (
        function test(){
            return 1;
        },
        function test2(){
            return "2";
        }
    )();
    // 逗号是运算符,只返回最后一个
    console.log(typeof(fn));// string
    // 立即执行函数,执行test2函数 ,typeof 返回string
    
    
    
     var a = 10;
    if(function b(){}){
        a += typeof(b);
    }
    // (function b(){}) 是表达式,忽略b的声明
    // 所以只有把一个不存在的值放进typeof(b)的时候才会返回undefined
    // 如果直接是 a += b;会报错
    console.log(a);// 10undefind
// 累加
function once(){
        var num = 0;
        return function() {
            num = num +1;
            console.log(num);
        }
    }

    var test = once();

    test();
    test();
    test();
    test();
    
    

对象

  • 键值对方式书写,逗号隔开 -- 对象字面量
  • 使用对象. 属性的方法访问,查找属性方法
  • 增加属性方法,对象名.xxx
  • 如果改的话直接赋值就行了,方法也可以赋值更改
  • 删除使用delete -- delete teacher.name

    var teacher = {
        name :"张三"age:32,
        sex:"male",
        height:176,
        weight:130,
        teach:function(){
            console.log("I am teaching");
        },
        smoke:function(){
            console.log("I am smoke");
        }
    }
    // 查找
    console.log(reacher.name);// 张三
    teacher.teach();
    // 增加
    teacher.address = "beijing";
    teacher.drink = function (){
        console.log("I am drinking beer");
    }
    
    // 改
    teacher.name = "李四";
    teacher.teach = function (){
        console.log("I am lisi");
    }
    // 删除
    delete teacher.name;
    delete teacher.drink;
    
    

var attend = {
        student:[],
        total:6,
        join:function(name){
            this.student.push(name);
            if(this.total === this.student.length){
                console.log(name + "到课,学生已到齐");
            }else{
                console.log(name + "学生未到齐");
            }
        },
        leave:function(name){
            var idx = this.student.indexOf(name);
            if(idx !== -1){
                this.student.splice(idx, 1);
            }
            console.log(name + "早退");
            console.log(this.student);
        }, 
        classover:function(){
            this.student = [];
            this.student.length = 0;
            console.log("已下课");
        }
    }

    attend.join("李四");
    attend.join("王五");
    attend.join("张1");
    attend.join("张2");
    attend.join("张3");
    attend.join("张7");
    attend.leave("李四")
    attend.classover();