Heim > Web-Frontend > js-Tutorial > Eine kurze Diskussion über JS-Funktionen und -Abschlüsse

Eine kurze Diskussion über JS-Funktionen und -Abschlüsse

青灯夜游
Freigeben: 2019-11-30 16:59:03
nach vorne
2178 Leute haben es durchsucht

Jedes Mal, wenn eine Funktion deklariert wird, wird ein Bereich erstellt. Der äußere Bereich kann nicht auf den inneren Bereich zugreifen (die Variablen und Funktionen in ausblenden), aber der innere Bereich kann auf den äußeren Bereich zugreifen. Eine sehr nützliche Technik zum Ausblenden von Variablen und Funktionen.

Eine kurze Diskussion über JS-Funktionen und -Abschlüsse

Die Methode, die auf dem Ausblenden des Bereichs basiert, wird

Minimum Authorization oder Minimum Exposure Principle genannt.

Dieses Prinzip bedeutet, dass beim Software-Design notwendige Inhalte auf ein Minimum beschränkt und ihre Inhalte ausgeblendet werden sollten, wie zum Beispiel das API-Design eines bestimmten Moduls oder Objekts.

Versteckte Variablen und Funktionen können Konflikte zwischen Bezeichnern mit demselben Namen lösen, was zum versehentlichen Überschreiben von Variablen führen kann.

Zum Beispiel:

var a = 2;
function foo(){
  var a = 3;
  console.log(a);
}
foo();
console.log(a);
Nach dem Login kopieren
Obwohl diese Technik einige Probleme lösen kann, ist sie nicht ideal und wird einige zusätzliche Probleme verursachen. Zuerst muss eine benannte Funktion foo() deklariert werden, was foo bedeutet Der Name selbst „verschmutzt“ den Gültigkeitsbereich, und zweitens muss diese Funktion explizit über den Funktionsnamen foo() aufgerufen werden, um den darin enthaltenen Code auszuführen.


Idealer wäre es, wenn die Funktion keinen Funktionsnamen benötigt und automatisch ausgeführt werden kann. Glücklicherweise bietet js gleichzeitig eine Lösung für diese beiden Probleme – (IIFE) Sofort aufgerufener Funktionsausdruck –

Führen Sie die Funktion sofort aus

var a = 2;
(function foo(){
    var a = 3;
    console.log(a);
})()
console.log(a);
Nach dem Login kopieren
Zuallererst wird die

sofort ausgeführte Funktion nicht als Funktionsdeklaration, sondern als als Funktionsausdruck behandelt.

