{"action":"opened","issue":{"url":"https://api.github.com/repos/Fits-Liam/Bug/issues/2","repository_url":"https://api.github.com/repos/Fits-Liam/Bug","labels_url":"https://api.github.com/repos/Fits-Liam/Bug/issues/2/labels{/name}","comments_url":"https://api.github.com/repos/Fits-Liam/Bug/issues/2/comments","events_url":"https://api.github.com/repos/Fits-Liam/Bug/issues/2/events","html_url":"https://github.com/Fits-Liam/Bug/issues/2","id":308879785,"number":2,"title":"closure 闭包","user":{"login":"Fits-Liam","id":33616428,"avatar_url":"https://avatars3.githubusercontent.com/u/33616428?v=4","gravatar_id":"","url":"https://api.github.com/users/Fits-Liam","html_url":"https://github.com/Fits-Liam","followers_url":"https://api.github.com/users/Fits-Liam/followers","following_url":"https://api.github.com/users/Fits-Liam/following{/other_user}","gists_url":"https://api.github.com/users/Fits-Liam/gists{/gist_id}","starred_url":"https://api.github.com/users/Fits-Liam/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Fits-Liam/subscriptions","organizations_url":"https://api.github.com/users/Fits-Liam/orgs","repos_url":"https://api.github.com/users/Fits-Liam/repos","events_url":"https://api.github.com/users/Fits-Liam/events{/privacy}","received_events_url":"https://api.github.com/users/Fits-Liam/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2018-03-27T08:58:44Z","updated_at":"2018-03-27T08:58:44Z","closed_at":null,"author_association":"OWNER","body":"### JavaScript-闭包\r\n\r\n定义:\r\n闭包，官方对闭包的解释是：一个拥有许多变量和绑定了这些变量的环境的表达式（通常是一个函数），因而这些变量也是该表达式的一部分。\r\n简单来说，闭包就是能够读取其他函数内部变量的函数。在Javascript中，只有函数内部的子函数才能读取函数的局部变量，所以，可以把闭包理解成：定义在一个函数内部的函数，也就是函数嵌套函数，给函数内部和函数外部搭建起一座桥梁。\r\n\r\n闭包的特点:\r\n1. 定义在一个函数内部的函数。\r\n2. 函数内部可以引用函数外部的参数和变量。\r\n3. 作为一个函数变量的一个引用，当函数返回时，其处于激活状态。\r\n4. 当一个函数返回时，一个闭包就是一个没有释放资源的栈区。函数的参数和变量不会被垃圾回收机制回收。\r\n\r\n闭包的形成:\r\nJavascript允许使用内部函数，可以将函数定义和函数表达式放在另一个函数的函数体内。而且，内部函数可以访问它所在的外部函数声明的局部变量、参数以及声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时，就会形成闭包。\r\n```\r\nfunction a() {  \r\n    var i = 0;  \r\n    function b() { \r\n        console.log(i++); \r\n    }  \r\n    return b; \r\n}\r\nvar c = a(); \r\nc();\r\n```\r\n\r\n闭包的缺点\r\n1.由于闭包会使得函数中的变量都被保存在内存中，内存消耗很大。所以在闭包不用之后，将不使用的局部变量删除，使其被回收。在IE中可能导致内存泄露，即无法回收驻留在内存中的元素，这时候需要手动释放。\r\n```\r\nfunction a() {  \r\n    var i = 1;  \r\n    function b() { \r\n        console.log(i++); \r\n    }  \r\n    return b; \r\n}\r\nvar c = a(); \r\nc(); //1\r\nc(); //2\r\nc(); //3   i不被回收\r\nc = null;  //i被回收\r\n```\r\n\r\n2.闭包会在父函数外部，改变父函数内部变量的值。如果你把父函数当作对象使用，把闭包当作它的公用方法，把内部变量当作它的私有属性，要小心，不要随便改变父函数内部变量的值。\r\n\r\n```\r\nvar Xzavier = { \r\n    ten:10,  \r\n    addTen: function(num) {  \r\n       return this.ten + num;   //给一个数加10 \r\n   }    \r\n}\r\n \r\nconsole.log(Xzavier.addTen(15));  //25\r\nXzavier.ten = 20; \r\nconsole.log(Xzavier.addTen(15));  //35\r\n```\r\n\r\n内存泄露\r\n内存泄漏指一块被分配的内存既不能使用，又不能回收，直到浏览器进程结束。\r\n\r\n出现原因：\r\n1. 循环引用：含有DOM对象的循环引用将导致大部分当前主流浏览器内存泄露。循环 引用，简单来说假如a引用了b,b又引用了a,a和b就构成了循环引用。\r\n2. JS闭包：闭包，函数返回了内部函数还可以继续访问外部方法中定义的私有变量。\r\n3. Dom泄露，当原有的DOM被移除时，子结点引用没有被移除则无法回收。\r\n\r\nJavaScript垃圾回收机制\r\nJavascript中，如果一个对象不再被引用，那么这个对象就会被GC(garbage collection)回收。如果两个对象互相引用，而不再被第3者所引用，那么这两个互相引用的对象也会被回收。垃圾回收不是时时的，因为其开销比较大，所以垃圾回收器会按照固定的时间间隔周期性的执行。\r\n函数a被b引用，b又被a外的c引用，这就是为什么函数a执行后不会被回收的原因。\r\n\r\n垃圾回收的两个方法：\r\n\r\n标记清除法：\r\n1. 垃圾回收机制给存储在内存中的所有变量加上标记，然后去掉环境中的变量以及被环境中变量所引用的变量（闭包）。\r\n2. 操作1之后内存中仍存在标记的变量就是要删除的变量，垃圾回收机制将这些带有标记的变量回收。\r\n\r\n引用计数法：\r\n1.垃圾回收机制给一个变量一个引用次数，当声明了一个变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1。\r\n2.当该变量的值变成了另外一个值，则这个值得引用次数减1。\r\n3.当这个值的引用次数变为0的时候，说明没有变量在使用，垃圾回收机制会在运行的时候清理掉引用次数为0的值占用的空间。\r\n\r\n"}}
{"actor":{"display_login":"Fits-Liam"}}