web-dev-qa-db-ja.com

javascriptオブジェクトから親の親にアクセスする

何かのようなもの

var life= {
        users : {
             guys : function(){ this.SOMETHING.mameAndDestroy(this.girls); },
             girls : function(){ this.SOMETHING.kiss(this.boys); },
        },
        mameAndDestroy : function(group){ },
        kiss : function(group){ }
};

this.SOMETHINGは私が想像している形式ですが、そうではないかもしれません。オブジェクトの親に戻るには何が必要ですか?

54
Robert

JavaScriptはこの機能をネイティブに提供しません。そして、このタイプの機能を作成することさえできないと思います。例えば:

var Bobby = {name: "Bobby"};
var Dad = {name: "Dad", children: [ Bobby ]};
var Mom = {name: "Mom", children: [ Bobby ]};

ボビーは誰のものですか?

43
harley.333

最初の関数に追加しただけです

parentThis = this;

そして、サブ関数でparentThisを使用します。どうして? JavaScriptでは、オブジェクトはソフトだからです。新しいメンバーは、単純な割り当てによってソフトオブジェクトに追加できます(つまり、Javaではなく、古典的なオブジェクトはハードです。ハードオブジェクトに新しいメンバーを追加する唯一の方法は、新しいクラス)詳細はこちら: http://www.crockford.com/javascript/inheritance.html

また、最後にオブジェクトを殺したり破壊したりする必要はありません。ここで見つけた理由: http://bytes.com/topic/javascript/answers/152552-javascript-destroy-object

お役に立てれば

57
jazkat

この場合、lifeを使用して親オブジェクトを参照できます。または、lifeへの参照をusersオブジェクトに保存できます。ユーザーがオブジェクトへの単なる参照であり、他の参照が存在する可能性があるため、言語で使用可能な固定のparentはありません...

var death = { residents : life.users };
life.users.smallFurryCreaturesFromAlphaCentauri = { exist : function() {} };
// death.residents.smallFurryCreaturesFromAlphaCentauri now exists
//  - because life.users references the same object as death.residents!

次のようなものを使用すると便利です。

function addChild(ob, childName, childOb)
{
   ob[childName] = childOb;
   childOb.parent = ob;
}

var life= {
        mameAndDestroy : function(group){ },
        kiss : function(group){ }
};

addChild(life, 'users', {
   guys : function(){ this.parent.mameAndDestroy(this.girls); },
   girls : function(){ this.parent.kiss(this.boys); },
   });

// life.users.parent now exists and points to life
19
Shog9

私があなたの質問を正しく読んでいるなら、一般にオブジェクトはそれらがどこに含まれているかについて不可知です。彼らは両親が誰なのか知りません。その情報を見つけるには、親データ構造を解析する必要があります。 DOMには、ドキュメント内の要素オブジェクトについて話しているときにこれを行う方法がありますが、バニラオブジェクトについて話しているように見えます。

4
Adam Bellaire

コールについて:

.call() を使用して、この問題を解決できます:

  • 関数で呼び出す必要がありますaddName.call()
  • 「これ」にしたいもののオブジェクトを渡しますaddName.call({"name" : 'angela'});
  • addName.call({"name": "angela"}, true);で呼び出される関数で使用できる追加の引数を渡すことができます。おそらくaddNameはブールappendの引数を受け入れます。

コールを使用:

この特定の問題については、callを介して「親」オブジェクトを渡して、子オブジェクトに通常存在するthisをオーバーライドできます。

最初に問題を見てください

var app = {
    init: function() {
        var _this = this; // so we can access the app object in other functions

        $('#thingy').click(function(){
            alert(_this.options.thingy());
        });

        $('#another').click(function(){
            alert(_this.options.getAnother());
        });
    },
    options: {
      thingy: function() {
      // PROBLEM: the this here refers to options
        return this.getThingy();
      },
      getAnother: function() {
        // PROBLEM 2: we want the this here to refer to options,
        // but thingy will need the parent object
        return 'another ' + this.thingy();
      },
    },
    getThingy: function() {
        return 'thingy';
    }
};

さて、ここにソリューション使用の呼び出しがあります

