Javascript "return this" meet the "return"? - javascript

var Person = function(){};
function klass() {
initialize = function(name) {
// Protected variables
var _myProtectedMember = 'just a test';
this.getProtectedMember = function() {
return _myProtectedMember;
}
this.name = name;
return this;
};
say = function (message) {
return this.name + ': ' + message + this.getProtectedMember();
// how to use "return this" in here,in order to mark the code no error.
};
//console.log(this);
return {
constructor:klass,
initialize : initialize,
say: say
}
//return this;
}
Person.prototype = new klass();
//console.log(Person.prototype);
new Person().initialize("I :").say("you ").say(" & he");
how to use "return this" in "say",in order to mark the code no error.
i want to know that how to 'Chain call' in the function which has return alrealy?

You need return a class instance to chain call. I would suggest you create a base class for all your objects that is able to store the outputs of the class, and will return it in the "toString" or similar function, maybe "output".
Your code then becomes:
(new Person()).initialize("I :").say("you ").say(" & he").toString();

Only one object can be returned.
So you have two options.
One - Show the message inside the function ans return this
say = function (message) {
// show the message here e.g. using an alert
alert(this.name + ': ' + message + this.getProtectedMember());
// then return instance
return this;
};
Two - Return an object containing instance and message
say = function (message) {
message = this.name + ': ' + message + this.getProtectedMember();
return {message:message, instance:this};
};
and call it like
new Person().initialize("I :").say("you ").instance.say(" & he");

Related

How to chain functions into one sentence

So i have to write a program, which could chain function like this:
name("Adam").place("cinema").movie("xxx") expected output should be like this: Adam goes to Cinema to watch movie called xxx, what i have so far:
var test = function(name){
var self = {};
console.log(name)
function someFunc(where) {
console.log("goes to cinema" + where)
return self;
}
function someOtherFunc(what) {
console.log("to watch movie" + what)
return self;
}
self.someFunc = someFunc;
self.someOtherFunc = someOtherFunc;
return self;
}
console.log(test("Adam").someFunc("cinema").someOtherFunc("xxx"));
But it gives me strings in different lines, and i want to be it in one sentence, any help will be appreciated.
You can do something like this:
var test = function(message) {
this.someFunc = function(where) {
message += ` goes to ${where}`;
return this; // Allow chaining
}
this.someOtherFunc = function(what) {
message += ` to watch movie ${what}`;
return this; // Allow chaining
}
this.value = function() {
return message; //End chain
}
return this; // Start chain
}
console.log(test("Adam").someFunc("cinema").someOtherFunc("xxx").value());
//Adam goes to cinema to watch movie xxx
Edit:
Is it possible to get that result without .value() ?
You can override .toString().
Every object has a toString() method that is automatically called when
the object is to be represented as a text value or when an object is
referred to in a manner in which a string is expected. By default, the
toString() method is inherited by every object descended from Object.
If this method is not overridden in a custom object, toString()
returns "[object type]", where type is the object type.
This would require to convert the object to string though.
var test = function(message) {
this.someFunc = function(where) {
message += ` goes to ${where}`;
return this;
}
this.someOtherFunc = function(what) {
message += ` to watch movie ${what}`;
return this;
}
this.toString = function() {
return message;
}
return this;
}
console.log(`${ test("Adam").someFunc("cinema").someOtherFunc("xxx")}`);
Assuming you need your functions to execute in that order, and produce a sentence that doesn't vary in order, you could do the following:
var test = function(name){
var self = {
message: name,
};
function someFunc(where) {
self.message += " goes to cinema" + where;
return self;
}
function someOtherFunc(what) {
self.message += " to watch movie" + what;
console.log(self.message);
}
self.someFunc = someFunc;
self.someOtherFunc = someOtherFunc;
return self;
}
console.log(test("Adam").someFunc("cinema").someOtherFunc("xxx"));

Prototype/Subclasses in JavaScript

