Passing arguments to anonymous function of module - javascript

$(document).ready(function () {
var patient = (function (options) {
var age = options.age;
var name = options.name;
function getName() {
return this.name;
}
function setName(val) {
name = val;
}
function getAge() {
return this.age;
}
function setAge(val) {
age = val;
}
return {
getAge: getAge,
setAge: setAge,
getName: getName,
setName: setName
}
})();
});
I realize that I'm never passing any options in my example here.
If I try to do something like patient.setAge('100') and then console.log(patient.getAge()) I get an error saying cannot read property Age of undefined. The overarching theme that I'm trying to get at is within a module, how can I emulate consturctors to instantiate a new patient object while keeping all the OOP goodness of private variables and all that jazz.
I've seen some examples of constructors in a module pattern on here and I haven't understood them very well. Is it a good idea in general to have a constructor in a module? Is its main purpose similarity with class-based languages?

This is a constructor:
function Patient(options) {
options = options || {};
this.age = options.age;
this.name = options.name;
}
$(document).ready(function () {
var patient = new Patient();
});
You can put it inside a module if you want. What you shouldn’t do is provide getters and setters, especially ones that don’t do anything. If you’re exposing a variable through two properties to get and set it, it should just be one property.

Try this
function Patient (options) {
options = options || {};
var age = options.age;
var name = options.name;
function getName() {
return name;
}
function setName(val) {
name = val;
}
function getAge() {
return age;
}
function setAge(val) {
age = val;
}
return {
getAge: getAge,
setAge: setAge,
getName: getName,
setName: setName
}
}); // pass empty object
$(document).ready(function () {
var p1 = new Patient({});
var p2 = new Patient();
var p3 = new Patient({age:20});
var p4 = new Patient({name:"abcd"});
var p5 = new Patient({age:21, name:"abcd"});
});

Related

prototypal inheritance & how to do a super()