そして [〜#〜] jsfiddle [〜#〜] 動作を確認します。

var app = {
    init: function() {
        var _this = this; // so we can access the app object in other functions

        $('#thingy').click(function(){
            // SOLUTION: use call to pass _this as the 'this' used by thingy
            alert(_this.options.thingy.call(_this));
        });

        $('#another').click(function(){
            // SOLUTION 2: Use call to pass parent all the way through
            alert(_this.options.getAnother.call(_this)); 
        });
    },
    options: {
      thingy: function() {
        // SOLUTION in action, the this is the app object, not options.
        return this.getThingy(); 
      },
      getAnother: function() {
        // SOLUTION 2 in action, we can still access the options 
        // AND pass through the app object to the thingy method.
        return 'another ' + this.options.thingy.call(this); 
      },
    },
    getThingy: function() {
        return 'thingy';
    }
};

結論として

メインオブジェクトのプロパティでメソッドを使用するときはいつでも.call()を使用できます。app.options.someFunction(arg)は常に.call-app.options.someFunction.call(this, arg);で呼び出す必要があります。 llは常にオブジェクトのすべての部分にアクセスできます。 app.helpers.anotherFunction()のような別のプロパティのメソッドにアクセスできます。

somefunctionを使用して、_thisを変数_parentThisに格納することをお勧めします。したがって、thisが何を反映しているかは明らかです。

4
amurrell

どうぞ:

var life={
        users:{
             guys:function(){ life.mameAndDestroy(life.users.girls); },
             girls:function(){ life.kiss(life.users.guys); }
        },
        mameAndDestroy : function(group){ 
          alert("mameAndDestroy");
          group();
        },
        kiss : function(group){
          alert("kiss");
          //could call group() here, but would result in infinite loop
        }
};

life.users.guys();
life.users.girls();

また、「girls」の定義の後にカンマがないことを確認してください。これにより、スクリプトはIEでクラッシュします(IEで死ぬ)の配列の最後の項目の後にコンマがある場合はいつでも)。

実行を参照

3
cmcculloh

他の人が言ったように、ネストされた子から直接親を検索することはできません。提案されているソリューションはすべて、明示的な変数名を介して親オブジェクトまたは親スコープを参照するさまざまな方法を推奨しています。

ただし、親オブジェクトで再帰 ES6プロキシ を使用すると、親オブジェクトまで直接移動できます。

ObservableSlim と呼ばれるライブラリを作成しました。これにより、とりわけ、子オブジェクトから親まで上に移動できます。

以下に簡単な例を示します( jsFiddle demo ):

var test = {"hello":{"foo":{"bar":"world"}}};
var proxy = ObservableSlim.create(test, true, function() { return false });

function traverseUp(childObj) {
    console.log(JSON.stringify(childObj.__getParent())); // returns test.hello: {"foo":{"bar":"world"}}
    console.log(childObj.__getParent(2)); // attempts to traverse up two levels, returns undefined because test.hello does not have a parent object
};

traverseUp(proxy.hello.foo);
2
Elliot B.

シングルトンパターンに似たものを使用しました。

function myclass() = {
    var instance = this;

    this.Days = function() {
        var days = ["Piątek", "Sobota", "Niedziela"];
        return days;
    }

    this.EventTime = function(day, hours, minutes) {
        this.Day = instance.Days()[day];
        this.Hours = hours;
        this.minutes = minutes;
        this.TotalMinutes = day*24*60 + 60*hours + minutes;
    }
}
1
Parchandri

私はこのようなことをしました、そしてそれは魅力のように働きます。

シンプル。

追伸オブジェクトはもっとありますが、関連する部分を投稿しました。

var exScript = (function (undefined) {
    function exScript() {
        this.logInfo = [];
        var that = this;
        this.logInfo.Push = function(e) {
            that.logInfo[that.logInfo.length] = e;
            console.log(e);
        };
    }
})();
0
transilvlad

リテラルオブジェクト({})のノードのすべての親キーを取得する場合は、次のようにできます。

(function ($) {
    "use strict";

    $.defineProperties($, {
        parentKeys: {
            value: function (object) {
                var
                    traces = [],
                    queue = [{trace: [], node: object}],

                    block = function () {
                        var
                            node,
                            nodeKeys,
                            trace;

                        // clean the queue
                        queue = [];
                        return function (map) {
                            node = map.node;
                            nodeKeys = Object.keys(node);

                            nodeKeys.forEach(function (nodeKey) {
                                if (typeof node[nodeKey] == "object") {
                                    trace = map.trace.concat(nodeKey);
                                    // put on queue
                                    queue.Push({trace: trace, node: node[nodeKey]});

                                    // traces.unshift(trace);
                                    traces.Push(trace);
                                }
                            });
                        };
                    };

                while(true) {
                    if (queue.length) {
                        queue.forEach(block());
                    } else {
                        break;
                    }
                }

                return traces;
            },

            writable: true
        }

    });

})(Object);

このアルゴリズムは、FIFOメソッドを使用してグラフを反復するためにBFSコンセプトを使用します。このコードは、クラスObjectを拡張し、Javacriptのliteral Object(ハッシュテーブル-連想配列...)をパラメーターとして期待する静的メソッドparentKeysを追加します。

お役に立てば幸いです。

0
rplaurindo

次のコードを使用すると、オブジェクトの親にアクセスできます。

var Users = function(parent) {
    this.parent = parent;
};
Users.prototype.guys = function(){ 
    this.parent.nameAndDestroy(['test-name-and-destroy']);
};
Users.prototype.girls = function(){ 
    this.parent.kiss(['test-kiss']);
};

var list = {
    users : function() {
        return new Users(this);
    },
    nameAndDestroy : function(group){ console.log(group); },
    kiss : function(group){ console.log(group); }
};

list.users().guys(); // should output ["test-name-and-destroy"]
list.users().girls(); // should output ["test-kiss"]

オブジェクトの操作方法を知るために、javascript Objects を読むことをお勧めします。存在すら知らなかった関数についても知りました。

0
Rodrigo Morales