Magento – Magento 2 : scope of knockout JS variable

knockoutjsmagento2scope

Here's my code –

define(
[
    'ko',
    'uiComponent',
    'underscore',
    'jquery',
    'mage/url',
    'Magento_Checkout/js/model/quote',
    'Magento_Checkout/js/checkout-data',
    'Magento_Checkout/js/action/select-shipping-address'
],
function (
    ko,
    Component,
    _,
    $,
    urlBuilder,
    quote,
    checkoutData,
    selectShippingAddress
) {
    'use strict';

    return Component.extend({
        defaults: {
            template: 'Vendor_Module/shipping-address/list'
        },

        initObservable: function () {

        this._super()
            .observe({
                foo: ko.observable(false)                    
            });
        this._super()
            .observe({
                phoenix: ko.observable(false)                    
            });

        this.addresses = window.checkoutConfig.addresses;


        this.phoenix.subscribe(function(someVal){
            console.log("phoenix");
            var group = someVal;
            this.addresses.filter(function(el){
                console.log(el);
                return el.indexOf('Montreal');
            });
       this.foo.subscribe(function (newValue) {
            console.log(newValue);

        });


        return this;
        },



        initialize: function () {
            this._super();

            return this;
        },


        getAddressGroups:function(){
            return window.checkoutConfig.addressGroups;
        }


    });
},


 );

Error: TypeError: this.addresses is undefined

As far as I understand, this.addresses is a global variable.
Thanks

Best Answer

This is a context issue as the context of this changes in Javascript, inside the below code:

this.phoenix.subscribe(function(someVal){
    console.log("phoenix");
    var group = someVal;
    this.addresses.filter(function(el){
        console.log(el);
        return el.indexOf('Montreal');
});

this does not have the same context as it does when you are setting it.

When you set it this is the component, and when you try and access it this looks to be the event from the subscribe event (check by adding console.log(this) inside your subscribe function.

You can solve it by storing the 'correct' context in a variable. Outside your subscribe function add var self = this; and then use self instead of this - self.addresses.filter(function(el).

I recommending reading about this in Javascript - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

The working code would be:

var self = this;

this.phoenix.subscribe(function () {
    self.addresses.filter(function (el) {
        console.log(el);
        return el.indexOf('Montreal');
    });
});