简体   繁体   中英

Javascript object property undefined

I am trying to build a reddit api wrapper for node.js. I am fairly new to OO javascript and I am having an issue with assigning a value to my reddit object's properties.

var request = require("request");
var subreddit = require("./subreddit").subreddit;

var reddit = function () {

  var self = this,
      userAgent = "node.js api wrapper - https://github.com/theyshookhands/rednode",
      debug = false,
      cookie = "",
      uh = "";  

  self.getJSON = function (url, data, callback) {
    data["api_type"] = "json";
    request(url, { qs: data }, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        callback(body);
      }
    });
  };

  self.post = function (url, data, callback) {
    console.log("in post");
    console.log("cookie: " + self.cookie);
    console.log("uh: " + self.uh);
    data["api_type"] = "json";
    if (self.cookie) {
      request.cookie(self.cookie);
      console.log("cookie assigned");
    }
    if (self.uh) {
      data["uh"] = self.uh;
      console.log("uh assigned");
    }
    console.log("requesting");
    request.post(url, { form: data }, function (error, response, body) {
      if (!error && response.statusCode == 200) {
        console.log("no errors");
        callback(body);
      }
    });
  };

};

reddit.prototype = {

  login: function (username, password, callback) {
    var data = {
      "user": username,
      "passwd": password,
      "rem": false
    };

    this.post("http://www.reddit.com/api/login", data, function (body) {
      var response = JSON.parse(body);
      this.uh = response["json"]["data"]["modhash"];
      this.cookie = response.json.data.cookie;
      console.log("rednode --> logged in as: " + username);
      callback();
    });
  },

  setUserAgent: function (userAgent) {
    this.userAgent = userAgent;
  },

  r: function (name, callback) {
    var sr = new subreddit(name);
    if (callback) {
      sr.exec(callback);
    }
    return sr;
  },

  postLink: function (sr, title, url, callback) {
    var data = {
      "kind": "link",
      "sr": sr,
      "title": title,
      "url": url
    };
    console.log("calling post");
    this.post("http://www.reddit.com/api/submit", data, callback);
  }
}

exports.reddit = reddit;

The objects are defined at lines 15 and 16. They are given values at lines 62 and 63. Why am I not reaching these values using the

this.cookie, this.modhash

syntax?

When you use the keyword this to reference properties you have defined on your "object" they have to be within the same scope of the function/object.

You are incorrectly using the this keyword to reference the function/object variable/property which will actually be called reddit.cookie inside the scope of an unnamed callback function.

You must declare cookie as this.cookie =""; for it to be accessible as reddit.cookie however.

In the function:

var reddit = function () {

Why use a function expression where a function declaration will do and is likely clearer? And by convention, constructors start with a capital letter:

function Reddit() {

In the function:

  var self = this,

The value of a function's this is determined entirely by how the function is called. Since this is a constructor, when called with new its this will reference a newly constructed object (an "instance" of the constructor).

  var self = this,
      userAgent = "...",
      debug = false,
      cookie = "",

The above creates variables on the local execution object's variable object. You can only access variables by name, they are resolved on the scope chain of execution objects, ending with the global object.

...
self.post = function (url, data, callback) {
    console.log("in post");
    console.log("cookie: " + self.cookie);

Here, self on the LHS references the Reddit instance. On the RHS, the function expression has a closure to the outer scope so its self also references the same instance so you are looking for a cookie property on the object and its [[Prototype]] chain.

But you declared cookie as a local variable of the constructor, so the identifier is being resolved along the wrong chain (ie you should be looking for a variable on the scope chain, not a property on the object/ [[Prototype]] chain).

It just so happens that because of the closure, you can use:

    console.log("cookie: " + cookie);

to resolve cookie on the scope chain.

But it seems like you really want to access it as a property, so just make it a public property in the first place:

  var self = this,
      userAgent = "...",
      debug = false;

  this.cookie = "", // or self.cookie = '',
  ...

Now you can use self.cookie .

JavaScript doesn't really have the concept of private instance variables in the way you're trying to use them.

Only public members (explicitly set by saying this.whatever = "") can be accessed that way.

Otherwise you can still access them like any other variable by dropping the self. In front of them.

In your reddit constructor function, you define private variables like userAgent , cookie . To define public properties for your reddit object instances, you must proceed like this in your constructor function :

this.debug = false;

See this Douglas Crockford article for more informations.

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