How to inherit private variables in javascript using Object.create

I have it:

function Book (){
  this.width = 7;
  this.height = 10;
  var pages = 100;

  this.tear_page = function(){
    return --pages;
  }
}
function TechBook () {
  var pages = 50;
  this.open_book = function(){ return "Opened in page "+(pages/2); };
  return this;
}
var bBook = Object.create(new Book(), new TechBook());


console.log(bBook);
console.log(bBook.tear_page());
console.log(bBook.open_book());

      

I cannot get this to work. I got to the point where TechBook inherited access to local / private variables from the book, but only from the book functions. If I add new methods or overwrite them, they can't get these variables anymore. I wonder if there is a way to access these variables from the methods of the subclass and create new private variables within the subclass.

If this is in no way possible, it means that you cannot have private variables if you want to inherit or vice versa. Oh, and by the way, I know that now chrome now (thanks to ES6) implements classes naturally: the TechBook class extends Book () {} like many other languages, but since support is limited to the latest chrome versions at this time ... I wonder is there any other way to solve this problem.

+3


source to share


3 answers


Here is an example of how you can transfer data knowing a secret

function Book(secret) {
    secret = secret || {};
    var env = {}; // `env` to hold data requiring `secret`
    this.width = 7;
    this.height = 10;
    env.pages = 100;
    this.getEnv = function (s) { // give access to `env` if you know the secret
        if (s === secret) return env;
    };
    this.tear_page = function () {
        return --env.pages;
    };
}

function TechBook(secret) {
    secret = secret || {};
    Book.call(this, secret); // construct from Book
    var env = this.getEnv(secret); // get references via secret

    this.open_book = function () {
        return "Opened in page " + (env.pages/2);
    };
}

TechBook.prototype = Object.create(Book.prototype); // set up inheritance

      

Using an object reference as a secret is safer than using a primitive because you need the original reference to access it.



Now you have

var bBook = new TechBook();
console.log(bBook); // instance of TechBook
console.log(bBook.tear_page()); // 99
console.log(bBook.open_book()); // Opened in page 49.5

      

+2


source


You cannot inherit private in any language, only protected or public can be inherited.

This concept doesn't exist in javascript, but you can emulate when creating an object (properties = public, scope things = private);

A workaround could be to add a property that performs a function that returns a private variable / function of the object's scope.

If you expose a method that returns a private object, you can change it because u has a return reference.



I like to do it like this:

var SomeObject = function() {
    //private var one, can't access it outside of this scope
    var one = 1;

    /*private object anotherObject, can't access it directly
     but if you return it with a public function you can modify it.*/
    var anotherObject = {
        a : 'somevalue'
    };

    //public prop two, can access it outside of this scope.
    this.two = 2;

    //public method getOne, you can access it.
    this.getOne = function() {
       return one;
    };

    /* return private var anotherObject */
    this.getAnotherObject = function() {
       return anotherObject;
    };
};

var someObject = new SomeObject();
console.log(someObject.two); // print in console 2
console.log(someObject.getOne()); // print in console 1

var referencedObject = someObject.getAnotherObject();
console.log(referencedObject);
referencedObject.a = 'anotherValue';

console.log(someObject.getAnotherObject());

      

Fiddle

+5


source


Link to the basics of prototype inheritance and Object.create property arguments.

Implemented based on your example

function Book (){
  this.width = 7;
  this.height = 10;
  this.pages = 100;

  this.tear_page = function(){
    return --this.pages;
  }
  this.init = function() {
    return this
  }
}

Book.prototype = {
  open_book: function(){ return "Opened in page "+(this.pages/2) }
}


var bBook = Object.create(new Book(), {pages: { value: 50 } }).init();


console.log( new Book())              // { width: 7, height: 10, pages: 100, tear_page: [Function], init: [Function] }
console.log( bBook )                  //{}
console.log( bBook.width )            //->7              
console.log( bBook.height )           //-> 10             
console.log( bBook.pages )            // -> 50             
console.log( bBook.tear_page())       //-> 49
console.log(bBook.open_book())       //-> Opened in page 25

      

+1


source







All Articles