I'm having trouble identifying whether or not I'm using prototypes/subclasses properly in JavaScript.
Here's this constructor function I have:
function SentientBeing(homePlanet, language) {
this.homePlanet = homePlanet;
this.language = language;
}
And I am tasked with creating three 'subclasses' of SentientBeing. Would this be considered correct, or am I doing this improperly?
Thanks in advance.
// TODO: create three subclasses of SentientBeing, one for each
// species above (Klingon, Human, Romulan).
function Human() {
SentientBeing.call(this, homePlanet, language);
}
function Romulan() {
SentientBeing.call(this, homePlanet, language);
}
function Klingon() {
SentientBeing.call(this,homePlanet, language);
}
It is hard to find out, what you want to achive here, but I will quickly show how to use prototypes:
function SomeClass() {
this.a = 'a';
this.b = 'b';
}
// Objects Method
SomeClass.prototype.methodHello = function( name ) {
console.log('Hi, ' + name + '!');
};
// call this way:
var obj = new SomeClass();
obj.methodHello('Jose'); // => 'Hi, Jose!'
// Static Method
SomeClass.staticHello = function( name ) {
console.log('Hello, ' + name + '!');
};
// call this way:
SomeClass.staticHello('Herku'); // => 'Hello, Herku!'

Why toString is not a generic function in javascript

I was trying to do something like this.
var myFunc = function() {}
myFunc.prototype = new String();
myFunc.prototype.replace = function() {return 'hii, Mr '+ this.toString();}
var oVal = new myFunc('Jyotirmay');
oVal.replace();
o/p :: Uncaught TypeError: String.prototype.toString is not generic(…)
Why "function not generic" error comes actually in general?
As to be more clear, How can i pass my argument i.e Jyotirmay from inherited class to base class i.e string. So that i can get that value by calling any proper string function.
I don't want to get my passed value from my function by handling that variable in it.
I want that to be handled by parent class. You can say super() in other languages.
It is unclear what exactly you are trying to achieve from your question and comments, but perhaps this is all you are trying to do?
function myFunc(inputArg) {
this.inputArg = inputArg;
}
myFunc.prototype = {
replace: function () {
return 'hii, Mr ' + this.inputArg;
},
toString: function () {
return '' + this.inputArg;
}
};
myFunc.prototype.valueOf = myFunc.prototype.toString;
function log(inputArg) {
document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}
var oVal = new myFunc('Jyotirmay');
log(oVal);
log(oVal.replace());
<pre id="out"></pre>
As to Why is toString not generic, this is because not all objects can be represented as a string by the same conversion method.
Update based on your latest comment
Native objects are notoriously difficult, if not impossible, to subclass in Javascript. There are a few hacks that will allow you partial success, but I would not recommend them and good luck across different environments.
Two (but not the only) such hacks are:
Stealing from an iframe
function stealObject(objectName, myVariableName) {
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
iframe.src = 'javascript:parent.' + myVariableName + ' = ' + objectName;
document.body.appendChild(iframe);
document.body.removeChild(iframe);
return window[myVariableName];
}
function log(inputArg) {
document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}
try {
stealObject('String', 'MyString');
MyString.prototype.replace = function () {
return 'hii, Mr ' + this;
};
var oVal = new MyString('Jyotirmay');
log(oVal);
log(oVal.toUpperCase());
log(oVal.replace());
} catch (e) {
log(e);
}
<pre id="out"></pre>
Doesn't work in SO snippets because SecurityError: Sandbox access violation: but can see it on this jsFiddle. typeof oVal will return object and not string and oVal instanceof String will be false. oVal.constructor === String will return false.
Another hack
function MyString() {
this.str = '' + arguments[0];
};
with(MyString.prototype = new String()) {
toString = valueOf = function () {
return this.str;
};
}
MyString.prototype.replace = function () {
return 'hii, Mr ' + this;
};
function log(inputArg) {
document.getElementById('out').appendChild(document.createTextNode(inputArg + '\n'));
}
var oVal = new MyString('Jyotirmay');
log(oVal);
log(oVal.toUpperCase());
log(oVal.replace());
<pre id="out"></pre>
The magic length property is broken in this one and you would need to call oVal.toString().length instead. typeof oVal will return object and not string but oVal instanceof String will be true. oVal.constructor === String will return true.

Inheriting prototype using .call(this)

