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

JavaScript Encapsulation - Stack Overflow

programmeradmin0浏览0评论

So I've been looking into full development object oriented JavaScript practices, and wonder about the following examples.

As I understand it, (and it makes sense to me) that the following 'secret' field is 'private' :

var MyObject = function() {

    var secret = 'sshhh';

    this.getSecret() = function() {
        return secret;
    }

}

and this is because the field secret has function scope that the inner function can access, but nothing outside ... so far so good.

But I've seen the following around (and especially in Douglas Crockford's book) :

var MyObject = function() {

    var secret = 'sshhh';

    return {
       getSecret : function() {
            return secret;
       }
    }   

}();

and was wondering what the difference is, why is it better? I understand that in this case we're not even returning the same object that the private field exists in, but don't see a huge benefit as you can't access the field directly either way.

So I've been looking into full development object oriented JavaScript practices, and wonder about the following examples.

As I understand it, (and it makes sense to me) that the following 'secret' field is 'private' :

var MyObject = function() {

    var secret = 'sshhh';

    this.getSecret() = function() {
        return secret;
    }

}

and this is because the field secret has function scope that the inner function can access, but nothing outside ... so far so good.

But I've seen the following around (and especially in Douglas Crockford's book) :

var MyObject = function() {

    var secret = 'sshhh';

    return {
       getSecret : function() {
            return secret;
       }
    }   

}();

and was wondering what the difference is, why is it better? I understand that in this case we're not even returning the same object that the private field exists in, but don't see a huge benefit as you can't access the field directly either way.

Share Improve this question edited Jul 27, 2010 at 23:13 Marcel Korpel 21.8k6 gold badges62 silver badges80 bronze badges asked Jul 27, 2010 at 22:23 lucas1000001lucas1000001 2,7501 gold badge25 silver badges22 bronze badges 5
  • The only thing I can think of is to avoid the delete and overwrite/override scenarios? – lucas1000001 Commented Jul 27, 2010 at 22:24
  • JavaScript: The Good Parts - well, I can hardly start reading this book because I got myself confused several times flipping through a few pages... – Michael Mao Commented Jul 27, 2010 at 22:30
  • Yeah tell me about it :S - is good and all, but definitely screws with your mind! – lucas1000001 Commented Jul 27, 2010 at 22:41
  • Don't format your code using quoting marks (>), but by indenting it with 4 spaces (use the code button in the editor pane, instead of the quote button). – Marcel Korpel Commented Jul 27, 2010 at 23:14
  • Argh sorry - will do in future – lucas1000001 Commented Jul 27, 2010 at 23:20
Add a ment  | 

7 Answers 7

Reset to default 7

Those examples are very different... The first creates a "MyObject" function that, when called as a constructor using new, will have a "getSecret" function as a property; the second creates a "MyObject" Object with a "getSecret" function as a property.

In that respect, this is sort of like the difference between a static method and a public method. In the first case, the method only exists when the constructor is called, not in the constructor itself. In the second case there is no constructor.

So let's say you have:

var MyObject1 = function() {
  var secret = 'sshhh';
  this.getSecret = function() {
    return secret;
  }
}

// ...

var MyObject2 = function() {
  var secret = 'sshhh';
  return {
    getSecret : function() {
      return secret;
    }
  }
}();

running some tests:

MyObject1.getSecret();
// TypeError: Object has no method 'getSecret'
var m1 = new MyObject1();
m1.getSecret();
// "sshhh"

MyObject2.getSecret();
// "sshhh"
var m2 = new MyObject2();
// TypeError: object is not a function

So MyObject1 is like a class, and MyObject2 is like a static class.

In larger objects, having the returned object explicitly showing what is returned helps you see what is exposed in one place instead of worrying that you've missed a this.something.

It's not any better - or worse. Its used in two different scenarios.

The first example you give would work well for using the function as a 'class':

 stuff = new MyObject();

The second example works well for defining an inline object with some functions on it / a "singleton".

If you want some more information on it there is an article referring to it as the revealing module pattern:

http://www.klauskomenda./code/javascript-programming-patterns/#revealing

They're functionally the same, at least when it es to calling new MyObject().getSecret();. The only difference is that the latter does not need to be called with new because it is essentially a "factory method" and creates the object for you.

All I can say is that the first example is way simpler to implement. Consider, the first variable is a function that returns a simple string with MyObject().

The second returns an object, which returns the "secret" with MyObject.getSecret().

So, I'd rather get the "secret" from the function by calling the former example (which requires less code to do the exact same thing), if that's what you mean by "better."

Perhaps Crockford had a bigger idea when he used the second example.

With Javascript, things are not so simple because, as Douglas Crockford described: “objects are collections of name-value pairs”, so we can dynamically define any property to any object any time we want. This is one idea to achieve encapsulation in Javascript:

var Person = (function () {
    var SSN = "";
    function Person(name, SSN) {
        this.name = name;
        /* Preventing any changes on the SSN property */
        Object.defineProperty(this, 'SSN', {
            value: "",
            writable : false,
            enumerable : true,
            configurable : false
        });
        this.getSSN = function() {
            return SSN;
        };
        this.setSSN = function(ssn) {
            console.log("Check red tape here");
            SSN = ssn;
        };
        this.setSSN(SSN);
    }
    return Person;
})();

When the object is instantiated, it executes the IEF (Immediately-Executed Function) and returns the inner “Person” function that holds a special reference to the variable SSN in the outer function (i.e., closure), this variable can only be accessed by the public methods within the object that is returned, so it simulates the behaviour from, let's say, a Java class.

var p = new Person("Marcelo","444");
var p2 = new Person("Joe","777");
p
Person {name: "Marcelo", SSN: "", getSSN: function, setSSN: function}
p2
Person {name: "Joe", SSN: "", getSSN: function, setSSN: function}
p.setSSN("111")
p2.setSSN("222")
p.getSSN()
"111"
p2.getSSN()
"222"
p.SSN = "999"
p.SSN
""
发布评论

评论列表(0)

  1. 暂无评论