How to pass a function with named arguments - javascript

I am creating an extension function:
jQuery.fn.openCreatePersonModal = function (arg1, personHandler) {
var person = { "displayName": "john" };
personHandler(person);
return this;
}
But can't use it, neither this way:
$("<div></div>").openCreatePersonModal({
arg1: "bla",
personHandler: somePreviouslyCreatedFunction
});
Nor this way:
$("<div></div>").openCreatePersonModal({
arg1: "bla",
personHandler: function(person) { ... }
});
I'm getting:
undefined is not a function
So it is not recognizing somePreviouslyCreatedFunction as a function.

If one wants to use named arguments, should use 1 argument and interpret it as an object
jQuery.fn.openCreatePersonModal = function (args) {
var person = { "displayName": "john" };
args.personHandler(person); // <-- notice "args."
return this;
}

Related

Assigning functions to Objects

I want to add functions to JSON Objects, but I can't find function for assigning to all objects, only to one.
This code works with Arrays:
Object.defineProperty(Array.prototype, 'random', {
value: () => {
return this[Math.floor(Math.random() * this.length)];
},
});
I've also found this code:
const obj = {name: 'Bob'};
obj.fullName = function() { return this.name }
But that one only works for specific object, not all of them.
Is it event possible to write global functions for all JSON Objects, and if is, then how to do it?
You could add the function to Object.prototype. Note that this is not considered a very good practice because it could impact the rest of the code (like shown in the comments):
Object.prototype.fullName = function() { return this.name; };
const obj = { name: 'Bob' };
console.log(obj.fullName());
You should consider doing this instead:
const baseObject = { fullName: function() { return this.name; } };
const obj = Object.create(baseObject, { name: { value: 'Bob', writable: true } });
console.log(obj.fullName());
And if your target runtime (browser?) supports ECMAScript 6, you could also create a dedicated class for this:
class MyClass {
constructor(name) {
this.name = name;
}
fullName() { return this.name; }
}
const bob = new MyClass('Bob');
console.log(bob.fullName());
Finally, the class syntax for ECMAScript 5:
function MyClass(name) {
this.name = name;
}
MyClass.prototype.fullName = function() { return this.name; }
const bob = new MyClass('Bob');
console.log(bob.fullName());

Simple JS example of Singleton Pattern not working

