How to get parent object when context is function? - javascript

I would like to write curring function for object methods. I want to make this possible:
Function.prototype.curry = function (){
var originalFunction = this;
var args = ...; // here goes logic embracing arguments
var bind = ???; //how to get reference to someObject ???
return function(){
return originalFunction.apply(bind, args);
}
}
var someObject = {
doSomething : function (param1, param2, param3){
//do something with params
return param1 + ' ' + param2 + ' ' + param3;
}
}
someObject.doSomethingCurried = someObject.doSomething.curry('param1 value', 'param2 value');
//I want to be able to do:
someObject.doSomethingCurried('param3 value')'

There are some tricks, but in fact you should just pass context as a first argument, like native bind.

// Code goes here
Function.prototype.curry = function (context,arg){
var originalFunction = this;
var args = Array.prototype.slice.call(arguments,1) ; // here goes logic embracing arguments
var bind = context; //how to get reference to someObject ???
return function(){
return originalFunction.apply(bind, args.concat(Array.prototype.slice.call(arguments)));
}
}
var someObject = {
myObj:"Myobj",
doSomething : function (param1, param2, param3){
console.log(this);
//do something with params
return param1 + ' ' + param2 + ' ' + param3;
}
}
someObject.doSomethingCurried = someObject.doSomething.curry(someObject,'param1 value', 'param2 value');
//I want to be able to do:
console.log(someObject.doSomethingCurried('param3 value'));

Related

How to override a function in a Javascript class, and call the base function

Is it possible to override a function in a Javascript class, and call it's base implementation? I've achieved this by using prototypes, but I'm trying to preserve privacy for some of the data.
This is what I have so far, and it doesn't work. I can see why it doesn't work, but I can't see a way to resolve it. I'm beginning to wonder if this is not possible in javascript (without jumping through a lot of hoops).
Also, I need to support IE11, so can't use ES6.
var NoProto = NoProto || {};
NoProto.Shape = (function(){
var thing = function(name){
var privateData = 'this is a ' + name;
var self = this;
this.base = function(){
return self;
};
this.doStuff = function(){
return privateData;
};
};
return thing;
})();
NoProto.Square = (function(){
var thing = function(colour){
NoProto.Shape.call(this, "square");
this.doStuff = function(){
// this fails (stack overflow)
// ------> how to call the "base" function: doStuff, and preserve the private data?
var val = this.base().doStuff();
return val + ', which is '+ colour;
};
};
thing.prototype = Object.create(NoProto.Shape.prototype);
return thing;
})();
Usage:
var noProtoSqr = new NoProto.Square('blue');
try {
alert(noProtoSqr.doStuff()); // ---> Stack Overflow!
} catch (e){
console.error('There was an error: ' + e);
}
For reference, this is how I got it working with prototypes:
var Proto = Proto || {};
Proto.Shape = (function(){
var thing = function(name){
this._pseudoPrivateData = 'this is a ' + name;
};
thing.prototype._pseudoPrivateData = '';
thing.prototype.doStuff = function(){
return this._pseudoPrivateData;
};
return thing;
})();
Proto.Square = (function(){
var thing = function(colour){
Proto.Shape.call(this, "square");
this._colour = colour;
};
thing.prototype = Object.create(Proto.Shape.prototype);
thing.prototype._colour = '';
thing.prototype.doStuff = function(){
var val = Proto.Shape.prototype.doStuff.call(this);
return val + ', which is '+ this._colour;
};
return thing;
})();
Usage:
var protoSqr = new Proto.Square('blue');
try {
alert(protoSqr.doStuff()); // --> "this is a square, which is blue"
} catch (e){
console.error('There was an error: ' + e);
}
When you use
NoProto.Shape.call(this, "square")
this assigns the Shape's doStuff to the current instantiation, if that's what you want. So, now this.doStuff will reference the original doStuff function from NoProto.shape. If you want to overwrite the doStuff function on the current instantiation while being able to call the original doStuff, save a reference to the old doStuff before assigning to this.doStuff:
var thing = function(colour){
NoProto.Shape.call(this, "square");
const oldDoStuff = this.doStuff;
this.doStuff = function(){
var val = oldDoStuff();
return val + ', which is '+ colour;
};
};
Live snippet:
var NoProto = NoProto || {};
NoProto.Shape = (function(){
var thing = function(name){
var privateData = 'this is a ' + name;
var self = this;
this.base = function(){
return self;
};
this.doStuff = function(){
return privateData;
};
};
return thing;
})();
NoProto.Square = (function(){
var thing = function(colour){
NoProto.Shape.call(this, "square");
const oldDoStuff = this.doStuff;
this.doStuff = function(){
var val = oldDoStuff();
return val + ', which is '+ colour;
};
};
thing.prototype = Object.create(NoProto.Shape.prototype);
return thing;
})();
var noProtoSqr = new NoProto.Square('blue');
try {
console.log(noProtoSqr.doStuff()); // ---> Stack Overflow!
} catch (e){
console.error('There was an error: ' + e);
}

Currying function constructor

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())

calling a function from an object in javascript

