Mam obiekt i ma inny wewnętrzny przedmiot. Jak mogę zadzwonić do obiektu macierzystego z obiektu wewnętrznego?

var test = {
    init: function () {
        var instance = this;
    },
    call: function() {
        this.stop(); // works
    },
    stop: function() {
        this.parseText(); // works
    },
    parseText: {
        load: function ()
        {
            this.call(); //*** dont work
            instance.call(); // work, but what if i have this instance (same name) on another object, would'nt this conflict it?
        }
    }
};

Używam instancji, która działa dobrze, ale co, jeśli ja lub ktoś napisał instancję (ta sama nazwa) w innym obiekcie, czy nie będzie kolidować i zastąpić tej instancji?

2
Basit 30 październik 2011, 14:15

4 odpowiedzi

Najlepsza odpowiedź

Jeśli wszystko, o którym się martwisz, to zmiana test, zrób to:

var test = (function() {
    var object = {}
    object.call = function() {
        this.stop(); // works
    };
    object.stop = function() {
        this.parseText(); // apparently works, even though parseText is not a function
    };
    object.parseText = {
        load: function() {
            object.call(); // works
        }
    };
    return object;
})();
7
Eric 30 październik 2011, 10:19

Odpowiedź Eric daje rozsądny przykład, jak zrobić to, co chcesz zrobić, ale tak naprawdę nie idzie doczego.