I made a simple example of Singleton Pattern but it is giving blank objects in both cases. Please someone help?
var a = ( function(){
var instance = {};
function init() {
return {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
}
return {
getInstance: function(){
if(!instance) {instance = init();}
return instance;
}
}
})();
console.log(a.getInstance());
console.log(a.getInstance());
As I said in a comment, the problem is that instance is initialized to {}, which is truthy, so !instance will never be true.
There's only one instance variable, created for the one call to your anonymous function. That's the whole point of having it, it tracks the singleton. So initialize it with a falsy value (or leave it with the default undefined, which is falsy):
var a = ( function(){
var instance = null;
function init() {
return {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
}
return {
getInstance: function(){
if(!instance) {instance = init();}
return instance;
}
}
})();
const first = a.getInstance();
console.log(first);
const second = a.getInstance();
console.log(second);
console.log(first === second); // true
.as-console-wrapper {
max-height: 100% !important;
}
That said, you only need all of this complexity if you want late initialization. Otherwise, just create the object:
var a = {
instance = {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
};
Then a.instance is the singleton. If you want it to be non-writable:
var a = Object.defineProperty({}, "instance", {
value: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
}
});
(That will also be non-enumerable. If you want it to be enumerable, add enumerable: true.)
Or just:
var instance: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
If you want that to be read-only, use const in any modern environment:
const instance: {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
In all of the above, remember that although you may have a singleton, and although the instance property/constant may be read-only, nothing about the object itself is immutable. Properties can be added, removed, changed, etc. To prevent that, use Object.freeze.
If in case this can be a variety to T.J. Crowder answer, You may create an instance once and save it to a variable, then every time the method is called, you may return that variable. I think closure plays a role here.
var a = ( function(){
var instance = {
name: "rosy",
age: 29,
printName: function(){
console.log(this.name)
}
};
return {
getInstance: function(){
return instance;
}
}
})();
let b = a.getInstance();
let c = a.getInstance();
console.log(b);
console.log(c);
console.log( b === c )

How to pass argument in javascript

var Person = {
name: "jana",
getName: function(callBack) {
callBack();
console.log("** "+this.name);
}
}
var anotherPerson = { name: "prabu"}
I have 2 objects. I need "anotherPerson" to be bound with the Person object. Also, I want to send parameter as a function.
I have tried below methods, but its not working
Person.getName.apply(anotherPerson, function(){})
Person.getName.apply(anotherPerson)(function(){})
Use call to pass an arbitrary number of arguments to your function, or apply to pass an array of arguments:
var Person = {
name: "jana",
getName: function(callBack) {
callBack();
console.log("** " + this.name);
}
}
var anotherPerson = {
name: "prabu"
}
Person.getName.call(anotherPerson, function () {})
Person.getName.apply(anotherPerson, [function () {}])
Have you tried Object.assign ? Like so
var Person = {
name: "jana",
getName: function(callBack) {
callBack();
console.log("** " + this.name);
}
}
var anotherPerson = {
name: "prabu"
}
Object.assign(Person, anotherPerson).getName(alert)
You can use arrow function and return the name parameter to assign value to getName.
var Person = {
name: "jana",
getName: (obj) =>obj.name
}
var anotherPerson = {
name: "prabu"
}
Person.getName(anotherPerson);
console.log(Person);

Acess to this from subobject in JavaScript

How do I get access to the properties or method of the main object, from sub-obiect level two (sub3). If possible I would like to avoid solutions chaining return this.
Obj = function () {};
Obj.prototype = {
name: 'name',
main: function(){
console.log(this.name);
},
subobject: {
sub2: function () {
console.log(this);
},
sub3: function () {
console.log(this.name); // How access to Obj.name ??
}
}
}
o = new Obj();
o.main(); // return name
o.subobject.sub2(); // return subobject
o.subobject.sub3(); // return undefined
With your current syntax, you can't. Because for sub2 and sub3, the this variable is Obj.prototype.subobject.
You have multiple choice:
The obvious one: don't use a suboject.
Create subobject, sub2 and sub3 in the constructor
Obj = function() {
var self = this;
this.subobject = {
sub1: function() { console.log(self); }
}
}
Use bind at each call:
o.subobject.sub2.bind(o)();

What's the syntax to add a function other than an accessor?

I'm learning the JavaScript with Node. I like the idea of creating objects with factories, and after reading a lot on this subject, I chose to create objects with this code:
// ES6 only
'use strict';
// The base object, "object literal" syntax
let animal2 = {
// public member
animalType: 'animal',
// public method
describe() {
return `This is "${this.animalType}"`;
}
};
// factory function which serves 2 purposes:
// - encapsulation, that's where private things are declared thanks to closures
// - the "real" object creation, this prevents to use "new" which is not really Js-ish
let afc = function afc() {
// private member
let priv = "secret from afc";
return Object.create(animal2, {
// Object customisation
animalType: { value: 'animal with create'},
// object extension. The new objects created here get 3 new members:
// - a private member
// - a new property
// - a new method to access the private member
// new public member
color: { value: 'green' },
secret: {
get: function () { return priv; },
set: function (value) { priv = value; },
},
KO1() {
console.log("KO1");
},
KO2: function() {
console.log("KO2");
}
});
}
// creation of an animal instance
let tac = afc();
My problem is I can't figure out what's the syntax to add a function which can manipulate private data while not being just an accessor. I put here 2 examples which came to my mind (KOx), but as their names suggest, this syntax leads to: "KOx is not a function".
Object.create expects an object of property descriptors as its second argument. This is why you have to use {value: …} or {set: …, get: …} everywhere.
And in fact you'd have to do the same for a method - which is just a standard property with a function as its value:
…
KO3: {value: function() {
…
}},
…
However, I'd avoid using property descriptors when you don't need them. Object.assign is a better fit:
return Object.assign(Object.create(animal2, {
secret: {
get() { return priv; },
set(value) { priv = value; },
}
}), {
animalType: 'animal with create',
color: 'green',
KO1() {
console.log("KO1");
},
KO2: function() {
console.log("KO2");
}
});
Why don't just use the getter syntax?
return {
__proto__: animal2, // To be honest __proto__ is not a good thing to use
animalType: 'animal with create',
color: 'green',
get secret() { return priv; },
set secret(value) { priv = value; },
get KO3() { console.log("KO3"); },
// or just the following, if you would like it to be a regular member function
// KO3() { console.log("KO3"); },
};
Or without explicit __proto__:
const result = {
animalType: 'animal with create',
color: 'green',
get secret() { return priv; },
set secret(value) { priv = value; },
get KO3() { console.log("KO3"); },
};
Object.setPrototypeOf(result, animal2);
return result;

Categories