Declaring JavaScript Object property of a constructor object having arguments issue - javascript

I'm trying to create an object using constructor pattern and also define properties using Object.defineProperty.
function random (a,b,c) {
var sample = null;
this.a = a;
this.b = b;
if(b && c){
this.sample(b,c);
}
Object.defineProperty(random, 'sample', {
get: function(){
console.log(b);
}
});
};
var foo = new random(10,1,2);
This throws an error: Uncaught TypeError: object is not a function.
What am I doing wrong ? Please Help.

There are several issues:
You reference sample before it is defined
You define sample on the constructor (random), but it should be on this.
There was a closing parenthesis missing.
You call sample like a function, but you had not defined it as one. The function in defineProperty is the getter, not the method itself. If you want to code it like this, you need the getter to return your method.
Check this corrected code with comments:
function random (a,b,c) {
var sample = null;
this.a = a;
// First define, then call:
// Define on this, not on random:
Object.defineProperty(this, 'sample', {
get: function() {
// must return a function
return function (b) {
console.log(b);
};
}
}); // <-- missing bracket
// Moved after defineProperty:
if(b && c) {
this.sample(b,c); // note that you don't use the second argument
}
}
console.log(new random(1,2,3));

Related

Is it possible to get name property of a function without using new using ES6 in strict mode? [duplicate]

