How to bind "this" automatically while calling a function? - javascript

My example code:
var Person = (function () {
var __sym = Symbol('Person');
class Person {
constructor(name) {
this[__sym] = { name: name };
}
getName() {
let _this = this[__sym];
return _this.name;
}
}
return Person;
}());
var person = new Person('Hermione');
console.log(person.name); // undefined
console.log(person.getName()); // Hermione
In this example, I'd use __sym as a key to assign to the private data.
My question is: How to bind this[__sym] to every method inside the Person class?
My real project:
let Chatwindow = (function () {
let __sym = Symbol('Chatwindow');
let __data = {};
// for typo
let __prop = {
targetUserId: 'targetUserId'
};
__data.init = function (...args) {
let _this = this[__sym];
let options = args[0];
// validating the type of 'options' and the properties...
// just get what I need
_this[__prop.targetUserId] = options[__prop.targetUserId];
(async () => {
let messages = await __data.getMessagesAsync.call(_this);
// my goal:
// let messages = await __data.getMessagesAsync();
})();
};
__data.getMessagesAsync = function () {
let _this = this;
let promise = new Promise(function (done) {
// create model before sending
let model = { [__prop.targetUserId]: _this[__prop.targetUserId] };
// sending...
done();
});
return promise;
};
class Chatwindow {
constructor() {
this[__sym] = {};
}
set init(value) {
return __data.init;
}
get init() {
return (...args) => __data.init.call(this, ...args);
}
}
return Chatwindow;
}());
Everytime I call a method, I have to use call(_this) function to bind the key, like this:
let messages = await __data.getMessagesAsync.call(_this);
After that, inside the getMessagesAsync method, I can assign to the private data using this property.
What I want to achieve: I want to bind all of the methods just one time inside the init method. How can I do that?
Something like this:
__data.getMessagesAsync.oncall = function () {
// bind this with this[__sym]
};
Then,
__data.getMessagesAsync(); // no need to pass anymore
Thank you!

You can use arrow functions, so you will be sure that context (this) will be same every time (this will be pointing to parent this no matter from where arrow function is called)
__data.getMessagesAsync = () => {
let promise = new Promise((done) => {
// create model before sending
let model = { [__prop.targetUserId]: this[__prop.targetUserId] };
// sending...
done();
});
return promise;
}

In javascript, using function_name.bind(o) allows you to create a new function whose context this is bound to the object o.
What you want is to create a new function:
__data.boundMessagesFunction = __data.getMessagesAsync.bind(_this);
Now you can call:
let messages = await __data.boundMessagesFunction();

Related

How to convert regular function to async/await function taken from a singleton pattern?

