Currying function constructor - javascript

I'd like to know if it is possible to achieve this in javascript:
function Hello() { }
Hello.prototype.echo = function echo() {
return 'Hello ' + this.firstname + '!';
};
// execute the curryed new function
console.log(new Hello()('firstname').echo())
Is it possible to curry var o = new Class()(param1)(param2)(...) ?
Thank you in advance for your help.

Using the answer of georg with an array of the properties and a counter for assigning an arbitrary count of properties.
function Hello() {
var args = ['firstname', 'lastname'],
counter = 0,
self = function (val) {
self[args[counter++]] = val;
return self;
};
Object.setPrototypeOf(self, Hello.prototype);
return self;
}
Hello.prototype.echo = function echo() {
return 'Hello ' + this.firstname + ' ' + (this.lastname || '') + '!';
};
console.log(new Hello()('Bob').echo());
console.log(new Hello()('Marie')('Curie').echo());

For example:
function Hello() {
let self = function (key, val) {
self[key] = val;
return self;
};
Object.setPrototypeOf(self, Hello.prototype);
return self;
}
Hello.prototype.echo = function echo() {
return 'Hello ' + this.firstname + this.punct;
};
console.log(new Hello()('firstname', 'Bob')('punct', '...').echo())

In your code new Hello('Bob') does not return a function, but an object that has an .echo() method.
function Hello(firstname) {} is a contructor function that returns an object when instantiated with new.
// constructor function expecting 1 argument
function Hello(firstname) {
this.firstname = firstname;
}
// attach a method to the constructor prototype
Hello.prototype.echo = function() {
return 'Hello ' + this.firstname + '!'; // the method can use the contructor's properties
};
// new Hello('Bob') returns the object, and you can call the .echo() method of that object
console.log(new Hello('Bob').echo())

Related

Create dynamic prototype like jquery function chain