I'm trying to understand how to create inheritance. I think I have it (below), but the part I can't figure out is how to call the "baseclass" method (ie, doing a "super()"). How do I call the delegate's talk() method below?
(demo link: https://plnkr.co/edit/H76NFBiuWqgaZaUfR7H2?p=preview)
function Person(name) {
var api = {
name,
talk
}
return api;
function init(name) {
this.name = name;
}
function talk() {
return (`I am ${this.name}`)
}
}
function Student(name, major) {
var api = {
major: major,
talk
};
var o = $.extend({}, Person(name), api);
return o;
function changeMajor(newMajor) {
this.major = newMajor;
}
function talk() {
var str = ""
// var str = Person.prototype.talk.call(this)
str += ` and I study ${major}`;
return str;
}
}
var s = Student("Sue", "Economics")
console.log(s.talk())
You lose the reference to the "super" talk method from the Person object when using extend:
var o = $.extend({}, Person(name), api);
Although that parent object is created, it is not stored. Only the modified version of it (with api.talk overriding its talk method) is available in o.
So... you need to keep a reference to the original talk method:
var proto = Person(name);
var o = $.extend({}, proto, api);
And then reference it:
var str = proto.talk.call(this);
Note that since ES6 you can use the native Object.assign which has similar functionality as $.extend.
function Person(name) {
var api = {
name,
talk
};
return api;
function init(name) {
this.name = name;
}
function talk() {
return (`I am ${this.name}`)
}
}
function Student(name, major) {
var api = {
major: major,
talk
};
var proto = Person(name);
var o = Object.assign({}, proto, api);
return o;
function changeMajor(newMajor) {
this.major = newMajor;
}
function talk() {
var str = proto.talk.call(this);
str += ` and I study ${major}`;
return str;
}
}
var s = Student("Sue", "Economics");
console.log(s.talk());
You could reveal the init method in your api objects but mark it as I'm not part of the published API, I only happen to be public here so to say. Leveraging a naming convention you could do something like this:
function Person(name) {
var api = {
"__init__": function () {
// I'm part of the API but please treat me as private
},
talk: function () {
// Do sth.
}
};
return api;
}
function Student(name, major) {
var personApi = Person(name);
var api = {
"__init__": function () {
// I'm also part of the API but treat me as private
personApi.__init__.call(this, name)
},
talk: function () {
return personApi.talk.call(this);
}
};
return api;
}
But then you'd have to marshall around the this and you have to think about not accidentally overriding you __init__ so you customize your own $.extend() function... the rabbit hole goes deep :-). Things like this have been done by some frameworks in the past but I personally wouldn't recommend rolling your own object system - it's fun as a toy but in this day and age there are better options.
The old ES5 way to do this is via constructor functions:
// Base `class` is just a constructor function
function Person(name) {
this.name = name;
}
Person.prototype.talk = function () {
// Do sth.
};
function Student(name, major) {
Person.call(this, name); // emulating super(name)
}
Student.prototype = Object.create(Person.prototype);
Student.prototype.changeMajor = function () {
// Do sth.
};
// later
var homer = new Student("Homer Simpson", "Donuts");
In modern browsers or with the help of a transpiler say babeljs or TypeScript you can do this - which is probably what you wanted in the first place:
class Person {
constructor(name) {
this.name = name;
}
talk() {
// Do sth.
}
}
class Student extends Person {
constructor(name, major) {
super(name); // proper super(name);
this.major = major; // Or anything you want to do
}
changeMajor() {
// Do sth.
super.talk();
}
}
// later
let homer = new Student("Homer Simpson", "Donuts");

Getters and Setters in a function (javascript)

When using get in an object like this, get works:
var people = {
name: "Alex",
get sayHi() {
return `Hi, ${this.name}!`
}
};
var person = people;
document.write(person.sayHi);
But with a function I get an error. How to use Getters and Setters in a function like this?
function People2() {
this.name = "Mike";
get sayHi() {
return `Hi, ${this.name}!`;
}
};
var user = new People2();
document.write(user.sayHi);
You can use the actual get and set keywords only in classes (ES2015) and object literals.
ECMAScript 5
In ES5, your would typically use Object.defineProperty to implement what you're trying to achieve:
function People2() {
this.name = "Mike";
}
Object.defineProperty(People2.prototype, "sayHi", {
get: function() {
return "Hi, " + this.name + "!";
}
});
ECMAScript 2015
In ES2015, you could also use classes to achieve the desired behavior:
class People2 {
constructor() {
this.name = "Mike";
}
get sayHi() {
return `Hi, ${this.name}!`;
}
}
You can try this
<script>
function People2(name) {
this.name = name;
};
People2.prototype = {
get sayHi() {
return `Hi, ${this.name}!`;}
};
var user = new People2('Alex');
document.write(user.sayHi);
</script>
or this one...
<script>
function people(name) {
this.name = name;
};
Object.defineProperty(people.prototype, 'sayHi', {
get: function() { return `Hi, ${this.name}!`; }
});
var person = new people('Alex');
document.write(person.sayHi);
</script>
For the case you want to define a property like as name for a function with more control, we can use Object.defineProperty on function itself as following:
function people(name) {
//this.name = name; //this can be modified freely by caller code! we don't have any control
var _name = name; //use a private var to store input `name`
Object.defineProperty(this, 'name', {
get: function() { return _name; }, //we can also use `return name;` if we don't use `name` input param for other purposes in our code
writable: false, //if we need it to be read-only
//... other configs
});
};
var person = new people('Alex');
console.log(person.name); //writes Alex
For example, use this:
function People2() {
this.name = "Mike";
this.__defineGetter__("sayHi", function() {
return `Hi, ${this.name}!`;
});
};

How to use object oriented without using keyword ('new')

What am I trying to do is as following:
var Person = function(name) {
this.name = name;
}
Person.prototype.getName = function () {
return this.name;
}
// This will return error;
console.log(Person('John').getName());
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
Am I misunderstanding something?
// This will return error;
console.log(Person('John').getName());
it returns an error bcoz Person() by default returns undefined ,but if you use new it will return the newly created object.
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());
this works bcoz a new object with __proto__ set to Person.prototype is returned and since there is a getName() on it , it works as expected.
you may use scope safe constructor for your constructor to work without explicit new.
function Person(name) {
if(this instanceof Person) {
this.name = name;
} else {
return new Person(name);
}
}
http://www.mikepackdev.com/blog_posts/9-new-scope-safe-constructors-in-oo-javascript
If you don't want to have the new keyword all over your code (and I can't think of a good reason to want that, you would be basically hiding an important information), you could just do something like:
var pPerson = function(name) {
this.name = name;
};
pPerson.prototype.getName = function () {
return this.name;
};
var Person = function (name) {
return new pPerson(name);
};
You can use Object.create() if you don't want to use the new keyword. Here's an example from MDN:
// Animal properties and method encapsulation
var Animal = {
type: "Invertebrates", // Default value of properties
displayType : function(){ // Method which will display type of Animal
console.log(this.type);
}
}
// Create new animal type called animal1
var animal1 = Object.create(Animal);
animal1.displayType(); // Output:Invertebrates
// Create new animal type called Fishes
var fish = Object.create(Animal);
fish.type = "Fishes";
fish.displayType(); // Output:Fishes
If you really really hate your self, you can do this
var Person = function(name) {
var This = {};
This.name = name;
//See note
Object.setPrototypeOf(This, arguments.callee.prototype);
return This;
}
Person.prototype.getName = function () {
return this.name;
}
var p = Person('John');
console.log(p.getName());
Note
You absolutely have to read about this.
You can try creating prototype functions as a part of parent function itself.
var Person = function(name) {
this.name = name;
this.get_name = function() {
return this.name;
}
return this;
}
Person.prototype.getName = function() {
return this.name;
}
// This will return error;
console.log(Person('John').get_name());
// While this won't.
var p1 = new Person('john');
console.log(p1.getName());

