I have an object that is as follows:
{ except: player => ({ send :player.getSocket().broadcast.emit }) }
However this means that the this in the emit function is not the one it expects it to be (the broadcast object).
So I can do:
{ except: player => ({ send : (msg, data) => player.getSocket().broadcast.emit(msg, data) }) }
But this is ugly, especially if the arguments change.
So the alternative is:
{ except: player => ({ send : (t = player.getSocket().broadcast).emit.bind(t) }) }
But is there a tidier way of doing this, of assigning a function to an object while maintaining it's this as it's parent object.
You can specify who this will be by calling the function with apply or call. The first parameter to these methods will be this within the body of the function.
Using bind in order to maintain the scope of this is actually a good solution to your problem, the way I see it, it makes the code a lot more understandable because you can know to what object the function actually belongs, by using apply or call, when you read the code you wont know to what this the function/method belongs. As far as i know, bind is a pretty good solution to your problem here.
Related
I have a method in my vue js element:
_deleteDesign : function(dsn)
{
//_deleteDesign
var url = '{{ url('/fapi/designsTmp/') }}/'+dsn.design_id;
axios.delete(url)
.then(function(){
this.$delete(this.creations, this.creations.indexOf(function(el){
return el.design_id = dsn.design_id;
}));
})
.catch(function(e){
alert('error deleting design');
})
debugger;
}
In this method I am using the indexOf function of Javascript, but vuejs reports me this error in the Chrome debugger:
this.creations.indexOf is not a function
What's the problem?
The this context has changed in the promise then handler because of new function declaration. One way to fix, would be to use ES6 arrow function which keeps the existing this binding for code within the function:
.then(() => {
this.$delete(this.creations, this.creations.indexOf(function(el){
return el.design_id = dsn.design_id;
}));
})
"indexOf" method can only be executed on variables that are type "string" or "array" (which is actually type "object").
So in your particular case "this.creations" must be either array or string. The issue is that you somehow ended up with the case when "this.creations" is not one of those types.
One possible solution is to add
console.log(typeof this.creations)
and monitor the type of this variable.
Also as previous answer mentioned the issue is that "this" changed context. One solution for this is to make copy of this object:
const self = this;
in the beggining of _deleteDesign function and to use "self" object instead of "this". Generally avoid using "this" object as much as possible.
Using ES6/ES2015 and webpack, I am trying to wrap my head around the little monster that is the keyword this.
I have a class Edit containing a static method change(event) and within that method I am trying to make a recursive call to the method itself (depending on a given variable).
In most cases I could just call this.change(event) but here the keyword this is already occupied by the jquery object that was calling the function instead of the containing class.
The easiest solution would be to just call Edit.change(event) instead, but there must be a cleaner solution. Every programming language I have encountered so far has had some reference to its containing class built in.
I promise I have checked the docs and other threads on stackoverflow, but no one I found seems to address this particular problem.
// main.js
'use strict';
const $ = require('jquery');
const Edit = require('./Edit');
$(document).ready(() => {
let thingsToAddToData = {
whatToDo: // defined here depending on context
someVariable: //defined here depending on context
};
$('table :input').change(thingsToAddToData, Edit.change);
}
and here the Edit class is defined
// Edit.js
class Edit {
static change(event) {
if(event.data.whatToDo === 'do_nothing'){
return false;
}
if(event.data.whatToDo === 'do_this_important_thing'){
// here some important stuff is done
return true;
}
if(event.data.someVariable === 'special_case'){
event.data.whatToDo = 'do_this_important_thing'
// THIS IS THE LINE THAT GIVES ME HEADACHES
return this.change(event);
}
// here some default stuff is done
}
}
module.exports = Edit;
The easiest solution would be to just call Edit.change(event) instead, but there must be a cleaner solution
No, this is indeed what you need to use to always refer to the Edit class. There's nothing messy with it, just use it.
You could also use this.change(event) if you weren't using the method as an event handler. Make sure to call it as a method:
$('table :input').change(thingsToAddToData, Edit.change.bind(Edit));
// or
$('table :input').change(thingsToAddToData, e => Edit.change(e));
Either of the answers by #Bergi, should work (using Function.prototype.bind or () => {}). However I think your problem is more structural. Since Edit.change is an event handler it doesn't make sense to call it directly, since it is supposed to be fired through events.
I would suggest firing the event again with some parameter changes (http://api.jquery.com/trigger/):
replace Edit.change(event); with this.trigger(event);
That way there is no need for calling the handler directly, and you don't need to change the this context, thus keeping the code more transparent.
Static methods operate on the class instead of instances of the class, they are called on the class. There are two ways to call static methods:
<ClassName>.methodName()
or
<class-instance>.constructor.methodName()
In static methods, the this keyword references the class. You can call a static method from another static method within the same class with this.
I am currently looking into utilizing mostly pure functions in my code. I realize the benefits of this. However, I'm wondering what the best practice is when updating a state variable, calling methods defined within a module, and how to handle window functions.
Using the example below, let's say I have a module, MyModule.
The MyModule.calculate function is pure, so no worries there.
The MyModule.trackSomething function however is updating the MyModule.count to keep track of it for use in the event handler, used in MyModule.assignEventHandlers function. This is not pure because it is using an outside reference to a variable. Even if I refactor to make count an object and pass it in as a parameter to MyModule.trackSomething, I'd still be altering the value through reference, making it impure.
In the MyModule.assignEventHandlers function, I'm using global window object functions. This makes it impure because I'm referencing outside functions. Should the window object be passed by reference when calling functions it has?
In the MyModule.init function, I'm calling the MyModule.assignEventHandlers function. I guess this makes it impure as well since MyModule.assignEventHandlers is an outside reference.
So my question is: What is the best way to handle the last 3 bullet points?
Any advice is much appreciated. Thanks!
const MyModule = {
calculate(a, b) {
return a + b;
},
count: 0,
trackSomething() {
MyModule.count += 1;
},
assignEventHandlers() {
// assign event handlers to some DOM elements
window.document.getElementById('my-ele').addEventListener('click', () => {
window.alert(MyModule.count);
MyModule.trackSomething(MyModule.count);
});
},
init() {
MyModule.assignEventHandlers();
}
};
I think when we came out with a solution, instead of just focus on pure and impure function, it's better to focus on practicability as well. It's okay to have impure function.
Here is another version of the implementation using RxJs - a reactive js lib. Also using ES6 class instead of module. Take a look at action and action2. Both produce same result in different ways.
In my opinion, action is good enough. Don't need to make everything super pure.
class MyClass {
constructor(elementId) {
this.ele = document.getElementById(elementId);
this.click$ = Rx.Observable.fromEvent(this.ele, 'click');
this.count = new Rx.BehaviorSubject(0);
}
calculate(a, b) {
return a + b;
}
action() {
window.alert(this.count.getValue());
const nextVal = this.calculate(this.count.getValue(), 1);
this.count.next(nextVal);
}
action2(log, subject, method) {
log(subject.getValue());
const nextVal = method(subject.getValue(), 1);
subject.next(nextVal);
}
}
const a = new MyClass('my-ele1');
a.click$.subscribe(() => a.action2(window.alert, a.count, a.calculate));
const b = new MyClass('my-ele2');
b.click$.subscribe(() => b.action());
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.5.6/Rx.min.js"></script>
<button type="button" id="my-ele1">me1</button>
<br>
<button type="button" id="my-ele2">me2</button>
When subscribing to Http Observable objects most tutorials use arrow functions :
this.myService.getItems.subscribe(
(data) => // do something,
(errors) => //handle errors);
Why don't use function variables instead to have cleaner code :
this.myService.getItems.subscribe(this.extractData.bind(this), this.handleErrors.bind(this));
It depends on your style. Using (data) => { do something} looks a bit confuse first time, but the more you use it, the more you are comfortable. You'll like it and don't want to use this.extractData.bind(this)
This is my current code:
var PermissionsChecker = {};
PermissionsChecker.check = function(id) {
PermissionsChecker.getPermissions(id);
}
PermissionsChecker.getPermissions = function(id) {
// do stuff
}
Two questions:
Is this the right way to construct node.js functions?
Is that line in .check the correct way to refer to a sibling function?
Thanks!
It's perfectly fine. Some notes:
Sibling function isn't really any standard term for methods of the same object. Minor note, but could cause confusion.
When a function is called as a method on some object, then the value of this inside that function refers to the object on which it was called. That is, calling check like this:
PermissionsChecker.check()
...allows you to write the function like this:
PermissionsChecker.check = function(id) {
this.getPermissions(id);
}
...which is more succinct and probably more common.
Nothing about your question is specific to node.js. This applies to JavaScript in the browser (or anywhere else), too.
You could save some typing by rewriting your example like this:
var PermissionsChecker = {
check: function(id) {
this.getPermissions(id);
},
getPermissions: function(id) {
// do stuff
}
};
So long as the function is called with PermissionsChecker.check(), you can refer to the object with this.
CodePad.
What you've done above is called an object literal, but you could choose the prototypal way also (when you need to instantiate objects - OOP stuff).
You can call this inside to refer to another object property:
PermissionsChecker.check = function(id) {
this.getPermissions(id);
}