I try to create a dynamic prototype like jQuery and able to function chain, but I got error without use new and inside of function, return this object correct?
(function() {
var peopleDynamicProto = function(name, age, state) {
this.name = name;
this.age = age;
this.state = state;
if (typeof this.printPerson !== 'function') {
peopleDynamicProto.prototype.printPerson = function() {
console.log(this.name + ',' + this.age + ',' + this.state);
return this;
};
}
if (!this.hasOwnProperty('gender')) {
peopleDynamicProto.prototype.gender = 'male';
return this;
}
}
window.peopleDynamicProto = peopleDynamicProto;
return peopleDynamicProto;
})();
//var person1 = new peopleDynamicProto('john', 23,'CA');
//person1.printPerson();
peopleDynamicProto('john', 23, 'CA').printPerson(); //got error
Anyone know where is the problem?
You have to use "new" if you want to create a new object based off a prototype.
I am not sure what you are trying to do exactly, and why you are trying to create the prototype dynamically. I'm not going to say 100% sure, but I don't think jQuery does that (plus it looks like a very bad practice).
If you're trying to do something like jQuery, where your class is chainable and can be chained as (new peopleDynamicProto(...)).print() or peopleDynamicProto(...).print(), then you can do something like this:
function peopleDynamicProto(name) {
if (this instanceof peopleDynamicProto) {
/* initialize attributes here */
this.name = name;
} else {
return new peopleDynamicProto(name);
}
}
peopleDynamicProto.prototype.printPerson = function() {
console.log( this.name );
return this;
}
Now you should be able call it in both ways:
peopleDynamicProto('john').printPerson();
(new peopleDynamicProto('john')).printPerson();
If you don't care about supporting both ways, then you can just return an object, e.g.:
function peopleDynamicProto(name) {
return {
name: name,
printPerson = function() {
console.log( this.name );
return this;
}
};
}
peopleDynamicProto('John').printPerson();
(There are other ways of doing that)
I think the reason why you are getting such an error is because what you are returning here is a function not an object but you are trying to access a property of an object.
For eg,
If you write as:
**
var myFun = function(){
this.message = "TEST";
}
**
you cannot access myFUN.message because here myFun is a function not an object of this function constructor.
To access its property, you need to do something like
(new myFun()).message;
Similarly in you case what you return is "peopleDynamicProto" which is a function only, not an object of this function constructor.
To access method printPerson (which is a member), you need to create an instance of peopleDynamicProto and access its member
I guess you missed the new operator- see this for reference
The new operator creates an instance of a user-defined object type or
of one of the built-in object types that has a constructor function.
See demo below:
(function() {
var peopleDynamicProto = function(name, age, state) {
this.name = name;
this.age = age;
this.state = state;
if (typeof this.printPerson !== 'function') {
peopleDynamicProto.prototype.printPerson = function() {
console.log(this.name + ',' + this.age + ',' + this.state);
return this;
};
}
if (!this.hasOwnProperty('gender')) {
peopleDynamicProto.prototype.gender = 'male';
return this;
}
}
window.peopleDynamicProto = peopleDynamicProto;
return peopleDynamicProto;
})();
var person1 = new peopleDynamicProto('john', 23,'CA');
person1.printPerson();
new peopleDynamicProto('john', 23, 'CA').printPerson(); //got error
you cant create prototype inside contructor. see this explanation
defining-prototype-methods-inside-the-constructor
use this keyword instead of prototype:
(function(){
var peopleDynamicProto = function(name, age, state){
this.name = name;
this.age = age;
this.state = state;
this.printPerson = function(){
console.log( this.name + ',' + this.age + ',' + this.state );
return this;
}
if( !this.hasOwnProperty('gender') ){
peopleDynamicProto.prototype.gender = 'male';
return this;
}
}
window.peopleDynamicProto = peopleDynamicProto;
return peopleDynamicProto;
})();
peopleDynamicProto('john', 23,'CA').printPerson();
or use prototype outside constructor(this is better since function object not recreated each time object created)
(function(){
var peopleDynamicProto = function(name, age, state){
this.name = name;
this.age = age;
this.state = state;
if( !this.hasOwnProperty('gender') ){
peopleDynamicProto.prototype.gender = 'male';
return this;
}
}
if( typeof this.printPerson !== 'function' ){
peopleDynamicProto.prototype.printPerson = function(){
console.log( this.name + ',' + this.age + ',' + this.state );
return this;
};
}
window.peopleDynamicProto = peopleDynamicProto;
return peopleDynamicProto;
})();

Javascript - Scope and This

I have some code below. the problem I don't understand is why I don't have to refer to 'children' object via this.children but then accessing the firstname or surname, i have to use this.firstname....
Please help me understand why.
function User(first, sur) {
var firstName;
var surName;
var age;
var children = [];
this.firstName = first;
this.surName = sur;
this.getDisplayName = function() {
return this.firstName + ' ' + this.surName;
};
this.getTotalLength = function() {
return (this.firstName.length + this.surName.length);
};
this.displayFullName = function() {
return (this.firstName + ' ' + this.surName);
};
this.changeMaidenname = function(newSurname) {
if (newSurname)
{
this.surName = newSurname;
}
};
this.addChild = function(childUser) {
children.push(childUser);
};
this.numberOfChildren = function() {
return children.length;
};
this.killChild = function(childUser) {
children.forEach(function(item,index)
{
if (item.firstName === childUser.firstName && item.surName === childUser.surName)
{
children.splice(index, 1);
}
}
)
};
};
module.exports.User = User
In js,this keyword is used to create public variables whereas the var limits the scope of that variable to that particular function. :).You cant even access children object unless it is defined this.children=[]

Issue While Prototyping In javascript

