简体   繁体   中英

Javascript prototype: how do I call a method within another method?

This is my first attempt to javascript prototyping. I am using the Espruino(javascript interpreter for microcontrollers) to get data from environment sensors. I am trying to pause my code for 1000ms, then execute the getSensorReading() method which is(I think) located inside of another method. How do I execute getSensorReading() method? I believe the error is cause by this:

setTimeout(function (e) { this.getSensorReading(); }, w); //Attempting to execute getSensorReading()

I am receiving this error:

Uncaught Error: Function "getSensorReading" not found!  at line 1 col 8 { this.getSensorReading(); }
        ^ in function called from system

Code:

I2C1.setup({scl:b6, sda:b7});

function Sensor (theType, theAddress) {
  this.type = theType;   //i.e. PH
  this.address = theAddress;  //i2c Address
  this.sensorResult = 0; //Store sensor result
  this.cmdTable = {
    "Calibrate" : {  //List of Calibration commands and timeout value.
      "clear" : { "cmd" : "Cal,Clear",      "wait" : 300  },
      "mid"   : { "cmd" : "Cal,mid,7.00",   "wait" : 1300 },
      "low"   : { "cmd" : "Cal,low,4.00",   "wait" : 1300 },
      "high"  : { "cmd" : "Cal,high,10.00", "wait" : 1300 },
      "query" : { "cmd" : "Cal,?",          "wait" : 300  }
    },
    "Information" : {  //Device Information

    },
    "LED" : {  //Enable / Disable or Query the LEDs
      "L0" : { "cmd" : "L,0", "wait" : 300 },
      "L1" : { "cmd" : "L,1", "wait" : 300 },
      "L?" : { "cmd" : "L,?", "wait" : 300 }
    },
    "Reading" : {  //Takes a single reading
      "R" : { "cmd" : "R,25.6", "wait" : 1000 } //Takes a single temperature compensated reading
    },
    "Serial"      : {  //Switch back to UART mode

    },
    "Sleep"       : {  //Enter low power sleep mode

    },
    "Status"      : {  //Retrieve status information

    },
    "Temperature" : {  //Set or Query the temperature compensation
      "T"  : { "cmd" : "T,19.5", "wait" : 300 },  //Where the temperature is any value; floating point, or int, in ASCII form
      "T?" : { "cmd" : "T,?",   "wait" : 300 }  //Query the set temerature
    },
    "Factory"     : {  //Factory reset

    },
  };
}

Sensor.prototype = {
  constructor: Sensor,
  getSensorType:function () {
    return this.type; //Get Sensor type
  },
  getSensorAddress:function () {
    return this.address; //Get Sensor address
  },
  getSensorReading:function() {
    a = this.getSensorAddress;
    console.log("i2c Address: " + a);
    //d = I2C1.readFrom(a, 7);
    return d;
  },
  getSensorResult:function () {
    a = this.getSensorAddress;
    c = this.cmdTable.Reading.R.cmd;
    w = this.cmdTable.Reading.R.wait;

    //I2C1.writeTo(a, c);
    setTimeout(function (e) { this.getSensorReading(); }, w); //Attempting to execute getSensorReading()
  },
  storeSensorResult:function () {

  },
  updateResTemp:function (temp) {
    console.log("Before: " + this.cmdTable.Reading.R.cmd);
    this.cmdTable.Reading.R.cmd = "R," + temp;
    console.log("After: " + this.cmdTable.Reading.R.cmd);
  }
};

var ph = new Sensor("ph", 0x63);

ph.updateResTemp(90.5);
ph.getSensorResult();

In your code "this" in setTimeout callback refers the parent function getSensorResult . That function doesn't have a function called getSensorReading . That's the reason for the error... Also as you are using global variables inside function unexpected results may occur by overbidding the variables. Make them global with var keyword. Try changing like this..

getSensorReading:function() {
    var a = this.getSensorAddress;
    console.log("i2c Address: " + a);
    //var d = I2C1.readFrom(a, 7);
    return d;
  },
getSensorResult:function () {
    var a = this.getSensorAddress;
    var c = this.cmdTable.Reading.R.cmd;
    var w = this.cmdTable.Reading.R.wait;
    var that = this;
    //I2C1.writeTo(a, c);
    setTimeout(function (e) { that.getSensorReading(); }, w); //Attempting to execute getSensorReading()
  }

Declare global method foo and sub-method bar and refer to sub-method as function in itself, you can use this keyword inside sub-method by addressing previously declared variable, and then declare the return variable as the sub-method process.

Foo: function()
{
    var a='a';
    var ret='b';

    var Bar = function()
    {
        this.a='a';
        return 'a';    
    }

    ret=Bar();

    return ret; 
}

Agreed with looking into this , Function.prototype.bind , and also the prototype chain in general. Also, javascript is a dynamically bound language. You can re-bind this .

you can either store a reference to this as a closure variable, or bind the function literal that you're passing to setTimeout to the context you want ( Sensor.prototype or this in that context)

EDIT: In lieu of having bind available, you can accomplish the same thing with apply, call, or closures.

getSensorResult:function () {
    a = this.getSensorAddress;
    c = this.cmdTable.Reading.R.cmd;
    w = this.cmdTable.Reading.R.wait;

    //I2C1.writeTo(a, c);
    setTimeout((function(_this) {
      return function (e) {
        _this.getSensorReading();
      }
    })(this), w); //Attempting to execute getSensorReading()
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM