最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Define JavaScript get and set function in object without using "this"? - Stack Overflow

programmeradmin2浏览0评论

I have a simple global object with a get and set function. JSlint is not liking that I am using "this" in the get and set function because it violates "use strict". What would I replace "this" with so that it would not violate "use strict" (i.e. how go I reference the same thing "this" is referencing without using "this")?

function fnDirty() {
    "use strict";
    var bIsdirty = false;

    this.get_bIsdirty = function() {return bIsdirty; };
    this.set_bIsdirty = function(x) {bIsdirty = x; };
}
var GV_oDirty = new fnDirty();

I have a simple global object with a get and set function. JSlint is not liking that I am using "this" in the get and set function because it violates "use strict". What would I replace "this" with so that it would not violate "use strict" (i.e. how go I reference the same thing "this" is referencing without using "this")?

function fnDirty() {
    "use strict";
    var bIsdirty = false;

    this.get_bIsdirty = function() {return bIsdirty; };
    this.set_bIsdirty = function(x) {bIsdirty = x; };
}
var GV_oDirty = new fnDirty();
Share Improve this question asked Aug 27, 2012 at 0:30 LukeSLukeS 8092 gold badges9 silver badges17 bronze badges 2
  • 3 My question is why does this conflict with "use strict"? – jfriend00 Commented Aug 27, 2012 at 0:47
  • 2 jsLint isn't plaining about your usage of this, but is really plaining about your malformed class name. Renaming you constructor of function Dirty() yields no errors/warning. – J. Holmes Commented Aug 27, 2012 at 0:48
Add a ment  | 

3 Answers 3

Reset to default 5

By convention, constructor functions begin with capital letters. JSLint will allow use of this in strict mode if you are in a constructor function but yours begins with a lowercase letter so it does not get recognized as a constructor.

function FnDirty() {
    //your code
}

To answer your remaining question: "What is the roundabout way of doing this without a constructor?"

Brian had the right-ish idea -- but what he was really creating was a singular object with private properties, rather than a factory.

So to that end, if you wanted a function which granted each instance of the "class" its own unique copy of the private property, you could do this (I'm going to illustrate an actual class of something more useful than "Foo" and "Bar", to better-illustrate the concept -- it should be very simple to repose this into whatever your intended use is):

var makeWallet = function (starting_amount) {
    var amount = starting_amount,
        overdraft = 1000,
        addAmount = function (added_funds) { amount += added_funds; },
        deductAmount = function (extracted_amound) {
            if (is_sufficient_funds(amount, overdraft, extracted_amount)) {
                amount -= extracted_amount;
                return makeWallet(extracted_amount);
            }
        },
        // other needed public/helper methods here...
        // checkBalance(), is_sufficient_funds(), etc...
        public_interface = {
            // add all public-API methods you need here
            addFunds : addAmount,
            deductFunds : deductAmount
        };

     return public_interface;
};

Now, you've got a function which will return an object. Each object has methods which access that object's own "private" (ie: closed-over) amount variable, which is unique to those methods and only accessible to those methods.

Whether you build the functions as vars in the private scope, or build them as function declarations in the private scope, or put them directly into a return { func1 : () {...},... }; is irrelevant, as long as they're defined inside of that function when it's called (ie: not on the prototype chain -- which you CAN'T use in this pattern, anyway -- you will NOT call this function with new).

Okay, so that's all well and good. You've now got a working wallet-maker (without the security and user-features, yadda-yadda... ...homework).

But what if you wanted to add PRIVATE STATIC members to that? What if you needed to keep track of serial keys, so that you could issue bank cards to people? Or you needed to track the branch-number? This is where Brian's IIFE es into play. Except that instead of returning the finished wallet object, it's going to return the wallet FACTORY.

var makeWallet = (function () {
    var serial_num = 0,
        branch_num = "A011002z";
    function walletMaker = function (starting_amount) {
        /*same function as before, except that you ALSO call:
          serial_num += 1; in the construction of the wallet, and assign the id */
        var id = serial_num += 1;
        return wallet;
     }

     // then you return the wallet-factory
     // which bees the new value of the outer function
     return walletMaker; 
}());

Now you've got static properties (in the outermost closure, that the wallet-factory will have permanent access to, as "static" members), AND you have instance-based private members, which inner-methods, added during the creation of the instance-object, will have plete access to.

The only downsides to this are:

  1. Lose the prototype ability for this particular class, because you aren't using a constructor. Meh. If your objects need this setup, then it's worth not having it...
    ...if they don't, and public-everything is cool, then just use a constructor, and prototype -- or just build inline objects, with no methods, and build services (functions) to operate on each similarly-built object.

  2. If you build all objects this way, you're going to suffer a memory penalty, when you make thousands of these, or tens of thousands of these objects, each with their own copies of functions (to enclose the private references). Again, this is the price you pay for the functionality. Take the memory hit where security/clean interfaces are a must, and don't, where you don't need to.

Also goes without saying, but avoid using this in financial-institutions, as client-facing code isn't the best place to trust with the power to add and remove real money...

Hope that clears things up.

You can use an alternative approach:

var fnDirty = (function() {
  var _isDirty = false;

  return {
    get_dirty: function() { return _isDirty; },
    set_dirty: function(val) { _isDirty = value; }
  };

})();
发布评论

评论列表(0)

  1. 暂无评论