Funktionsdeklaration oder Funktionsausdruck unterscheiden: Überprüfen Sie, ob die Funktion das erste Wort in der Deklaration ist. Wenn es das erste Wort ist, handelt es sich um eine Funktionsdeklaration, andernfalls um eine Funktionsausdruck. Die Funktion „ (Funktion“ wird sofort ausgeführt, nicht „Funktion“, es handelt sich also um einen Funktionsausdruck.

Zwischen Funktionsdeklaration und FunktionsausdruckDer wichtigste Unterschied besteht darin, wo ihre Namensbezeichner gebunden werden

Der von der Funktion deklarierte Funktionsname wird im aktuellen Bereich gebunden, wenn Sie erstellen Bei einer Funktionsdeklaration im globalen Bereich können Sie auf den Funktionsnamen zugreifen und ihn im globalen Bereich ausführen. Der Funktionsname des Funktionsausdrucks wird an die Funktion selbst gebunden, nicht an den aktuellen Bereich. Sie erstellen einen Funktionsausdruck global. Wenn Sie den Funktionsnamen des von Ihnen erstellten Funktionsausdrucks direkt ausführen, wird ein Fehler gemeldet, da im aktuellen Bereich kein solcher Bezeichner vorhanden ist und Sie im Bereich innerhalb des Funktionsausdrucks auf diese Funktion zugreifen. Der Name gibt einen Verweis auf zurück Diese Funktion

Scope-Verschluss, nun, die beiden Wörter Verschluss sind etwas schwer zu verstehen (Sie können sich vorstellen, dass ein Paket geschlossen ist. Darin sind einige mysteriöse Dinge versteckt.) Die Definition von Verschluss sagt dies : Wenn sich eine Funktion an den Bereich erinnern kann, in dem sie sich befindet, wird ein Abschluss generiert, auch wenn die Funktion beispielsweise außerhalb des aktuellen Bereichs ausgeführt wird (auf Englisch, haha).
function foo() {
    var a = 2;
    function bar() {
        console.log(a);
    }
    bar();
}
foo();
Nach dem Login kopieren

Der obige Code bar() kann gemäß der obigen Definition auf Variablen zugreifen. Vielleicht ist es das, aber wir verstehen, dass, wenn der Bereich nach Variablen im aktuellen Bereich sucht, Es wird weiter nach oben gesucht, und wenn es gefunden wird, wird es weiter gesucht, bis es im globalen Bereich gefunden wird – und dies sind die Abschlüsse. Die Funktion bar() hat einen Abschluss, der den Bereich von foo( abdeckt. ). Der obige Code zeigt den Abschluss der Funktion

außerhalb des Gültigkeitsbereichs (wird zu diesem Zeitpunkt im globalen Bereich ausgeführt) und wird normalerweise erwartet dass der gesamte interne Bereich von foo() zerstört wird, da wir wissen, dass die Engine über einen

Garbage Collector

verfügt, der verwendet wird, um ungenutzten Speicherplatz freizugeben. Da foo() ausgeführt wurde, scheint es, dass der Inhalt zerstört wird nicht mehr verwendet werden, daher ist es selbstverständlich, die Ausrichtung für die Wiederverwertung in Betracht zu ziehen. Nach der Ausführung von foo() enthält die Variable baz einen Verweis auf die Funktion bar Ich verstehe die Schließungen möglicherweise nicht. Ist der Umfang der

-Funktion noch vorhanden?

当foo()执行后,bar函数被返回全局作用域下,但是bar函数还保留着当时的词法作用域(当时写代码是的顺序就已经定义了作用域,这个作用域叫词法作用域--外面函数套着里面的函数的那种)甚至直到全局作用域。所以bar还留有foo()函数的引用。使得foo()函数没有被回收。

闭包可以说不出不在,只是你没有发现认出他。在定时器,事件监听器,ajax请求,跨窗口通信或者任何其他的异步(或者同步)任务中,只要使用了回调函数,实际上就是使用闭包。

for instance

function wait(message) {
    setTimeout(function timer() {
        console.log(message);
    }, 1000);
}
wait("hello");
Nach dem Login kopieren

在上面的代码中将一个内部函数(名为timer)传递给setTimerout(...).timer具有涵盖wait(...)的作用域的闭包。因此还保有对变量message的引用。wait()执行1000毫秒后,它的内部作用域不会消失,timer函数依然保有wait()作用域的闭包。

而闭包和立即执行函数息息相关。

循环和闭包

for(var i = 1; i <= 5; i++){
    setTimeout(function timer(){
        console.log(i);
    },i*1000);
}
Nach dem Login kopieren

上面代码我们以为输出的会是1-5,可事实上输出的是5个6,这是为啥啊 -- 闭包啊。

延迟函数的回调会在循环结束时执行。事实上,当定时器运行时即使每个迭代的是setTimerout(...,0),所有的回调函数依然是循环结束后才会执行。我猜是跟js执行机制有关系吧。至于为什么都是6. 因为即使5个函数是在各个迭代中分别定义的,但是他们又被封闭在一个共享的全局作用域中因此实际上只有一个i.而怎么解决呢,立即执行函数来了!!!

for (var i = 1; i <= 5; i++) {
    (function (i) {
        setTimeout(function timer() {
            console.log(i);
        }, i * 1000);
    })(i)

}
Nach dem Login kopieren

打印出来1,2,3,4,5了欧,这回是你想要的数了。解释一下,5次循环创建了5个立即执行函数,这5个函数的作用域都不相同,立即函数接收的参数是当前循环的i.所以当timer执行时访问的就是自己立即执行函数对应的作用域。也就是说5个timer函数分别对应5个作用域,每个作用域保存的变量i都不同,解决啦!!!

你懂闭包了吗?

js执行机制

JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊。JavaScript的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript的主要用途是与用户互动,以及操作DOM。这决定了它只能是单线程,否则会带来很复杂的同步问题。比如,假定JavaScript同时有两个线程,一个线程在某个DOM节点上添加内容,另一个线程删除了这个节点,这时浏览器应该以哪个线程为准所以,为了避免复杂性,从一诞生,JavaScript就是单线程,这已经成了这门语言的核心特征,将来也不会改变。

单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。JavaScript语言的设计者意识到这个问题,将所有任务分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。只要主线程空了,就会去读取"任务队列",这就是JavaScript的运行机制。

哪些语句会放入异步任务队列及放入时机一般来说,有以下四种会放入异步任务队列:setTimeout 和 setlnterval  ,DOM事件,ES6中的Promise,Ajax异步请求

 本文来自 js教程 栏目,欢迎学习!

Das obige ist der detaillierte Inhalt vonEine kurze Diskussion über JS-Funktionen und -Abschlüsse. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:cnblogs.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage