this is prototypal model in javascript.
unlike use constructor function with new keyword in this pattern we are using
existing object to create a new object as shown below
var answerprototype = {
name:'ss',
get:function fn1()
{
return "--";
}
}
var lifeanswer = Object.create(answerprototype);
this is how implement private ,public members in javascript using classical pattern
function Restaurant()
{
//private varible
var myPrivateVar = 'aaa';
//public variable
this.myPublicVar = 'bbbb'
//private method
// Only visible inside Restaurant()
var private_stuff = function()
{
return "private metho";
}
//public method
// use_restroom is visible to all
this.use_restroom = function()
{
return "public method"
}
}
//create object
var r1 = new Restaurant();
r1.myPrivateVar //return undefined
r1.myPublicVar //return "bbbb"
r1.private_stuff() //error
r1.use_restroom() //return "public method"
this is how implement static members in javascript using classical pattern
function Shape(shapeName)
{
//instance field
this.ShapeName = shapeName;
//static field
Shape.Count = ++Shape.Count;
//static method
Shape.ShowCount = function()
{
return Shape.Count;
}
}
var shape1 = new Shape("circle");
var shape1 = new Shape("rectangle");
var shape1 = new Shape("Triangle");
Shape.ShowCount(); //return 3
i want to implement static members and private ,public members in javascript using prototypal pattern(not using new keyword with constructor function)
how to do it
In JavaScript, private doesn't mean what you think it means. You have to create a closure which is where you trap your "private" values.
Using a function is the traditional way to create a closure
function makeProto(chainTo) {
const secret = 'foo';
return Object.assign(Object.create(chainTo || null), {
get hello() {return secret;}
});
}
let fizz = makeProto();
fizz.hello; // "foo"
Object.prototype.hasOwnProperty.call(fizz, 'hello'); // true
With ES6, you can use the block-scoped let or const in combination with the function scoped var to achieve something similar
;{
let foo = 'bar';
var obj = {
get baz() {return foo;}
};
}
obj.baz; // "bar"
foo; // ReferenceError
Please remember that as soon as you inherit from one of these objects, all descendant objects will share the same references to these values, not create new ones
I wrote ;{ /* ... */ } so if you try the code in your console it doesn't attempt to interpret this pattern as an Object literal, but instead a code block. In production the initial ; is not necessary.
Related
I am trying to build a javascript app with a document database that can store and retrieve object data (provided as api) without function members.
Now I have a class which have many properties and some functions as prototype.
Project: function(){
this.a= 'abc';
this.f = function(){
console.log(this.a);
}
}
//object from the databse
p0 = {
a: 'abc';
}
I want to convert a plain object to an object with member function usable.
When I try something like this, it won't work:
// It won't work:
// for it needs a map that have many properties such as writable etc.
var pobj = Object.create(new Project(), p0);
I tried to search this question with different keywords on the internet, but I didn't find one related.
The function you probably want to use is Object.assign.
So you can use Object.create to create an instance of the class (using the prototype), then assign the values from the data onto the new instance and then call the constructor (make sure to not override the values).
function Project() {
if (this.foo === undefined) this.a = 'foobar';
return this;
}
Project.prototype.print = function() {
console.log(this.foo);
};
var data = {
foo: 'bar'
};
var obj = Object.create(Project.prototype); // empty instance
obj = Object.assign(obj, data); // copy data
obj = obj.constructor(); // start constructor
obj.print();
Alternatively you could create a new instance using the new operator and then assign the data.
function Project() {
this.a = 'foobar';
return this;
}
Project.prototype.print = function() {
console.log(this.foo);
};
var data = {
foo: 'bar'
};
var obj = Object.assign(new Project(), data);
obj.print();
Unrelated note
It's usually a good idea to declare public functions that don't require closure outside the function body using class.prototype.functionName = function(){...}
What's the difference between the following two ways of implementing class inheritance in JavaScript?
function Super () {
}
function Sub() {
}
Sub.prototype = new Super();
vs.
Function.prototype.inherits = function inherits(ParentClass) {
function Surrogate () {};
Surrogate.prototype = ParentClass.prototype;
this.prototype = new Surrogate();
}
Specifically, for the second example using a surrogate function, why can't we just use:
Function.prototype.inherits = function inherits(ParentClass) {
this.prototype = new ParentClass();
}
I thought that by calling new on the ParentClass() and setting it to this.prototype, the this.prototype then points to ParentClass.prototype, hence inheriting from the latter.
Specifically, for the second example using a surrogate function, why can't we just use [...]
The Surrogate way is basically a shim for Object.create, the modern practice is
Sub.prototype = Object.create(Super.prototype);
and if you need to invoke the constructor of Super on your instance,
function Sub() {
// an instanceof check here
Super.apply(this);
// construct Sub as desired
}
The advantage of not having an instance of Super as the prototype of Sub is that we have better control over instances of Sub and don't have weird bugs resulting from unexpected shared values,
Consider the following
function Foo() {
this.bar = [];
}
function Fizz() {}
Fizz.prototype = new Foo();
var a = new Fizz(),
b = new Fizz();
a.bar.push('Hello world!');
// What is b.bar?
b.bar; // ["Hello world!"], we are sharing with `a`
vs
function Foo() {
this.bar = [];
}
function Fizz() {
Foo.apply(this);
}
Fizz.prototype = Object.create(Foo.prototype);
var a = new Fizz(),
b = new Fizz();
a.bar.push('Hello world!');
// What is b.bar?
b.bar; // [], `b` has some privacy at last
If I use constructor functions for my objects and prototype for shared functionality I would like to mixin shared functionality (functions) to the object's prototype but instance specific (this varaibles) to the object instances.
To add the prototype part I found this pattern. To set instance variables that are assumed to be there by the prototype functions I came up with an init (one for each mixin).
Here is a simple example:
var mixIn=function(target,source){
for(fn in source){
if(source.hasOwnProperty(fn)){
target.prototype[fn]=source[fn];
}
}
};
var SpeakEnable = {
say:function(){
console.log(this.message);
},
initSpeak:function(){// for initializing instance vars
this.message="Hello World Mixed in!";
this.object=[];
}
};
var Person=function(){
this.initSpeak();//have to init instance vars
};
// set up inheritance
// set up Person.prototype
// set speak enable
mixIn(Person,SpeakEnable);
var lulu=new Person();
lulu.say();
var june=new Person();
console.log(june.say===lulu.say);//true
console.log(june.object===lulu.object);//false
This all works fine and dandy but initializing the instance variables is where I have some problem with. It somehow doesn't seem to be a very clean way. When I mix in several mixins the Person constructor function has to call all the init functions to set up the instance variables. Forgetting to call it will result in strange errors (in this case console logging undefined when say is called on an instance).
So the question is: is there a cleaner way to setup initial instance variables that are assumed to be there by the mixin functions?
You could inherit all mixable objects from a base object that ensures proper initialization. This is a clean way of achieving your goal.
The following code demonstrates this principle:
//------------ framework
var inherits = function(childCtor, parentCtor) {
function tempCtor() {};
tempCtor.prototype = parentCtor.prototype;
childCtor.superClass_ = parentCtor.prototype;
childCtor.prototype = new tempCtor();
childCtor.prototype.constructor = childCtor;
};
var mixIn=function(target,source){
for(fn in source){
if(source.hasOwnProperty(fn) && fn.name != 'init'){
target.prototype[fn]=source[fn];
}
}
if (typeof source.init == 'function') {
if (target.prototype._mixInits === undefined) {
target.prototype._mixInits = [];
}
target.prototype._mixInits.push(source.init);
}
};
// all objects that can be mixin's should inherit from
// this object in order to ensure proper initialization
var Mixable = function() {
var mixInits = this.__proto__._mixInits;
if (mixInits !== undefined) {
for (var i = 0; i < mixInits.length; i++) {
mixInits[i].call(this);
}
}
};
//------------ testcode
var SpeakEnable = {
say:function(){
console.log(this.message);
},
init:function(){
console.log('say init called');
this.message="Saying Hello World Mixed in!";
this.object=[];
}
};
var WalkEnable = {
walk:function(){
console.log(this.walk_message);
},
init:function(){
console.log('walk init called');
this.walk_message="Walking step 1.2.3.";
}
};
var Person=function() {
Mixable.call(this);
};
inherits(Person, Mixable);
mixIn(Person,SpeakEnable);
mixIn(Person,WalkEnable);
var lulu=new Person();
lulu.say();
lulu.walk();
Given simple JS inheritance, what's the practical difference in the base function between these two examples? In other words, when should a person choose to define a function on "this" instead of on the prototype (or the other way around)?
For me the second example is easier to digest, but how much more is there to this?
function defined on this:
//base
var _base = function () {
this.baseFunction = function () {
console.log("Hello from base function");
}
};
//inherit from base
function _ctor() {
this.property1 = "my property value";
};
_ctor.prototype = new _base();
_ctor.prototype.constructor = _ctor;
//get an instance
var instance = new _ctor();
console.log(instance.baseFunction);
function defined on prototype:
//base
var _base = function () {};
_base.prototype.baseFunction = function () {
console.log("Hello from base function");
}
//inherit from base
function _ctor() {
this.property1 = "my property value";
};
_ctor.prototype = new _base();
_ctor.prototype.constructor = _ctor;
//get an instance
var instance = new _ctor();
console.log(instance.baseFunction);
Functions on the prototype are only created once and shared between each instance. Functions created in the constructor are created as new objects for each new object created with the constructor.
As a general rule functions should be on the prototype since they will generally not be modified for different objects of the same type, and this has a slight memory/performance benefit. Other properties like objects and arrays should be defined in the constructor, unless you want to create a shared, static property, in which case you should use the prototype.
Its easier to see the distinctions with normal objects or arrays rather than functions
function Foo(){
this.bar = [];
}
var fooObj1 = new Foo();
var fooObj2 = new Foo();
fooObj1.bar.push("x");
alert(fooObj2.bar) //[]
as opposed to:
function Foo(){
}
Foo.prototype.bar = []
var fooObj1 = new Foo();
var fooObj2 = new Foo();
fooObj1.bar.push("x");
alert(fooObj2.bar) //["x"]
Is it possible in javascript to have a variable that is not able to access out side the class's functions, but is able to be accessed by classes that inherit it? I.E:
class1 has protected var x = 4;
class2 inherits class1;
class2.prototype.getVar = function(){return /* parent, uber, super, whatever */ this.x;};
var cl2 = new class2();
console.log(cl2.x) // undefined
console.log(cl2.getVar()) // 4
No. Prototypal inheritance is limited to properties of objects.
Variables within the constructor are only available to other code in that variable scope.
You could probably come up with something like...
function cls1() {
var a = 'foo';
this.some_func = function() {
alert(a);
};
}
function cls2() {
cls1.apply(this, arguments);
var cls1_func = this.some_func;
var b = 'bar'
this.some_func = function() {
cls1_func.apply(this, arguments);
alert(b);
};
}
var x = new cls2;
x.some_func(); // alert "foo" alert "bar"
Or to make it more specific to your pseudo code...
function class1() {
var x = 4;
this.getVar = function() {
return x;
};
}
function class2() {
class1.apply(this, arguments);
var cls1_get_var = this.getVar;
this.getVar = function() {
return cls1_get_var.apply(this, arguments);
};
}
class2.prototype = Object.create( class1.prototype );
var cl2 = new class2;
console.log(cl2.x) // undefined
console.log(cl2.getVar()) // 4
I think you need to use a closure to achieve what your trying to do. Something like this:
Class1 = function() {
var x = 4;
return {
getVar: function() {
return x;
}
}
} ();// executes the function immediately and returns an
//an object with one method - getVar. Through closure this method
//still has access to the variable x
Class2 = function() { };// define a constructor function
Class2.prototype = Class1;//have it inherit from Class1
Cl2 = new Class2();//instantiate a new instance of Class2
console.log(Cl2.x);//this is undefined
console.log(Cl2.getVar());//this outputs 4
This is one of the neat things about javascript in that you can achieve the same things in javascript as you would in a class based language without all the extra key words. Douglas Crockford (always good to consult about javascript) explains prototypal inheritance here
Edit:
Just had a second look at your question.If you want newly created methods in your class to access the variable in the base class then you would have to call the getVar method within your own method.Like such:
Class2 = function() {
this.getVar2 = function() {
return this.getVar();
}
};
console.log(Cl2.getVar2()) //outputs 4