W JavaScript, this jest ustawiony całkowicie przez , jak nazywa się funkcja (na teraz ; patrz poniżej fałdy, aby uzyskać szczegółowe informacje), a nie , gdzie funkcja jest zdefiniowany , ponieważ jest w innych językach, które mają tego samego słowa kluczowego (Java, C ++, C #, ...).

Coder, określić, co będzie this za każdym razem, gdy zadzwonisz do funkcji. Istnieją dwa główne sposoby: dzwoniąc do funkcji za pomocą właściwości obiektu (w tym samym wyrażeniu) lub wyraźnie przy użyciu wbudowanej funkcji call i apply.

Za pośrednictwem obiektu

Korzystanie z obiektu obiektu:

obj.foo();    // or
obj["foo"](); // both work

Wykonuje to dwie bardzo wyraźne rzeczy, ale które współpracują, aby ustawić wartość this: Najpierw odwołanie do funkcji znajduje się, szukając właściwości foo obiektu obj. Następnie wymagana jest funkcja. Ponieważ wezwasz go jako część tego samego wyrażenia ogólnego pobierania wartości nieruchomości, silnik JavaScript ustawił this do obj w połączeniu.

Tak więc w twoim przykładzie, test.parseText.load(), w load call this będzie parseText, a nie test, ponieważ to obiekt, na którym load został podekscytowany.

Należy pamiętać, że ustawienie - this - Via-właściwości-Lookup działa tylko wtedy, gdy są wykonywane w tym samym czasie. To robi nie praca:

var f = obj.foo;
f(); // `this` will not be `obj` within the call

To nie działa, ponieważ nie zostały wykonane w tym samym czasie. Wyszukiwanie właściwości i wywołanie funkcji zostały rozdzielone.

Za pomocą call lub apply

Drugi sposób ustawienia this jest bardziej wyraźny: Wszystkie funkcje mają właściwości call i apply, które są referencjami funkcji, które wywołują funkcję przy użyciu dostarczania informacji. W obu przypadkach pierwszy argument jest obiektem do użycia jako this podczas połączenia. Więc gdybyśmy chcieli naprawić przykład, który nie działa, moglibyśmy to zrobić:

var f = obj.foo;
f.call(obj);  // `this` will be `obj` within the call
f.apply(obj); // same

Jedyną różnicą między call a apply jest sposób dostarczania argumentów funkcji. Z call, dostarczasz je jako dalsze dyskretne argumenty do funkcji; Z apply przechodzisz w szeregu argumentów.

Więc wszyscy robią to samo:

// 1 - Directly via property
obj.foo("a", "b", "c");

// 2 - Using `call`
f = obj.foo;
f.call(obj, "a", "b", "c");

// 3 - Using `apply`
f = obj.foo;
f.apply(obj, ["a", "b", "c"]); // Note the `[ ... ]`, one array with three elements

Możesz zobaczyć, jak call i apply może współpracować z istniejącą strukturą:

test.parseText.load.call(test.parseText);

Korzystanie z test.parseText.load, tworzenie this = test.parseText w połączeniu.

Co Eric zrobił w swojej odpowiedzi, było użycie zamknięcia, aby było prostsze, aby zadzwonić parseText z oczekiwaną wartością this.

Dalsze czytanie (ujawnienie: z mojego bloga):


Top powiedział:

W javascript, this jest ustawiony całkowicie przez , jak nazywa się funkcja ( na razie ...

Powód, dla którego powiedziałem "na razie" jest to, że w ES6, JavaScript otrzymuje "Funkcje strzałki" i w przeciwieństwie do innych funkcji, wartość this w funkcji strzałki jest ustawiona przez , gdzie są tworzone , nie Jak nazywa się: otrzymują this z kontekstu, w którym je tworzysz.

Przypuśćmy, że pisał kod w metodzie obiektu i chciał użyć innego sposobu obiektu, nie wiem, informacje wyjściowe z tablicy (tak, jest to wymyślone). W ES5 prawdopodobnie to zrobiłeś:

this.output("Entries:");
theArray.forEach(function(entry, index) {
    this.output(index + ": " + entry);
}, this);
// ^------- tells `forEach` what to use as `this` during the callback

Jeśli zostawiłeś argument, masz błąd:

this.output("Entries:");
theArray.forEach(function(entry, index) {
    this.output(index + ": " + entry); // <== Bug, `this` is either
                                       // `undefined` (strict) or
                                       // the global object (loose)
});

Ale ponieważ strzałki funkcje dziedziczy this, skąd są tworzone, a nie pobierając go na podstawie tego, w jaki sposób są nazywane, wersja funkcji strzałki, która nie potrzebuje drugiego argumentu:

this.output("Entries:");
theArray.forEach((entry, index) => {
  this.output(index + ": " + entry);
});
9
Community 23 maj 2017, 12:27

Jeśli nie znasz nazwy test, możesz użyć samodzielnej funkcji anonimowej, aby utworzyć opakowanie i zapoznać się z obiektem, jak pokazano poniżej.

Należy pamiętać, że test nie jest odniesieniem do funkcji, ale do wartości zwracania funkcji anonimowej. Ponieważ nazwa obiektu (obj) jest zawinięta wewnątrz funkcji, nie można go odczytać ani modyfikować z zewnątrz

Poniższy roztwór jest schludny, nie zanieczyszcza zakresu test i działa jak urok. Jak wspomniano wcześniej, test odnosi się do tego samego obiektu, co obj. Nie jest jednak możliwe manipulowanie zmienną obj, z zewnątrz, dzięki czemu kod wewnątrz przerw w funkcji.

var test = (function(){ //Self-executing function
    var obj = {
        call: function() {
            this.stop(); // works
        },
        stop: function() {
            this.parseText(); // works
        },
        parseText: {
            load: function ()
            {
                obj.call();  // obj refers to the main object
            }
        }
    };
    return obj; //Return the object, which is assigned to `test`.
})(); //Invoke function

Aktualizacja

Nie można wiarygodnie odnosić się do self, this, lub dowolne odniesienie do obiektu wewnątrz obiektu, bez owijania go.

Twoje obecne rozwiązanie nie działa , zobacz Komentarze w poniższym kodzie:

var obj = {
   init: function(){
      var instance = this; //`instance` is declared using `var` inside a function
   },                       // This variable cannot read from "the outside"
   parseText: {
      load: function(){
          instance.call(); //Does NOT work! instance is not defined
      }
   }
}
5
Rob W 30 październik 2011, 10:36

"Zadzwoń" jest w rzeczywistości wbudowany W funkcji na obiekcie funkcji, który można użyć do wywołania funkcji określającą to, czego do wykorzystania. Jak działa twój kod? Wygląda na to, że powinno być, ponieważ Parsext nie jest funkcją ...

Może spróbuj tego:

parseText: function() {
    var load =  function ()
    {
        this.call(); //*** should work
    };
    load.call(this);
}
-1
Jason Goemaat 30 październik 2011, 10:35