var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
var Greeting = (function(){
Greeting.prototype = new Greeter();
Greeting.prototype.constructor = Greeter;
function Greeting(greeting){
}
return Greeting;
})();
var greeting = new Greeting("World");
alert(greeting.greet());
I'm trying to manipulate inheritance using javascript prototyping. I have a class structure like above. But when I call the greet method it display some thing like the below image shows. Can anybody guid me on this ?
You are never invoking the "constructor" function Greeter when you are creating the Greeting object. So the this.greeting = message; line never runs, that is why it is undefined.
You have to either insert that line manually:
function Greeting(greeting){
this.greeting = greeting;
}
or invoke the parent constructor:
function Greeting(greeting){
Greeter.call(this, greeting);
}
In your "greet" method of your Greeter you call this.greeting. However, in your Greeting object you haven't defined a "greeting" method...
You call greet method on Greeting context which don't have greeting property.
And there is no reason to wrap code in IIEF in your case, because there is no private vars, so (it works):
var Greeter = function (message) {
this.greeting = message;
};
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
var Greeting = function (greeting){
Greeter.call(this, greeting)
}
Greeting.prototype = new Greeter();
var greeting = new Greeting("World");
alert(greeting.greet());
When you call greeting.greet(), this.greeting is undefined, thus the problem.
Explanation:
Try this code:
var Greeter = (function () {
function Greeter(message) {
this.greeting = message;
}
Greeter.prototype.greet = function () {
return "Hello, " + this.greeting;
};
return Greeter;
})();
console.log('Log 1: ' + Greeter);
var Greeting = (function(){
console.log('Log 2: ' + Greeting);
Greeting.prototype = new Greeter();
console.log('Log 3: ' + Greeting);
Greeting.prototype.constructor = Greeter;
console.log('Log 4: ' + Greeting);
function Greeting(greeting){
}
console.log('Log 5: ' + Greeting);
return Greeting;
})();
console.log('Log 6: '+Greeting);
var greeting = new Greeting("World");
alert(greeting.greet());
You will see that Greeting is just an empty function, but with Greeter as the prototype. So, new Greeting('World') creates the following function:
function Greeting(greeting){
}
with a prototype containing greeting (undefined), constructor (a function), and greet (a function). Greeting.prototype.greet, in turn, has this definition:
Greeting.prototype.greet = function () {
return "Hello, " + this.greeting;
};
But this.greeting is undefined in this context, because this refers to Greeting.prototype.greet, not Greeter. Thus, these lines:
var greeting = new Greeting("World");
alert(greeting.greet());
fail, because greeting.greet() returns Hello, concatenated with an undefined value.
change the Greeting class like this:
var Greeting = (function(){
function Greeting(greeting){
Greeter.apply(this, arguments);
}
Greeting.prototype = new Greeter();
Greeting.prototype.constructor = Greeter;
Greeting.superClass = Greeter;
return Greeting;
})();
or if you want to create a general solution for all of your inheritance model, do this:
var Greeting = (function(){
var Greeting = function $SubClass(greeting){
$SubClass.prototype.constructor.apply(this, arguments);
}
Greeting.prototype = new Greeter();
Greeting.prototype.constructor = Greeter;
return Greeting;
})();
The important point in this part:
var Greeting = function $SubClass(greeting){};
is when you directly assign the function to a variable, you would have access to your function based on its label ($SubClass) only in the function context.

what is wrong with this piece of code of javascript inheritance?

