2017-03-13 2 views
1

Als ich John Resigs Learning Advanced Javascript las, stieß ich auf zwei Folien, die ich nicht vollständig verstehe.Verweise auf Eigenschaften, die anonyme vs. benannte Funktionen sind

Folie # 13 - Referenzieren Sie eine Eigenschaft, die eine anonyme Funktion ist. Die zweite Behauptung schlägt fehl.

var ninja = { 
    yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
    } 
}; 
assert(ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either."); // PASS 

var samurai = { yell: ninja.yell }; 
var ninja = null; 

try { 
    samurai.yell(4); 
} catch(e){ 
    assert(false, "Uh, this isn't good! Where'd ninja.yell go?"); // FAIL 
} 

Folie # 14 - Referenzieren Sie eine Eigenschaft, die eine definierte Funktion ist. Die zweite Behauptung passiert.

var ninja = { 
    yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
    } 
}; 
assert(ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!"); // PASS 

var samurai = { yell: ninja.yell }; 
var ninja = {}; 
assert(samurai.yell(4) == "hiyaaaa", "The method correctly calls itself."); // PASS 

Der einzige Unterschied ist, dass yell ist eine benannte Funktion in Schlitten 14. Warum wird der Verweis auf eine Eigenschaft als benannte Funktion definiert bleiben auch nach dem ursprünglichen Objekt (ninja) auf ein neues Objekt Einstellung (oder sogar null)?

+0

@Weedoze - Nein. Funktionsdeklarationen werden gehisst. Funktionsausdrücke sind nicht. Funktionsdeklarationen * müssen * benannt sein. Funktionsausdrücke ** können ** benannt werden. Diese Frage betrifft den Unterschied zwischen benannten und anonymen Funktionsausdrücken. Es gibt keine Funktionserklärungen. – Quentin

Antwort

1

Der einzige Unterschied ist, dass Yell ist eine benannte Funktion in Schlitten 14.

Nein, das ist nicht der einzige Unterschied, noch der wichtigste Unterschied (obwohl es auf dem wichtigen Unterschied in engem Zusammenhang steht).

In der ersten, beachten Sie, wie ninja.yell definiert:

var ninja = { 
    yell: function(n){ 
    return n > 0 ? ninja.yell(n-1) + "a" : "hiy"; 
// ----------------^^^^^^^^^^^^^^^ 
    } 
}; 

Es nutzt explizit ninja.yell in sich. Rufen Sie also die Variable ninja auf und versuchen Sie dann, yell als Eigenschaft auf ninja nachzuschlagen.

Vergleichen, dass mit der Definition im zweiten Beispiel:

var ninja = { 
    yell: function yell(n){ 
    return n > 0 ? yell(n-1) + "a" : "hiy"; 
// ----------------^^^^^^^^^ 
    } 
}; 

yell verwendet nicht mehr die Variable ninja, es ist nur die in-scope verwendet Kennung für sich selbst (die man, indem die Funktion einen Namen erstellt via ein benannter Funktionsausdruck).

Deshalb, wenn ninja wird im ersten Beispiel genullt:

var ninja = null; 

... die erste beginnt nicht bestanden haben; Sie können nicht yell auf null nachschlagen.

Aber wenn ninaj in der zweiten Fassung (ich sehe nicht, warum John nicht null in beiden Fällen verwendet haben, aber was auch immer):

var ninja = {}; 

... yell kümmert sich nicht darum, weil es ninja nicht verwendet.


Randbemerkung: Ab ES2015, weder Version von yell ist eine anonyme Funktion, auch wenn die erste mit einem anonymen Funktion Ausdruck erstellt wird. In ES2015 kann eine Funktion ihren Namen basierend auf dem Kontext erhalten, und eine der Möglichkeiten, wie sie einen Namen erhält, besteht darin, dass sie einer Objekteigenschaft innerhalb eines Objektinitialisierers zugewiesen wird. Das hilft jedoch nicht bei diesem Problem, da der Name innerhalb der Funktion keine In-Scope-Kennung ist, wie wenn Sie einen benannten Funktionsausdruck verwenden.

+0

Gut erklärt, danke – bflemi3

1

Ein Funktionsausdruck wird als Referenz auf die Funktion ausgewertet.

foo = function() { ... }; 

Der Wert von foo ist nun ein Verweis auf die Funktion. Sie können diesen Wert beliebig kopieren.


A namens Funktion Ausdruck auch eine lokale Variable in sich erstellen, die den gleichen Namen wie die Funktion hat.

foo = function baz() { ... }; 

Hier ist foo ein Verweis auf die Funktion im globalen Gültigkeitsbereich. baz ist eine Referenz auf die Funktion innerhalb des Funktionsumfangs.


Sie können den Wert einer Variablen oder Eigenschaft löschen oder zu überschreiben, ohne eine andere Variable oder Eigenschaft zu beeinflussen, die eine Kopie dieser Referenz hält.

Der Unterschied zwischen Ihren beiden Fällen besteht darin, dass der zweite mit einer zweiten Referenz in einer anderen Variablen beginnt und (intern) diese Referenz statt der im weiteren Bereich verwendet.

Verwandte Themen