Prototypes issue in javascript

i am just starting learn a prototypes in javascript an i can't understand what a problem is in my code. I'm sorry, my question may seem silly
i got an error like this :
Uncaught TypeError: undefined is not a function
why is undefined? I inherited a function of the user.
can't understand it :(
var user = {
sayName: function() {
console.log(this.name)
}
};
user.name = "viktor";
user.sayName();
var user2 = {};
user2.prototype = user;
user2.name = "segey";
user2.sayName();
All you need to set up the prototype chain with plain objects is:
var user2 = Object.create(user); // set `user` as prototype of `user2`
user2.name = "segey";
user2.sayName();
For you question correct solution will:
function User() {
this.name = 'Viktor';
return this;
}
User.prototype = Object.create({
sayName: function() {
return this.name;
}
});
function User2() {}
User2.prototype = Object.create(User.prototype);
var user = new User();
user.sayName(); // 'Viktor'
user2 = new User2();
user2.name = 'Bogdan';
user2.sayName(); // 'Bogdan'
And detailed explanation with example.
Let say we have some basic class Animal. Our Animal have age and name.
function Animal() {
this.age = 5;
this.name = "Stuffy";
return this;
}
Animal.prototype = Object.create({
getAge: function() {
return this.age;
},
getName: function() {
return this.name;
}
});
And when I spent some time with architecture I understand that I also need SubClass of Animal. For example, let it will be Dog class with new property and functions. And also Dog must extend functions and properties from Animal class.
function Dog() {
Animal.apply(this, arguments); // Call parent constructor
this.wantsEat = true; // Add new properties
return this;
}
Dog.prototype = Object.create(Animal.prototype); // Create object with Animal prototype
Object.extend(Dog.prototype, { // Any extend() function, wish you want
constructor: Dog, // Restore constructor for Dog class
eat: function() {
this.wantsEat = false;
return this;
}
});
Or you can use Object.defineProperties() and extend in this way:
Dog.prototype = Object.create(Animal.prototype, {
constructor: {
value: Dog
},
eat: {
value: function() {
this.wantsEat = false;
return this;
}
}
});

JavaScript - Invoking Methods that Reference this

Not sure what I'm doing wrong here, I just want to be able to have functions of an object reference the object scope
myscipt.js
function MyFoo () {
this.name = 'myname';
}
function MyBar () {
this.myFoo = new MyFoo();
function setMyFoosName( name ) {
this.myFoo.name = name;
}
}
somepage.html
<scipt>
$('document').ready( function() {
$.myBar = new MyBar();
}
...
some action
...
$.myBar.setMyFoosName( 'new name' );
</script>
this throws an exception:
this.myFoo.name = name; this.myFoo is not defined
Lekensteyn and Ken got it half right each.
You have to put "this" in a variable, like Lekensteyn did, in order to be able to reference it inside of the nested function as well.
You have to make setMyFoosName accessible outside of the scope of MyBar, by assigning it to a property of "this", like Ken did.
This is how I would do it:
function MyFoo () {
this.name = 'myname';
}
function MyBar () {
var that = this;
this.myFoo = new MyFoo();
this.setMyFoosName = function( name ) {
that.myFoo.name = name;
}
}
Cant you do an instance static method with the JSON Data type?
var MyFoo = {
_instance : null,
Instance : function(){
if(this._instance == null)
{
this._instance = new this.Object();
}
return this._instance;
},
Object : function()
{
this.name = 'not robert';
}
}
function MyBar (){
this.setMyFoosName = function ( name ) {
MyFoo.Instance().name = name;
}
}
Bar = new MyBar()
Bar.setMyFoosName('Robert');
Gives it more of a global scope and so on, aslong as MyFoo is in the global scope.
Example here.
this referes to the scope of setMyFoosName. You should put this in a variable, and refer to that variable:
function MyFoo () {
this.name = 'myname';
}
function MyBar () {
var that = this;
this.myFoo = new MyFoo();
this.setMyFoosName = function( name ) {
that.myFoo.name = name;
}
}
Try to avoid exporting variables which should remain private:
function myFoo () {
this.name = 'myname';
}
function MyBar () {
/* myFoo is private */
var myFoo = new MyFoo();
this.setMyFoosName = function( name ) {
myFoo.name = name;
}
}
In this way, you cannot break your function with:
$.myBar = new MyBar();
$.myBar.myFoo = new EvilObject();
$.myBar.setMyFoosName();
Of course, this depends on your use, whether myFoo should be overridable or not.

Categories