(function() {
LoggerBase.prototype.output = function(message) {
console.log('LoggerBase: ' + message);
};
function BookAppLogger() {
LoggerBase.call(this);
this.logBook = function(book) {
console.log('Book: ' + book.title);
}
}
BookAppLogger.prototype = Object.create(LoggerBase.prototype);
}());
In this code the BookAppLogger inherits the prototypes of the LoggerBase object, I think that is clear from the last statement. What I don't understand is the purpose of the LoggerBase.call(this) statement. What does this line do and why is it neccessary?
BookAppLogger.prototype = Object.create(LoggerBase.prototype);
will only add LoggerBase.prototype functions to BookAppLogger.prototype but you cannot inherit the functions/properties that are written inside LoggerBase function. For example if LoggerBase is something like
function LoggerBase () {
this.fname = "First";
this.lname = "Last";
this.fullname = function(){
return this.fname + " " + this.lname;
}
}
LoggerBase.prototype.somefunction = function(){}
If you do not write LoggerBase.call(this) inside BookAppLogger, then only only LoggerBase somefunction is inherited but not fname, lname, fullname
Its just calling the base class constructor
LoggerBase is a function object and the call method of a function can be used to call that function with a specific this value. Calling LoggerBase directly would result in this being the global object, which in a browser is the window object.
function LoggerBase() {
console.log(this);
}
function BookAppLogger() {
LoggerBase.call(this); // will print the book logger
LoggerBase(); // will print the global object
}
BookAppLogger.prototype = Object.create(LoggerBase.prototype);

Javascript OOP - declaring methods of an object

This is the most basic JS object example I can think of that illustrates my questions.
Question 1.
How can I reference functions within a class so that in other code I could call a method? This gives me an error.
var name1 = new Name();
name1.render();
Question 2.
What is the difference between declaring functions in-line like this vs. using var getByID = function() ...?
Example object:
function Name(user_id, container_id) {
this.userID = user_id;
this.containerID = container_id;
this.firstName = null;
this.lastName = null;
function getByID(userID) {
// An ajax call that takes a userID to get a name.
}
function setName() {
// An ajax call to get the name from db.
name_record = this.getByID(this.userID); ????? this returns an error that getByID is undefined.
this.firstName = name_record.firstName;
this.lastName = name_record.lastName;
}
function render() {
$(this.containerID).val(this.firstName + ' ' + this.lastName);
}
}
You can declare an object like you done in your second question, it's valid because a function is an object too. Or other ways like:
var Name = {
render: function() {
}
}
Name.render();
Or with prototype:
function Name() {
}
Name.prototype.render = function() {
}
// or
Name.prototype = {
getByID: function() {
},
setName: function() {
}
}
var n = new Name();
All these snipets are a valid object declaration.
Your second question may answer the first ones. When you declare a function like this:
function Name() {
function render() {
}
}
var n = new Name();
It is like render() be a private method. if you call outside the function name n.render(), you will see an error thrown because render is not recognized. But if you change to this...
function Name() {
this.render = function() {
}
}
... then n.render() will work like render() being a public method. See this and this for further information about public and private methods.
Now, the difference between declaring a function "in-line" or setting it to a variable is that with this:
function Name() {
}
You can do:
var n1 = Name();
var n2 = Name();
var nn = Name(); // and so on...
But with:
var n = function Name() {
}
Is that n() will work and Name() will not. Even var a = Name() will throw an exception.
Here's a good article about this subject that worth a read. I hope it can help.
Question 1:
A "Class" in Javascript is nothing more than an object. An object has properties which you can access. Those properties are either variables, functions, or other objects. By declaring your function like:
function render() {
$(this.containerID).val(this.firstName + ' ' + this.lastName);
}
You are declaring a function within the scope of function Name() but that function isn't a property of Name. It's just a private method. There are multiple ways you could make it a part of Name(), such as:
function Name(user_id, container_id) {
this.userID = user_id;
this.containerID = container_id;
this.firstName = null;
this.lastName = null;
this.render = function() {
console.log('hello world');
}
}
var name1 = new Name();
name1.render();
Question 2:
There is no difference. They are simply two different syntax's that achieve the same result. The second way (declaring a var and defining the function) immediately gives you a reference to the function, but that can be achieved just as well the first way.
Answer to your first question:
Functions getByID,setName and render are local to the constructor and cannot be called by class object. You have to use prototypal inheritance.
for eg.
function Name(user_id, container_id) {
this.userID = user_id;
this.containerID = container_id;
this.firstName = null;
this.lastName = null;
}
Name.prototype = {
getByID :function(userID) {
// An ajax call that takes a userID to get a name.
}
setName:function() {
// An ajax call to get the name from db.
name_record = this.getByID(this.userID);
this.firstName = name_record.firstName;
this.lastName = name_record.lastName;
}
render:function() {
$(this.containerID).val(this.firstName + ' ' + this.lastName);
}
};
Answer to your second question:
in case of
abc();//Error
function abc(){
}
this function is created at run time , so you can call it only after declaration
however, this
abc();
var abc = function(){
};
is created at parse time so you can call it before declaration.

Categories