浅谈闭包

一、闭包

什么是闭包?

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

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

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

闭包的应用场景

  • 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.原型对象继承

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

转载于:https://www.cnblogs.com/wufenfen/p/11546649.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值