I copied the following design pattern from dofactory.com
My question is how can I convert that to async/await?
var Singleton = (function () {
var instance;
function createInstance() {
var object = new Object("I am the instance");
return object;
}
return {
getInstance: function () {
if (!instance) {
instance = createInstance();
}
return instance;
}
};
})();
function run() {
var instance1 = Singleton.getInstance();
var instance2 = Singleton.getInstance();
console.log("Same instance? " + (instance1 === instance2));
}
It probably goes something like this (it's hard to tell without your code for asynchronously creating the instance):
const Singleton = (() => {
let instance;
const createInstance = async () => {
// no need to `await` in here unless it's actually needed as part of
// your singleton build process; return the object or the promise,
// whichever you end up with.
const object = new Object("I am the instance");
return object;
}
return {
getInstance: async () => {
if(!instance) {
// `createInstance()` always returns a promise because
// it's async; store the promise; this only happens
// in the first call to `getInstance()`
instance = createInstance();
}
// it doesn't matter that we're returning the promise
// (resolved or not), chained promises are coalesced
// and the `await`s in `run()` will either wait for
// resolution or resolve immediately
return instance;
}
};
})();
const run = async () => {
// let instance1 = await Singleton.getInstance();
// let instance2 = await Singleton.getInstance();
// not a good way to test this, lets try something else
let [instance1, instance2] = await Promise.all([
Singleton.getInstance(),
Singleton.getInstance(),
]);
console.log("instance1:", instance1.toString());
console.log("instance2:", instance2.toString());
console.log("Same instance?", (instance1 === instance2));
};
run();

How to set proxy on constructor function

I have a constructor function like this:
function a(p){
this.k=12;
this.f = p;
this.t = function(){};
}
Now let say i create a object with this function:
let obj = new a("tf");
I can always do this to check if a new property assigned to object:
obj = new Proxy(obj,{set:()=>{console.log("new property assigned!");return true;}})
//Now if i were to say
obj.property1 = 12
//It will log out "new property assigned!"
But the problem is, that i have to do this for every new object i create with this constructor function.
So what i want to do is whenever i create a new object like this:
let newObj = new a();
I want to set my proxy automatically.
How can i achieve this?
Write a factory function in which you create a new instance of your object while also adds a Proxy to the newly created instance.
function proxyFactory(Class, ...args) {
const instance = new Class(...args);
return new Proxy(instance, {
set: () => {
console.log("new property assigned!");
return true;
}
});
}
And then call the factory function with the class and the arguments you want to apply.
let newObj = proxyFactory(a, "tf");
You could also make a proxy around class, intercept construct calls, and return a proxy with set trap.
const A = new Proxy(a, {
construct(target, args) {
return new Proxy(new target(...args), {
set() {
console.log('new property assigned');
return true
}
})
}
})
const inst = new A('tf')
inst.property = true
function a(p) {
this.k = 12;
this.f = p;
this.t = function() {};
}
You could make a function that wraps around your class. E.g.
const proxyify = (Class, ...args) => {
return new Proxy(new Class(...args), {
set: () => {
console.log('set');
return true;
}
});
}
Usage would then be
function Dog() {
this.type = "Dog";
}
const ProxiedDog = proxify(Dog);

Javascript method in Function Error with "is not a function"

I've been learning basic Javascript concept with class.
I'm trying it with ES5 syntax.
By the way, I'm stuck with this problem.
I defined a class with function declaration. And Defined a method in that class.
const Vehicle = function() {
this.passengers = [];
console.log('Vehicle created');
const addPassenger = function(p) {
this.passengers.push(p);
}
}
const v = new Vehicle();
v.addPassenger("Frank");
v.addPassenger("Zim");
console.log(v.passengers);
But when I call it with its instance, I got the error. I think the problem is bind...But I have no idea where and which one should I bind.
Thank you!
You are currently only declaring the addPassenger function as a constant inside the function.
To "make the function part of class", use this
this.addPassenger = function(p) {
////
}
When you create a function inside the vehicle function using const or function syntax, it doesn't belong to the instance variable and is private to the constructor function. In order to use it from the instace object you need to define it for the instance like
const Vehicle = function() {
this.passengers = [];
console.log('Vehicle created');
this.addPassenger = function(p) {
this.passengers.push(p);
}
}
const v = new Vehicle();
v.addPassenger("Frank");
v.addPassenger("Zim");
console.log(v.passengers);
You need to replace const with this
const Vehicle = function() {
this.passengers = [];
console.log('Vehicle created');
this.addPassenger = function(p) {
this.passengers.push(p);
}
}
const v = new Vehicle();
v.addPassenger("Frank");
v.addPassenger("Zim");
console.log(v.passengers);

javascript: call a default function?

I need to make some js functionality like that:
let text =function()
{
this.main = ...;
this.toArr = ...;
};
let t = new text();
console.log( t() ); // call a function 'main' in text;
t().toArr(); // call a function 'toArr' in text;
Try this:
let text = function (myarg) {
// Usage: var t = new text(<arg>);
this.uniqueProperty = "test";
var main = () => {
// main code
return {
toArr: () => {
return [myarg, this.uniqueProperty];
}
};
};
return main;
}
var t = new text("hey world");
console.log(t());
console.log(t().toArr());
Calls are the same as in your question
Note: your main function returns object now.
How does this work?
You call new text("arg"), but constructor returns main function instead of this. Main function returns object with toArr function, and can be accessed through new text("arg")().toArr code. Why I put both functions into () => {}?. The answer is simple - that's how to access text instance properties. So we can access unique text properties. Else, this will be main function reference.
Please take a deeply look at MDN's Inheritance part.
This is a simple usage as below:
let text = function()
{
this.main = function(){
return {a:1};
}
this.toArr = function(){
return [1,2,3];
}
};
let t = new text();
console.log( t.main() ); // call a function 'main' in text;
console.log(t.toArr()); // call a function 'toArr' in text;

Access `this` from within required object literal?

I desire to have the following type of object:
const Client = require('./Client')
let client = new Client()
client.someObject.create(...)
client.someObject.update(...)
client.someObject.delete(...)
etc.
This is very easy to accomplish doing something like this:
const Client = function () {
this.someObject = {}
this.someObject.create = function () {...}
this.someObject.update = function () {...}
this.someObject.delete = function () {...}
}
module.exports = Client
But from an organizational standpoint (and because of the massive number of functions someObject has, it would be helpful to put all the someObject stuff into it's own file and require it: require('./someObject'). However, I still need to be able to access the Client object (this) within someObject.create(), someObject.update(), etc.
this.someObject = require('./someObject')
// someObject.js
module.exports = {
create: function () {
// How do I access Client here? Can I pass it to the object literal?
}
}
I've tried to do some prototype sub module type of setup but it doesn't appear to work.
Client.prototype.someObject.create = function () { ... }
How can I separate someObject into it's own file and still access the Client this?
You'll need to provide the Client instance to someObject itself so the latter's methods can use it to reference the former.
One way you accomplish that is to define a 2nd constructor for someObject that takes the client as an argument.
const SomeObject = function (client) {
if (!client) throw new Error('Client reference is required.');
this.client = client;
};
SomeObject.prototype.create = function () {
let client = this.client;
// ...
};
// ....
module.exports = SomeObject;
const SomeObject = require('./someObject');
const Client = function () {
this.someObject = new SomeObject(this);
}
You can also get a similar result with Object.create() if you'd rather keep the object literal:
const baseline = {
create: function () {
let client = this.client;
// ...
},
// ...
};
module.exports = function createSomeObject(client) {
return Object.create(baseline, {
client: {
value: client
}
});
};
const createSomeObject = require('./someObject');
const Client = function () {
this.someObject = createSomeObject(this);
};

Categories