Search code examples
javascriptnode.jsjavascript-objectsecmascript-5

Unable to access object variable from bound function, or internal method from unbound function


Just for reference, I'm trying to follow the Abstract Encoding specifications. Essentially, I want to create a "function variable" let foo = codec.encode, where encode() calls another function within codec, and I can access foo.bytes. It seems I can either access the value of bytes but not be able to access the inner function this.encodingLength(), or create a bound function variable and have the exact opposite occur. This issue only occurs when I assign the function encode() to a variable. I read somewhere that bind() creates a wrapper function (which wouldn't be able to access bytes, and also that the object functions cannot access other object functions if it doesn't have the correct context. Is it possible to have both worlds?

Example Code:

const codec = {
  encode: function encode () {
    encode.bytes = 2
    this.encodingLength()
  },
  encodingLength: function encodingLength () { }
}

let foo = codec.encode
let bar = codec.encode.bind(codec)

> foo()
TypeError: this.encodingLength is not a function
    at encode (repl:4:6)
> foo.bytes
2

> bar()
undefined
> bar.bytes
undefined

Also using this.encode.bytes seems to make no difference

const codec = {
  encode () {
    this.encode.bytes = 2
    this.encodingLength()
  },
  encodingLength () { }
}

Solution

  • Would this work for you?

    // define encodingLength function here
    function encodingLength(object) {
      // determine encoding length of obj here
      return 5; // dummy value
    }
    
    const codec = {
      encode: function encode(object, buffer, offset) {
        // encode object here
        // capture `encodingLength` in a closure
        encode.bytes = encodingLength(object); // dummy value
        return []; // dummy empty "buffer"
      },
      decode: function decode(buffer, start, end) {
        // decode buffer here
        decode.bytes = 12; // another dummy value
        return {}; // dummy "decoded" object
      },
      encodingLength: encodingLength
    };
    
    let foo = codec.encode;
    foo();
    console.log(foo.bytes); // 5, as expected
    console.log(codec.encode.bytes); // 5, as expected
    
    let bar = codec.decode;
    bar();
    console.log(bar.bytes); // 12, as expected
    console.log(codec.decode.bytes); // 12, as expected