Konzepte im Zusammenhang mit Abschlüssen: der Umfang von Variablen und die Lebensdauer von Variablen. Der folgende Artikel stellt Ihnen den Umfang und die Schließung von Variablen in JavaScript vor. Ich hoffe, dass er für alle hilfreich ist.
1 Der Geltungsbereich der Variable
1 Der gültige Bereich der Variablen hängt eng mit dem Ort der Variablendefinition zusammen. Der Bereich beschreibt Variablen aus räumlicher Sicht und kann auch als Sichtbarkeit von Variablen verstanden werden. Eine Variable ist innerhalb eines bestimmten Bereichs sichtbar, also verfügbar. [Verwandte Kursempfehlungen: JavaScript-Video-Tutorial]
2. Je nach Umfang können Variablen in globale Variablen und lokale Variablen unterteilt werden.
● Globale Variablen: in der globalen Umgebung deklarierte Variablen
● Lokale Variablen: in der Funktion deklarierte Variablen
● Wenn die Funktion ausgeführt wird, wird ein Abschluss erstellt. Die Ausführung Im Kontext der Funktion können die innerhalb der Funktion deklarierten Variablen nur innerhalb der Funktion verwendet werden und sind von außen nicht zugänglich, während globale Variablen überall verwendet werden können
3. Verwenden Sie das Schlüsselwort var in der Funktion, um anzuzeigen Deklarationsvariablen sind lokale Variablen; durch direkte Zuweisung deklarierte Variablen sind globale Variablen
var m=8; function f1(){ var a1=10; console.log(m); //8 } function f2(){ var a2=20; console.log(m); //8 } f1(); f2();
4 Verlassen Sie sich auf den Variablenbereich, um Kapselungsfunktionen zu implementieren
(1) Verwenden Sie ES6 vorausgesetzt let
(2) erstellt den Geltungsbereich durch Funktionen:
var myObject=(function(){ var _name="yian"; //私有变量 return { getName:function(){ //公有方法 return _name; } } })(); console.log(myObject._name); //undefined console.log(myObject.getName()); //yian
2. Lebenszyklus von Variablen
1 Variablen haben einen dauerhaften Lebenszyklus, es sei denn, die globale Variable wird aktiv zerstört.
2 Bei lokalen Variablen, die mit dem Schlüsselwort var innerhalb einer Funktion deklariert werden, verlieren diese lokalen Variablen ihren Wert und sie werden zerstört, wenn der Funktionsaufruf endet
3. Imitieren Sie den Bereich auf Blockebene
(1) Verwenden Sie anonyme Funktionen als Bereich auf Blockebene: Eine Funktionsdeklaration ist in ein Paar eingeschlossen Klammern, die darauf hinweisen, dass es sich tatsächlich um einen Funktionsausdruck handelt, und ein weiteres Klammerpaar, das darauf folgt, ruft die Funktion sofort auf.
(function(){ //这里是块级作用域 })();
Alle in der anonymen Funktion definierten Variablen werden am Ende der Ausführung zerstört
(2) Definieren Sie zuerst eine Funktion und rufen Sie sie dann auf. Die Möglichkeit, eine Funktion zu definieren, besteht darin, eine anonyme Funktion zu erstellen und die anonyme Funktion einer Variablen zuzuweisen. Um eine Funktion aufzurufen, müssen Sie nach dem Funktionsnamen ein Klammerpaar hinzufügen.
var someFunction=function(){ //这里是块级作用域 }; someFunction();
Klassisches Problem:
var nodes=document.getElementsByTagName("div"); for(var i= 0,len=nodes.length;i<len;i++){ nodes[i].onclick=function(){ console.log(i); //无论点击哪个div,最后弹出的结果都是5 } }
Erklärung: Das onclick-Ereignis des div-Knotens wird asynchron ausgelöst Schleife Es ist schon lange vorbei. Zu diesem Zeitpunkt bin ich bereits 5
Lösung:
Methode 1: Verwenden Sie let in ES6
Methode 2: Im Abschluss Mit Hilfe von 1) Eingekapselten Variablen: Abschlüsse können einige Variablen kapseln, die nicht global als „private Variablen“ verfügbar gemacht werden müssen. Zu den privaten Variablen gehören Funktionsparameter, lokale Variablen und andere innerhalb der Funktion definierte Funktionen.
Beispiel: Die Mult-Funktion empfängt Parameter vom Typ Nummer und gibt das Produkt dieser Parameter zurück,
Anfangscode:
var nodes=document.getElementsByTagName("div"); for(var i= 0,len=nodes.length;i<len;i++){ (function(x){ nodes[i].onclick=function(){ console.log(x); } })(i); }
Nach Verwendung des Abschlusses:
var cache={ }; var mult=function(){ var args=Array.prototype.join.call(arguments,","); if(cache[args]){ return cache[args]; } var a=1; for(var i=0,len=arguments.length;i<len;i++){ a=a*arguments[i]; } return cache[args]=a; }; console.log(mult(1,2,3)); //6 console.log(mult(3,4,5)); //60
Ergänzung: in bestimmt, dass das Attribut zum Objekt gehört
var mult=(function(){ var cache={ }; //加入缓存机制,避免相同参数的计算 var calculate=function(){ var a=1; for(var i= 0,len=arguments.length;i<len;i++){ a=a*arguments[i]; } return a; }; return function(){ var args=Array.prototype.join.call(arguments,","); if(args in cache){ return cache[args]; } return cache[args]=calculate.apply(null,arguments); } })();
(2) Verlängern Sie die Lebensdauer lokaler Variablen
Beispiel: Beim Melden von Daten mithilfe von Report werden etwa 30 % der Daten angezeigt Der Grund dafür ist, dass im Bericht, wenn die lokale Variable img endet, die lokale Variable img sofort zerstört wird img-Variable mit Abschluss):
var mycar = {make: "Honda", model: "Accord", year: 1998}; if ( "make" in mycar ){ //属性名必须是字符串形式,因为make不是一个变量 document.write('true'); // 显示true } else{ document.write('false'); }
5. Abschluss und objektorientiertes Design
Abschluss-Schreibmethode:
var report=function(src){ var image=new Image(); image.src=src; };
Objektorientierte Schreibmethode eins:
var report=(function(){ var imgs=[ ]; return function(){ var image=new Image(); imgs.push(image); image.src=src; } })();
Objektorientierte Schreibmethode zwei:
var extent=function(){ var value=0; return { call:function(){ value++; console.log(value); } } } var extent=extent(); extent.call(); //1 extent.call(); //2
6. Abschlüsse und Speicherverwaltung
● Lokale Variablen sollten beim Beenden der Funktion dereferenziert werden, wenn die lokalen Variablen jedoch in der gebildeten Umgebung eingeschlossen sind Durch den Abschluss bleiben die lokalen Variablen erhalten, das heißt, sie bleiben im Speicher.
● Bei der Verwendung von Abschlüssen ist es einfacher, einen Zirkelverweis zu bilden. Wenn einige DOM-Knoten in der Bereichskette des Abschlusses gespeichert sind, kann dies zu einem Speicherverlust führen.
● Lösen Sie das durch Zirkelverweise verursachte Speicherverlustproblem: Setzen Sie die Variablen in den Zirkelverweisen auf Null. (Wenn Sie eine Variable auf Null setzen, wird die Verbindung zwischen der Variablen und den Werten, auf die sie zuvor verwiesen hat, unterbrochen. Wenn der Garbage Collector das nächste Mal ausgeführt wird, werden diese Werte gelöscht und der von ihnen belegte Speicher wird zurückgefordert.)
7. Funktionen:
● Funktion verschachtelt;
● Externe Parameter und Variablen können innerhalb der Funktion referenziert werden.
● Parameter und Variablen werden von der Funktion nicht recycelt Garbage-Collection-Mechanismus.
8. Vorteile: Verschmutzung globaler Variablen vermeiden
9、缺点:会常驻内存,增加内存的使用量,使用不当会造成内存泄漏;闭包会携带包含它的函数的作用域,因此会比其他函数占用更多的内存
10、创建闭包
写法一:
function a() { var b=123; function c(){ console.log(b+=1); } return c; } var d=a(); d();
方式二:
function f1(){ var num=10; //函数执行完毕,变量仍然存在 var f2=function(){ num++; console.log(num); //11 }; return f2; } var res=f1(); res();
● 解释:执行f1()后,f1()闭包内部的变量会存在,而闭包内部函数的内部变量不会存在,使得JavaScript的垃圾回收机制不会收回f1()占用的资源,因为f1()中内部函数的执行需要依赖f1()中的变量。
方式三:
function foo(x) { var tmp = 3; return function f2(y) { alert(x + y + (++tmp)); //17 }; } var bar = foo(3); //bar现在是一个闭包 bar(10);
练习题:
function f1(){ var a=1; t=function(){ a++; } return function(){ console.log(a); } } var b=f1(); //返回值为一个匿名函数 b(); //1 t(); b(); //2
声明变量,若变量名称相同,就近原则:
var name="g"; function out(){ var name="loc"; function foo(){ console.log(name); } foo(); } out(); //name=loc
补充知识点:
1、JS中有哪些垃圾回收机制?
(1)引用计数:跟踪记录每个值被使用的次数。
● 当声明一个变量并将一个引用类型赋值给该变量时,该值的引用次数加1;
● 若该变量的值变为另一个,则该值引用次数减1;
● 若该值引用次数为0时,说明变量没有在使用,此值无法访问;
● 因此,可以将它占用的空间回收,垃圾回收机制会在运行时清理引用次数为0 的值所占用的空间。
● 在低版的IE中会发生内存泄漏,很多时候就是因为它采用引用计数得到方式进行垃圾回收(如果两个对象之间形成了循环引用,那么这两个对象都无法被回收)。
(2)标记清除:最常见的垃圾回收方式
● 当变量进入执行环境时,垃圾回收器将其标为“进入环境”,离开时标记为“离开环境”;
● 垃圾回收机制在运行时给存储在内存中的所有变量加上标记;
● 去掉环境中的变量及被环境中变量所引用的变量(闭包)的标记;
● 完成这些后仍存在的标记就是要删除的变量。
2、哪些操作会造成内存泄漏?
● 内存泄漏:指不再拥有或需要任何对象(数据)之后,它们仍然存在于内存中。
● 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为0(没有其他对象引用过该对象),或对该对象的唯一引用是循环的,那么该对象占用的内存立即被回收。
● 如果setTimeout的第一个参数使用字符串而非函数,会造成内存泄漏。
● 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)等会造成内存泄漏。
本文来自 js教程 栏目,欢迎学习!
Das obige ist der detaillierte Inhalt vonEine kurze Diskussion zum Umfang und Abschluss von JavaScript-Variablen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!