The code below works, but my gut tells me this isn't the most succinct way to do this. I'd like to use this.function2() instead of videoControler.function2(), but that doesn't work. Is this the best way to write this?
const myController = {
function1() {
return res.json({
blah: myController.function2()
})
},
function2() {
return "blah"
}
}
Definitely check out #Teemu's link in the comment but another way to handle this is by using classes.
For instance:
class myController {
constructor(type) {
this.controllerType = type;
}
function1(x) {
return res.json({
blah: this.function2()
});
}
function2(x) {
return "blah";
}
}
And this would follow the properties of OOP where you can instantiate a new myController("video") object and invoke functions belonging to the class, outside the class as well.
In your example, replacing myController to this will point to currect scope, so it will not work. You should bind function1 to myController, and create reference to this outside the return state object, like const self = this;
Related
Is there a way to make a function that is being called with no parameters ? for example, I have this class
export class Student {
constructor(ssn) {
this.SSN = ssn;
}
SocialSecurityNumber() {
return this.SSN;
}
}
I want to be able to do this:
let student = new Student(123456);
console.log(student.SocialSecurityNumber);
this doesnt work now, but is there a syntax that I can use to accomplish this ?
Just to add that an alternative to calling the function with parenthesis student.socialSecurityNumber(), you could make this a getter:
class Student {
constructor(ssn) {
this.SSN = ssn;
}
get socialSecurityNumber() {
return this.SSN;
}
}
const student = new Student(123456);
console.log(student.socialSecurityNumber);
That way you could call it with the same syntax as a property.
If you are supporting Object methods, you can add object properties similar to the syntactic sugar you'd see in C#.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty
Basically,
Object.defineProperty(this,
'SocialSecurityNumber',
{
get: function() { return this.SocialSecurityNumber(); }
}
inside your constructor
I'm registering the "$routeChangeSuccessEvent" from Angularjs by setting the callback function. When the event is raised I can not access my controllers instance by "this". The current this instance is unedfined.
My complete TypeScript Code:
export class Ctlr {
static $inject = ["$rootScope","$route"];
constructor(private $scope: ng.IRootScopeService) {
this.Scope = $scope;
this.Title = "";
//this.Scope.$on("$routeChangeSuccessEvent", this.onRouteChangeStart);
this.RegisterEvents();
}
private RegisterEvents(): void {
this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
//this is undefined
console.log(this);
});
}
public Scope: ng.IScope;
public Title: string;
public onRouteChangeStart(event: ng.IAngularEvent, args: any) {
//this is undefined
this.Title = args.$$route.name);
}
}
}
I'm able to get access of the Title property with:
private RegisterEvents(): void {
var ref = this.Title;
this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
ref = args.$$route.name;
});
}
But that's not a real solution because angularJS doesn't update its view. It seems that I didn't catch the right reference. If thats not possible the whole angularjs events seems to be not useabel - that can't be possible?
I also didn't find any topic about this strange behavior. Is there a solution for this issue?
The scope changes when a callback is fired, that is why this becomes undefined.
Your other example of doing:
var ref = this.Title;
Actually just creates a -copy- of Title as it is a primitive type (string). Which is why it didn't work either. Updating ref does not update this.Title.
The usual solution to this, is to start the definition as:
var vm = this;
...
private RegisterEvents(): void {
this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
//this is undefined
console.log(vm);
});
}
So rather than using this everywhere, you would use vm. Note that vm can be named whatever you want. The important part is you capture a reference to this in a scope where this is what you want to use in a callback. This works because this is not a primitive type, as it is an object and rather than taking a copy, it takes a reference.
Your other option is to use bind which you can apply to any function, this function essentially tells JavaScript what this will equate to. E.g.
$scope.$on("SomeEventHere", someCallbackFunction.bind(this));
It's a matter of preference which you use here but generally I see people using the var something = this; method.
That's because this always refers to it's parent which is now the function. So if you wanted you could do this:
private RegisterEvents(): void {
var ref = this;
this.Scope.$on("$routeChangeSuccessEvent",(event: ng.IAngularEvent, args: any) => {
console.log(ref);
});
}
you can rebind the this variable:
this.Scope.$on("$routeChangeSuccessEvent",this.onRouteChangeStart.bind(this));
As noted in other solutions, and using at least TypeScript v1.7, you can use this using a fat arrow like:
$scope.$on('some-event', () => { console.log('here `this` is not undefined'); });
$scope.$watch('foo.bar', (a,b) => { console.log('here too...'); }
$scope.$on('$routeChangeSuccessEvent', () => { console.log('here too...'); });
But, if you want to pass a reference to a function from the same class you have to use the .bind(this) notation:
$cope.$on('$routeChangeSuccessEvent', this.onRouteChangeStart.bind(this));
I have this typescript code:
module MyPage {
export class MyVm {
ToDo : string;
Load() {
//can access todo here by using this:
this.ToDo = "test";
$.get("GetUrl", function (servertodos) {
//but how do I get to Todo here??
this.ToDo(servertodos); //WRONG ToDo..
});
}
}
}
The question is, how do I access the todo member field in the $.get callback?
TypeScript also supports arrow function that preserve lexical scoping. Arrow functions result in similar code to Jakub's example but are neater as you don't need to create the variable and adjust usage yourself:
Here is the example using an arrow function:
$.get("GetUrl", (todos) => {
this.ToDo(todos);
});
The same way you do it in javascript
export class MyVm {
ToDo : string;
Load() {
//can access todo here by using this:
this.ToDo = "test";
var me = this;
$.get("GetUrl", function (todos) {
//but how do I get to Todo here??
me.ToDo(todos); //WRONG ToDo..
});
}
}
Fenton is right.
But you can also do this:
mycallback(todos, self) { self.todo(todos)); }
$.get('url', mycallback(todos, this));
I'm writing a JavaScript library in which I want some methods and properties public and other private. The following seems a great way of doing this whilst wrapping everything up into a single object.
(function (window) {
var Thing = function() {
// private var
var variable = "value";
return {
// public method
method:function() {
alert(variable);
}
}
}();
window.Thing = Thing;
})(window);
Thing.method();
Which is great. (Mostly grabbed from here).
However, I'd still like to be able to use the constructor of Thing to pass in some arguments.
Is there anyway I can provide a constructor in the return statement, or use prototype to override the constructor? So I can call:
Thing(stuff);
Right now, if I try that it causes:
Uncaught TypeError: Property 'Thing' of object [object DOMWindow] is not a function
Which makes sense as it's not returning itself, but ideally it'd be possible to call a constructor.
OR, is this just baaaad and I should steer clear of some or all of this?
To accomplish what you are asking, do something like this:
(function (window) {
var thingMaker= function(stuff) {
// private var
var variable = "value";
return {
// public method
method:function() {
alert(variable);
}
alertStuff:function() {
alert(stuff);
}
}
};
window.thingMaker= thingMaker;
})(window);
var myThing = window.thingMaker(stuff);
myThing.alertStuff()
More information can be found by searching the googlenets for Douglas Crockford. Some great and very informative videos by him are available on yui theater. But I would have to ask, why create another framework when there are already so many great ones out there (jquery,prototype,yui,dojo to name a few)
Thing is already created, so you are always going to be too late to call a 'constructor'.
You could pass variables in like this:
(function (window, var1, var2) {
var Thing = function() {
// private var
var variable = "value";
return {
// public method
method:function() {
alert(variable);
}
}
}();
window.Thing = Thing;
})(window, var1, var2);
Thing is an Object with one method called method:
{
// public method
method:function() {
alert(variable);
}
}
Thing.method(); // alerts "value"
You could return instead:
function () {
alert(arguments)
}
Then
Thing(6,5,4); // alerts 6,5,4
I'm new to javascript namespaces, and I found myself kinda deep within a namespace, but unable to find a way to navigate from within the namespace to another object in the same general namespace. It's best described by the code below:
$.fileUploading = {
images: {
settings: {
// How do you do this?
bing_bong: find.a.way.to.functionOne
},
functionOne: function() { return "Rock!"; }
}
}
Is there a way to do that?
Because namespaces are just properties on objects, there's no way to find out what object a property belongs to, from the property. A simple reason is that an identical property can appear in multiple objects.
Namespaces are supposed to be stable and constant, so there's nothing wrong with referencing the entire thing. However, if you need to access the same names a ton of times, you could make it a bit easier for yourself by assigning it to a variable.
var my_ns = $.fileUploading;
This would work:
$.fileUploading = {
images: {
settings: {},
functionOne: function() { return "Rock!"; }
}
};
$.fileUploading.images.settings.bing_bong = $.fileUploading.images.functionOne;
This also:
function f() { return "Rock!"; }
$.fileUploading = {
images: {
settings: {
// How do you do this?
bing_bong: f
},
functionOne: f
}
};
(function(){
var yourNameSpace={
publicProp1:publicFn1,
publicProp2:publicFn2,
publicProp3:publicFn3
};
window.yourNameSpace = yourNameSpace;
//private variable
var _privateVar1,_privateVar2,_privateVar3;
//privatefns
function _privateFn1(){}
function _privateFn2(){}
function _privateFn3(){}
function _privateFn4(){}
//public functions can access private fns
function publicFn1(){}
function publicFn2(){}
function publicFn3(){}
}(undefined);