knockoutのscope(context) 

    この記事は、knockout.js Advent Calendar 2015の８日目の記事です。 先に７日目に目を通すことを推奨しています。
    knockout , knockout-es5 , knockout.punches環境を想定しています。

knockoutにも、scope(context)の概念があります。
scopeが切り替わるタイミングは、``foreach``bindなどのイテレータでの子scopeや、``with``bindでの明示的なscope切換えを行った場合です。

例えば、[この**サンプル**](http://jsfiddle.net/MKGaru/mtavwtbp/)を見てみましょう。
Country(国)とState(州/県)とCity（市・区）はそれぞれ親子関係にあります。

```html:index.html
<div data-bind="foreach:countries">
    <div class="country">
        <span>{{name}}</span>
        {{#foreach: states}}
        <div class="state">
            <span>{{name}}</span>
            {{#foreach: cities}}
            <div class="city">
                <span>{{name}}</span>は、{{$parents[1].name}}の{{$parents[0].name}}にあります
            </div>
            {{/foreach}}
        </div>
        {{/foreach}}
    </div>
</div>
```

``<div data-bind="foreach:list">``は、divの内側を繰り返し、
``{{#foreach:list}} {{/foreach}}``もまた、このタグの内側を繰り返します。 
これは、``<!-- ko foreach:list--><!-- /ko -->``の構文糖衣です。
[VirtualElement](http://knockoutjs.com/documentation/custom-bindings-for-virtual-elements.html)と呼ばれるもので、余計なタグのネストを避けるために利用しています。

    (コメントを用いる方法を使ってもいいのですが、すこし長いですし、最適化ツールなどでコメントが消された場合に、不都合が生じるので注意が必要です。)

サンプルを眺めてみると、なんとなくわかる通り、

div.countryの内側が指す name は国名ですし、
div.stateの内側側す name は 県・州名です。
div.cityでは name は市・区名となっています。

子scopeから親scopeを参照するには、 ``$parents``を使います。
``$parents[0]``と``$parent`` は等価です。
cityのscopeからみて、
　\$parents[0]はstateのscopeで、
　\$parents[1]はcountryのscope
となっています。

```js:script.js
function Country(name){
    this.states=[];
    this.name = name;
    ko.track(this);
}
function State(name){
    this.cities=[];
    this.name = name;
    ko.track(this);
}
function City(name){
    this.name = name;
    ko.track(this);
}

function VM(){
    var countries = this.countries = [];
	var src = [
        {
            name:'jp',
            state:[
                {name:'東京',city:[{name:'千代田'},{name:'港'},{name:' 渋谷'}]},
                {name:'大阪',city:[{name:'大阪'},{name:'堺'},{name:'松原'}]},
                {name:'宮城',city:[{name:'仙台'},{name:'角田'},{name:'名取'}]}
            ]
        },
        {
            name:'us',
            state:[
                {name:'Texas',city:[{name:'SanAntonio'},{name:'Austin'},{name:' Huston'}]},
                {name:'NewYork',city:[{name:'Rochester'},{name:'Buffalo'}]}
            ]
        }
    ];
    // mapping to model
    src.forEach(function(c){
        var country = new Country(c.name);
        c.state.forEach(function(s){
            var state = new State(s.name);
            s.city.forEach(function(ci){
            	state.cities.push(new City(ci.name));
        	});
            country.states.push(state)
        });
        countries.push(country);
    });
    ko.track(this);
}
var vm = new VM();

ko.punches.enableAll();
ko.applyBindings(vm);
```

------------------------------------------------------------------------
scopeのcontextには、
 ``$parent``や``$parents[]``や``$data``　そして、イテレータのscopeでは``$index``を持っています。
　それぞれ、
　　``$parent``は、自分の親scope、
　　``$parents``は、自分の先祖scope、
　　``$data``は、自分自身のscope、
　　``$index``は、親から見た自分のindex
　となります。

  
  ``$data``の使い道は、例えば　``data-bind="foreach:['A','B','C']"``など、propertyを有さないprimitiveな値をまわす際などに使ったりします。