I need more clarification for this problem.I have an object and it has two functions as like this.
<script type="text/javascript">
obj =
{
f1 : function ()
{
var k = this. f2(param1 , param2 , param3);// I don't know whether it is correct
},
f2 : function (par1 , par2 , par3)
{
return param1 + param2 + param3;
}
}
</script>
How can I call function f2 from f1? Can I declare f1 in f2? If yes, how is it? Which is the best method?
Not to replace the above answers, but to provide an alternative: when I write definitions of objects that have methods I prefer to use function constructor so that I can hide "private" closure variables and have some resemblance to OOP.
var myClass = function() {
/******** PRIVATE **********/
var _s = "foo"; // Private member
var _f = function() {}; // Private method
/******** PUBLIC **********/
this.s = "bar"; // Public member
this.f1 = function() { // Public method
console.log(_s + " " + this.s); // Concat private and public
}
this.f2 = function() {
this.f1();
}
}
var myObject = new myClass();
myObject.f2(); // prints "foo bar"
You can use it by the code you have given,but be care of the scope.
Please consider the output of following two part of code.
obj =
{
f1 : function () {
var k = this. f2(1 , 2 , 3);
},
f2 : function (par1 , par2 , par3){
console.log(this);
return par1 + par2 + par3;
}
}
obj.f1();
and
obj =
{
f1 : function () {
var k = this. f2(1 , 2 , 3);
},
f2 : function (par1 , par2 , par3){
console.log(this);
return par1 + par2 + par3;
}
}
function MyClass () {
return this;
}
MyClass.prototype = obj;
var tmp = new MyClass();
tmp.f1();
You also can declare f1 in f2,but if you want to use f1 at the other place,you must write f1 agian.
To share this, the functions would be better to be added to obj.prototype.
obj = {};
obj.prototype = {
f1: function(){
},
f2: function(params){
}
};
Something like this may give you a better idea. I have tested it it runs fine.
obj =
{
f1 : function ()
{
console.log("in F1");
obj.f2();
},
f2 : function ()
{
console.log("in F2");
}
};
console.log(obj.f1());
Here is the fiddle to it => http://jsfiddle.net/CJ7Uz/
calling f2 like this:
<pre>
<script type="text/javascript">
obj =
{
f1 : function ()
{
var k = this.f2(1 , 2 , 3);// it is correct :)
alert(k);
},
f2 : function (par1 , par2 , par3)
{
return par1 + par2 + par3;
}
}
obj.f1();
</script>
</pre>
and check the link below to find the answer of your second question
http://www.phpied.com/3-ways-to-define-a-javascript-class/
Going off of Barmar's suggestion, here's what the code would look like:
<script type="text/javascript">
var obj = {
f1: function () {
var k = this.f2(param1 , param2 , param3);
},
f2: function (par1 , par2 , par3) {
return par1 + par2 + par3;
}
};
</script>
Also, bad idea to stick a space after this. in your code. :)
your problem is resolved:
Click
obj =
{
f1 : function ()
{
alert('f1');
var param1=param2=param3=0;
var k = this.f2(param1 , param2 , param3);
},
f2 : function (param1 , param2 , param3)
{
alert('f2')
return param1 + param2 + param3;
}
}
For demo visit this link DEMO

Pass arguments to anonymous functions using ()() in JavaScript

I'm trying to add a hook to each of the functions in the object, follows are my code and it's runs good.
function foo(){}
foo.beforeMethodHook = function(){console.log('Hook was called.');}
foo.getInstance = function(){
var newInstance = new foo;
var funcNames = Object.getOwnPropertyNames(foo);
for(i in funcNames){
var funcName = funcNames[i];
if(funcName == 'getInstance' || funcName == 'beforeMethodHook' || Object.hasOwnProperty(funcName)) continue;
newInstance[funcName] = function (){
foo.beforeMethodHook();
return foo[this].apply(foo,arguments);
}.bind(funcName);
}
return newInstance;
}
foo.test1 = function(arg1){console.log('test1 was called. arg1 = ' + arg1);return true;}
foo.test2 = function(arg1,arg2){console.log('test2 was called. arg1 = ' + arg1 + ' , arg2 = ' + arg2);return true;}
//Test
var f = foo.getInstance();
f.test1('ahaha');
f.test2('heihei','houhou');
As IE10- don't support function(){}.bind(), I tried to change the .bind() to (function(){})() which follows
newInstance[funcName] = (function (){
foo.beforeMethodHook();console.log(arguments);
return foo[funcName].apply(foo,arguments);
})(funcName);
But the problem comes, I lose arguments that f.test1('ahaha') has passed. the arguments array only gives ["test1"] which is the function name.
How can I fix that? Thanks in advance.
You can implement your own bind. Easy version:
if (!Function.prototype.bind) {
Function.prototype.bind = function(that) {
var fn = this;
return function() {
fn.apply(that, arguments);
}
};
}
or proper version:
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
// closest thing possible to the ECMAScript 5 internal IsCallable function
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP && oThis
? this
: oThis,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
Code taken from:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
try using the alternative code for bind given over here
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FFunction%2Fbind
you should do something like this
newInstance[funcName] = (function (){
console.log(arguments);
return function(){
foo.beforeMethodHook();
foo[funcName].apply(foo,arguments);
}
})(funcName);

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