I need the current function name as a string to log to our log facility. But arguments.callee.name only works in loose mode. How to get the function name under "use strict"?
For logging/debugging purposes, you can create a new Error object in the logger and inspect its .stack property, e.g.
function logIt(message) {
var stack = new Error().stack,
caller = stack.split('\n')[2].trim();
console.log(caller + ":" + message);
}
function a(b) {
b()
}
a(function xyz() {
logIt('hello');
});
You can bind function as its context then you can access its name via this.nameproperty:
function x(){
console.log(this.name);
}
x.bind(x)();
After little research here is a good solution :
function getFnName(fn) {
var f = typeof fn == 'function';
var s = f && ((fn.name && ['', fn.name]) || fn.toString().match(/function ([^\(]+)/));
return (!f && 'not a function') || (s && s[1] || 'anonymous');
}
function test(){
console.log(getFnName(this));
}
test = test.bind(test);
test(); // 'test'
Source : https://gist.github.com/dfkaye/6384439
Building on #georg solution, this one returns just the function name. Note though that it may fail if called from an anonymous function
function getFncName() {
const stackLine = (new Error())!.stack!.split('\n')[2].trim()
const fncName = stackLine.match(/at Object.([^ ]+)/)?.[1]
return fncName
}
function Foo() {
console.log(getFncName()) // prints 'Foo'
}
A simple solution to dynamically retrieve function names [like magic variables] is the use of scoped variables, and the Function.name property.
{
function foo() {
alert (a.name);
}; let a = foo
}
{
function foo2() {
alert(a.name)
}; let a = foo2
};
foo();//logs foo
foo2();//logs foo2
Note: Nested functions cease to be source elements, and are hence not hoisted. Also, this technique cannot work with anonymous functions.
If (like me) you want to define this elsewhere and call it generically, you can store the code as a string somewhere global or import it, then eval() it wherever to access the current function name. (Using eval keeps the context at the point of invocation.)
There's gotta be a way to do this without using a string, but whatever.
SomeObject.whatFunc =
'const s = new Error().stack;' +
"const stackLine = new Error().stack.split('\\n')[2].trim();" +
'const fncName = stackLine.match(/(?<=at )(.*)(?= \\()/gm)[0];' +
'console.log(fncName);'
// Whereever you want the func name
function countBananas('weeee') {
eval(SomeObject.whatFunc)
// blah blah blah
}
countBananas() // logs 'countBananas'
just an update to get the full name :
function logIt(message) {
var stack = new Error().stack,
// update is on this line
caller = stack.split('\n')[2].trim().split(/\s+/)[1];
console.log(caller.trim().split(/\s+/)[1];);
}
function a(b) {
b()
}
a(function xyz() {
logIt('hello');
});

Overriding a function's toString() in node exports

I am trying to override a toString() method, but getting into difficulties.
Already looked here and here, but still no luck.
My code is as follows:
var Foo = function(arg) {
// some code here...
return function (a, b, c) {
// return function code...
};
};
Foo.prototype.toString = function () {
return "string representation of function";
};
exports.bar(arg) {
return Foo(arg);
};
In another module:
var mod = require('the-module-from-above');
console.log(mod.bar().toString()); // prints return function source code.
My question is, how come my toString() function isn't called, and how can I make it get called?
thank you.
You only set things on a function's prototype if you're using the function as a constructor with new. Since you don't appear to be doing that here, you need to set the toString function on the actual function you return.
function fooToString() {
return "string representation of function";
}
var Foo = function(arg) {
// some code here...
var ret = function (a, b, c) {
// return function code...
};
ret.toString = fooToString;
return ret;
};
You could also add the toString function when you actually create the object in the bar function, if you'd prefer to do that.
exports.bar(arg) {
var foo = Foo(arg);
foo.toString = fooToString;
return foo;
};

Javascript Prototype Oriented Programming doubts

I want to do the following in Javascript
function A(){
this.B = function() { ... };
this.C = function() { <<I need to call B() here>> } ;
};
I have read the following way of method overloading, but I want to know whether professional programmers would do it this way. I.e. if you would only do this as an exercise or experiment or would actually do this in production code.
function foo(a, b, opts) {
};
foo(1, 2, {"method":"add"});
foo(3, 4, {"test":"equals", "bar":"tree"});
Just call B() from inside C();
function A(){
B = function() {
// Do something here
}
C = function() { B(); }
};
Or, if you just want to create an alias
function A(){
B = function() {
// Do something here
}
C = B
};
The clean way would be :
var A = function() { };
A.prototype.B = function() { };
A.prototype.C = function() { this.B(); };
The prototype is just a static set of properties that is cloned inside every new instance you create.
The difference between what you're doing and this is that in your case, methods are created and added when you are in the "constructor" of the object, while with this method they already are properties of the object before you enter its "constructor", and are only parsed once (when you add them to the prototype) instead of being parsed everytime you create a new instance, which is faster.
I think, correct me if i'm wrong.
var A = function() {
// this scope is what i mean by "constructor".
};

Invoke Function.prototype.apply inside a re-declaration of apply (Javascript)

While learning Javascript, I tried to re-declare the apply property of a function. Thus far no problem.
function foo() { return 1; }
alert(foo()); // 1
alert(foo.apply(null)); // 1
foo.apply = function () { return 2; }
alert(foo()); // 1
alert(foo.apply(null)); // 2
Now, I tried to make apply do something more and call the "old" apply (like logging).
var old = foo.apply;
foo.apply = function() {
alert("A");
return old(null);
}
alert(foo.apply(null));
I get
TypeError: Function.prototype.apply was called on [object Window],
which is a object and not a function
I tried
foo.apply = function() {
alert("A");
return arguments.callee[Function.prototype.apply](null);
}
alert(foo.apply(null));
I get
TypeError: Property 'function apply() { [native code] }' of object function () { alert("A"); return arguments.calleeFunction.prototype.apply; } is not a function
Is there any real way to accomplice what I try? Or is it some restriction due to Function.prototype.apply being native code?
Yes. apply expects to be applyed (yes, with exactly itself) on a function, while the way you used it (by old()) makes its this value the global object (window). So you can do this:
var old = foo.apply; // === Function.prototype.apply
foo.apply = function() {
// "this" is the function foo
alert("A");
return old.apply(this, arguments); // applying the (old) apply function on foo
// or better without any arguments:
return old.call(this); // like this(); which is foo()
}
alert(foo.apply(null));
// and the call solution with an argument:
foo.apply = function(context) {
return old.call(this, context);
// like this.call(context);
// which is foo.call(context)
// which is like context.foo()
}
Also check out the docs for the call and apply "methods" (though we've use old not as a method, but as a pure function).

Can a JavaScript object have a prototype chain, but also be a function?

function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () { };
c.prototype = a;
var d = new c();
d.b(); // returns "bar"
d(); // throws exception, d is not a function
Is there some way for d to be a function, and yet still inherit properties from a?
Actually, it turns out that this is possible, albeit in a non-standard way.
Mozilla, Webkit, Blink/V8, Rhino and ActionScript provide a non-standard __proto__ property, which allow changing the prototype of an object after it has been created. On these platforms, the following code is possible:
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
return "hatstand";
}
c.__proto__ = a;
c(); // returns "hatstand"
c.b(); // returns "bar"; inherited from a
This might be of use to anyone who doesn't need to worry about cross-platform compatibility.
However, note that only the properties of an object can be inherited. For example:
var d = {};
d.__proto__ = a;
d.b(); // returns "bar"
d(); // throws exception -- the fact that d is inheriting from a function
// doesn't make d itself a function.
Short answer: not possible.
This line of your code:
var d = new c();
automatically assumes that d is an object. Unless c is a constructor of a builtin object, e.g., Function. But if c is already defined by the language, you cannot manipulate its prototype, and cannot "inherit" it from whatever you like. Well, in some interpreters you can, but you cannot do it safely across all interpreters — the standard says: "you doth not mess with standard objects or the interpreter will smite you!".
The builtin objects are "unique" and JavaScript does not provide ways to duplicate them. It is not possible to recreate String, Number, Function, and so on without resorting to incompatible trickery.
Based on a discussion on meta about a similar question I'm posting this answer here based on #alexander-mills original
This can now be done in a standards compliant way
First create an object which inherits Function
const obj = Object.create(Function.prototype); // Ensures availability of call, apply ext
Then add you custom methods and properties to obj
Next declare the function
const f = function(){
// Hello, World!
};
And set obj as the prototype of f
Object.setPrototypeOf(f,obj);
Demonstraction
const obj = Object.create(Function.prototype);
// Define an 'answer' method on 'obj'
obj.answer = function() {
// Call this object
this.call(); // Logs 'Hello, World'
console.log('The ultimate answer is 42');
}
const f = function() {
// Standard example
console.log('Hello, World');
};
Object.setPrototypeOf(f, obj);
// 'f' is now an object with an 'answer' method
f.answer();
// But is still a callable function
f();
Yes, it is possible if you use the __proto__ property Daniel Cassidy mentioned. The trick is to have c actually return a function that has had a attached to its prototype chain.
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
var func = function() {
return "I am a function";
};
func.__proto__ = a;
return func;
}
c.prototype = a;
var d = new c();
d.b(); // returns "bar"
d(); // returns "I am a function"
However, you'll need to do some more tweaking of the prototype chain if you want instanceof to return better results.
d instanceof c // true
d instanceof a // false
c instanceof a // false
Does it have to actually be a prototype chain? You can use a mixin pattern to make a function have all of the properties of a instead. You can even wrap it in a nice "new" syntax to fake it if you really want.
function a () {
return "foo";
}
a.b = function () {
return "bar";
}
function c () {
var f = function(){
return a();
};
//mixin all properties on a
for(var prop in a){
f[prop] = a[prop];
}
return f; //just returns the function instead of "this"
};
var d = new c(); //doesn't need the new keyword, but just for fun it still works
alert(d()); //show "foo"
alert(d.b()); //shows "bar"
You can add properties to d without affecting a. The only difference between this and what you want is that changes to a will not affect existing "instances" of c.
This is something I've been trying to do for a while now. Special thanks to the authors above for their input.
Here is a chained implementation of using a "callable-object":
var $omnifarious = (function(Schema){
var fn = function f(){
console.log('ran f!!!');
return f;
};
Schema.prototype = {
w: function(w){ console.log('w'); return this; },
x: function(x){ console.log('x'); return this; },
y: function(y){ console.log('y'); return this; }
};
fn.__proto__ = (new Schema()).__proto__;
return fn;
})(function schema(){ console.log('created new schema', this); });
console.log(
$omnifarious()().w().x().y()()()
);
Also, with this "Schema" approach, it may be possible to create a reusable interface using Object.freeze() on Schema's prototype or __proto__ object. That might look something like this: fn.__proto__ = Object.freeze(new Schema().__proto__) -- this is not a practical example and more may be needed. That said, its a different discussion. Try it out and let me know!
Hope this is helpful.

Categories

Resources