function condition(){
this.expression = "";
this.toString = function(){
return this.expression;
}
};
function and(first, second){
this.expression = first + " and " + second;
}
function nop(){};
nop.prototype = condition.prototype;
and.prototype = new nop();
var a =new and(1,2);
console.log(a.toString());
it is expected to see "1 and 2" as output but this is what happened:
"[object Object]"
You are transfering the prototype of condition to nop's prototype. The problem is that your condition.toString is not declared in the prototype... Here:
function condition(){
this.expression = "";
};
condition.prototype.toString = function(){
return this.expression;
}
function and(first, second){
this.expression = first + " and " + second;
}
function nop(){};
nop.prototype = condition.prototype;
and.prototype = new nop();
var a =new and(1,2);
console.log(a.toString());
OR
function condition(){
this.expression = "";
this.toString = function(){
return this.expression;
}
};
function and(first, second){
this.expression = first + " and " + second;
}
function nop(){};
nop = condition;
and.prototype = new nop();
var a =new and(1,2);
console.log(a.toString());
you aren't overriding the toString method, because the constructer of condition is never called! try doing this;
condition.prototype.toString=function(){
return this.expression;
}
try passing strings into your and function, as at the moment you are trying to concatenate integers to a string var a =new and("1","2");
it should be like this
function condition(){
this.expression = "";
};
condition.prototype.toString = function(){
return this.expression;
}
Ok, so the problem here is you are mixing two inheritance patterns (http://davidshariff.com/blog/javascript-inheritance-patterns/) the pseudo-classical with the functional patterns.
You can create an object by adding methods on the constructor function:
function MyClass() {
var privateProperty = 1;
this.publicProperty = 2;
function pivateMethod() {
// some code ...
}
this.publicMethod = function() {
// some code ...
};
}
// inheritance
function SubClass() {
MyClass.call(this);
this.newMethod = function() { };
}
Here when you create a instance of this class you are creating every method again.
Then you have the prototype pattern:
function MyClass() {
this._protectedProperty = 1;
this.publicProperty = 2;
}
MyClass.prototype._protectedMethod = function() {
// some code ...
};
MyClass.prototype.publicMethod = function() {
// some code ...
};
// inheritance
function SubClass() {
MyClass.call(this);
}
SubClass.prototype = new MyClass();
SubClass.prototype.newMethod = function() { };
// OR
function SubClass() {
MyClass.call(this);
}
function dummy() { }
dummy.prototype = MyClass.prototype;
SubClass.prototype = new dummy();
SubClass.prototype.newMethod = function() { };
Yhen you must choose one of those two patterns, not both·
I've fixed your code on this fiddle: http://jsfiddle.net/dz6Ch/

return statement in a function as class

I am confused about the return statement in a function that serves as a class. See the example code below:
<html>
<body>
<script type="text/javascript">
function test() {
this.abc = 'def';
return 3;
}
var mytest = new test();
document.write(mytest + ', ' + (typeof mytest) + ', ' + mytest.abc);
</script>
</body>
</html>
The code out put: [object Object], object, def.
Here is my question. I wrote 'return 3' in the test() function. Is this statement ignored when 'new test()' is called?
Thanks.
When you call a function with new, you're invoking it as a constructor which automatically returns the new object it constructs.
Your return 3; statement is ignored. What is returned is effectively:
{ abc:'def' }
...with an implicit reference to a prototype object, which in your example doesn't have any enumerable properties because you haven't given it any.
If you did:
mytest instanceof test;
...it would evaluate to true.
If you did:
function test() {
this.abc = 'def';
}
test.prototype.ghi = 'jkl';
var mytest = new test();
...you could then do:
mytest.ghi;
...which would give you the value 'jkl'.
When you use the new operator, you're using the function as a constructor, in that case for the return value:
if it's not an object, it is ignored (like in your example)
if it is an object, the object returned becomes the result of the whole new expression
So if you were to write
Test = function(arg) {
this.a = 1;
return arg;
}
var t1 = new Test(10);
var t2 = new Test({b: 2});
console.log(t1, t2)
// output:
// Test {a:1} Object {b: 2}
The new operator instantiates and returns an object. Here are some examples with its output:
(...)
var mytest = test();
document.write(mytest + ', ' + (typeof mytest) + ', ' + mytest.abc);
// 3, number, undefined
Or:
function test() {
this.abc = 'def';
this.getvalue = function(){
return 3;
}
}
var mytest = new test();
document.write(mytest.getvalue() + ', ' + (typeof mytest) + ', ' + mytest.abc);
// 3, object, def
you can do
function test(){
this.abc = "def"
this.ghi = function(){
return "jkl"
}
}
or
function test(){
this.Class = function(){
this.def = "abc"
this.jkl = "ghi"
}
this.abc = "def"
this.ghi = function(){
return "jkl"
}
}

Categories

Resources