浅谈闭包

一、闭包

什么是闭包?

闭包:"利用作用域的嵌套,将原本的局部变量,进化成自由(私有)变量的环境"

闭包的原理:
    局部作用域,局部变量的生命周期,朝生暮死
    利用作用域的嵌套,触发计算机的垃圾回收机制,将原本要删除的变量,暂时保存起来,可以继续使用

垃圾回收机制:将要删除的数据,先暂时存放在一个临时空间内,不立即删除,如果需要再次使用,可以直接找到该数据,继续使用,直到真正不用了,再被删除

闭包的应用场景

  • 1、(for)循环中的异步
    for循环之中的i变量会因为for的循环次数被覆盖,所以在for循环内部存在函数时,而且这个函数内会调用i变量,这种情况下就需要用到闭包。
    for(var i=0;i<10;i++){
        console.log(i);        //可以访问到每次的i
    }

   " 必须满足两个条件:
        1.在for循环内存在函数
        2.函数内会调用这个变量"
        
    var ali = document.getElementsByTagName("li");
    for(var i=0;i<10;i++){
        ali[i].onclick = function(){
            console.log(i);        //在函数内部就无法访问到外部变量
        }
    }
    如何形成闭包
    var ali = document.querySelectorAll("li");
// 用法一: 用法一和用法二都是通过匿名函数形成作用域
    for(var i=0;i<ali.length;i++){
        (function(index){
            ali[index].onclick = function(){
                console.log(index);
            }
        })(i)
    }
// 用法二:
    for(var i=0;i<ali.length;i++){
        ali[i].onclick = (function(index){
            return function(){
                console.log(index);
            }
        })(i);
    }
// 用法三:借助 let/cont 触发之后形成块级作用域,形成闭包,把i的值传到内部的作用域中
    for(let i=0;i<ali.length;i++){
        ali[i].onclick = function(){
            console.log(i);
        }
    }
    
    利用匿名函数将i保存起来了
    "一旦内部函数调用外部函数的局部变量,那么这个时候,这个局部变量就会变成内部函数的私有变量"
  • 2、计时器(setTimeout)的回调函数的传参时(还有事件委托的封装也是闭包--day14):
    setTimeout(function (a){
        console.log(a);     //两秒后,undefined       函数被放到setTimeout内部里,内部只有执行,没有传参进去
    }, 2000);
    或
    setTimeout(fn("hello"), 5000);
    function fn(str{
        console.log(str);     //没有延迟,立即打印hello      任何情况下函数名+()都是立即执行
    }
    
    使用闭包: 
    function fn(a){
        return function(){
            console.log(a);     // 三秒后,打印10
        }
    } 
    // function(){console.log(a);}     //  作为fn内部的一个小函数,是一个独立的作用域,可以拿到外面的fn(str)的参数str,将其临时保存起来,等setTimeout到时间了就执行这个小函数
    var f = fn(10);  // fn做参数,把10传入a中
    setTimeout(f, 3000);

闭包的特点

优点:可以将要删除的数据,保存起来,继续使用,方便 
可以在函数外部操作内部的数据

缺点:因为要删除的数据,没有被删除,继续存起来,那么占内存,耗性能
     在外部有可能改变内部的数据

"闭包就是将作用域内部和外部连接起来的桥梁"

闭包番外篇--作用域

闭包
    var a = 10;
    function fn(){
        var a = 20;
        return function(){
            console.log(a++);
        }
    }
    var f = fn();
    f();

"函数:定义上下文,执行上下文(this)"
"函数执行时,在函数的内部可以拿到自身的定义作用域中的变量"

作用域链----查资料,理解写法原理

代码是在运行状态下被执行的,运行在内存中(内存:运行结束后立即删除,硬盘里的东西不会删)


二、趣味性方法:eval

eval();
参数:(只能是)字符
功能:将字符解析成js代码

var str = "1+1";
    console.log(str);  // 1+1
    console.log(eval(str));  // 2
var str = "hello";
    console.log(eval(str));  // 报错,把str解析成js代码就报错
var str = "console.log(123)";
var str = '[{"name":"admin"},]';
var str = '[{name:"admin"}]';
var str = '{"name":"admin"}';

console.log(str);

console.log(eval(str));

console.log(JSON.parse(str));

三、继承

1.继承的介绍

继承:子承父业;一个原本没有某些方法或属性的对象,统一写方法,拿到了另外一个对象的属性和方法
改变this指向继承(构造函数继承):继承构造函数中的属性和方法
优点:简单方便易操作,可以多继承
缺点:只能继承构造函数,不能继承原型

构造函数创建对象

function Fn(){
    this.name = "admin";
}
Fn.prototype.init = function(){
    console.log(this.name)
}

var f1 = new Fn();
var f2 = new Fn();

console.log(f1);
console.log(f2);
console.log(f1 == f2);  // false;

bind()
call()
apply()

var obj = {
    name:"admin",
    show:function(){
        console.log(this.name)
    }
}

var obj2 = {
    name:"root"
}

obj.show();  // admin
// obj2.show();
obj.show.bind(obj2)();  // root
obj.show.call(obj2);    // root
obj.show.apply(obj2);   // root

2.改变this指向继承/构造函数继承

原型对象继承:继承原型
优点:简单,方便,可以继承原型身上的方式和属性
缺单:只能继承原型,不方便传参

3.原型对象继承

原型对象继承:继承原型
优点:简单,方便,可以继承原型身上的方式和属性
缺单:只能继承原型,不方便传参
posted on 2019-09-19 08:01  取个名字真wff  阅读(182)  评论(0编辑  收藏  举报