|
|
Why not have a default context of "this" inside instance methods, like C#?
Seems to me it would be easy enough to allow this while still making "call(x, y, z)" render as "this.call(this.x, this.y, this.z)".
|
|
|
Coordinator
Jan 11 at 11:42 PM
|
There have been a few feature requests around this.
The short answer is that, while this aspect is no doubt a little verbose, our class syntax tries to align very closely with the ES6 proposal for classes, which currently requires explicit "this." for member accesses.
|
|
|
Developer
Jan 12 at 4:29 PM
|
Also, a real problem is that an implicit 'this' would in some cases change the meaning of the code. For example:
var x = 10;
class Foo {
x = 20;
f() {
console.log(x);
}
}
var foo = new Foo();
foo.f();
In ES6 this is supposed to output '10', but it would output '20' with an implicit 'this'. We would basically break perfectly valid ES6 code!
Anders
|
|
|
|
|
I get this but for people like me that only does TS programming (and C#), this wouldn’t matter, I would love to have a switch in the compiler that would enable ‘implicit this”.
Another related issue is the lack of nested block scope as in C#, it's somewhat frustrating that you cannot use blocks to introduce new variable like below, any chance support for this could be added as a switch to the compiler?
{
From: ahejlsberg
Sent: January 12, 2013 9:30 AM
To: bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: ahejlsberg
Also, a real problem is that an implicit 'this' would in some cases change the meaning of the code. For example:
var x = 10;
class Foo {
x = 20;
f() {
console.log(x);
}
}
var foo = new Foo();
foo.f();
In ES6 this is supposed to output '10', but it would output '20' with an implicit 'this'. We would basically break perfectly valid ES6 code!
Anders
|
|
|
|
|
Sorry I’m not really used to the new Mail app in W8...
I was adding the sample code below when Mail “decided” it was time to send the message.
{
{
var x = new Foo();
}
{
var x = new Bar(); // x is not redefined, i.e. declared as of type Foo;
}
From: ahejlsberg
Sent: January 12, 2013 9:30 AM
To: bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: ahejlsberg
Also, a real problem is that an implicit 'this' would in some cases change the meaning of the code. For example:
var x = 10;
class Foo {
x = 20;
f() {
console.log(x);
}
}
var foo = new Foo();
foo.f();
In ES6 this is supposed to output '10', but it would output '20' with an implicit 'this'. We would basically break perfectly valid ES6 code!
Anders
|
|
|
|
|
Anders,
The issue you mentioned seems to be solved by the same context rules already applied today even in javascript. If there is a local variable defined, you use that, otherwise use the one from the parent closure. In the end, the compiler would follow exactly
the same rules that are applied to C# compiler.
The only issue I see is that if you want to access the global variable instead of the instance one. C# has qualified names for everything, JS doesn't. But this seems to be simple to solve by not creating a local or instance variable with the same name of
a global one that you want to use. Optionally, there could be a "global::x" that would look for a defined global outside of the scope and compile without the "this".
I really believe this would make coding much better than using "this" for everything.
jonturner,
I understand the will to make TypeScript compatible with current ES and ES6, but I don't believe that all TypeScript is supposed to be is a bridge between today and tomorrow. Otherwise, when ES6 is available in all browsers, there will be no reason to use
TS other than type checks. As Bjorn said, this could be a switch in the compiler, or an option similar to "use strict". I really hope you don't plan for TS to be only a temporary ES6.
|
|
|
|
|
First people ask to skip 'this.' then they ask to mandate underscore or m_ prefixes for the same.
|
|
|
|
|
ES6 is still a dynamic language, there are no proposals to add static typing or type-checking in JavaScript, and that is the goodness that TypeScript is bringing. When the time comes that targeting ES6 is viable and the TypeScript compiler simply
passes over the class declarations, there will still be plenty of other things for it to do.
On Sat, Jan 12, 2013 at 11:41 PM, nvivo <notifications@codeplex.com> wrote:
From: nvivo
Anders,
The issue you mentioned seems to be solved by the same context rules already applied today even in javascript. If there is a local variable defined, you use that, otherwise use the one from the parent closure. In the end, the compiler would follow exactly
the same rules that are applied to C# compiler.
The only issue I see is that if you want to access the global variable instead of the instance one. C# has qualified names for everything, JS doesn't. But this seems to be simple to solve by not creating a local or instance variable with the same name of
a global one that you want to use. Optionally, there could be a "global::x" that would look for a defined global outside of the scope and compile without the "this".
I really believe this would make coding much better than using "this" for everything.
jonturner,
I understand the will to make TypeScript compatible with current ES and ES6, but I don't believe that all TypeScript is supposed to be is a bridge between today and tomorrow. Otherwise, when ES6 is available in all browsers, there will be no reason to use
TS other than type checks. As Bjorn said, this could be a switch in the compiler, or an option similar to "use strict". I really hope you don't plan for TS to be only a temporary ES6.
|
|
|
|
|
How many compiler switches do you want!?
On Sat, Jan 12, 2013 at 7:07 PM, BjornBacklund <notifications@codeplex.com> wrote:
From: BjornBacklund
I get this but for people like me that only does TS programming (and C#), this wouldn’t matter, I would love to have a switch in the compiler that would enable ‘implicit this”.
Another related issue is the lack of nested block scope as in C#, it's somewhat frustrating that you cannot use blocks to introduce new variable like below, any chance support for this could be added as a switch to the compiler?
{
From: ahejlsberg
Sent: January 12, 2013 9:30 AM
To: bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: ahejlsberg
Also, a real problem is that an implicit 'this' would in some cases change the meaning of the code. For example:
var x = 10;
class Foo {
x = 20;
f() {
console.log(x);
}
}
var foo = new Foo();
foo.f();
In ES6 this is supposed to output '10', but it would output '20' with an implicit 'this'. We would basically break perfectly valid ES6 code!
Anders
|
|
|
|
|
One switch to turn TS more into C# would be sufficient
😊
Honestly, I’m working on a larger project with TS for the UI and C# for the backend and it would be great to be able to use the same style of programming in both worlds. TS is so much better than JS but it could be made even better if the “ES6 alignment
goal” would be dropped (or overridden by aforementioned switch)
---bjorn
From: markrendle
Sent: January 13, 2013 7:21 AM
To: bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: markrendle
How many compiler switches do you want!?
On Sat, Jan 12, 2013 at 7:07 PM, BjornBacklund <notifications@codeplex.com> wrote:
From: BjornBacklund
I get this but for people like me that only does TS programming (and C#), this wouldn’t matter, I would love to have a switch in the compiler that would enable ‘implicit this”.
Another related issue is the lack of nested block scope as in C#, it's somewhat frustrating that you cannot use blocks to introduce new variable like below, any chance support for this could be added as a switch to the compiler?
{
From: ahejlsberg
Sent: January 12, 2013 9:30 AM
To:
bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: ahejlsberg
Also, a real problem is that an implicit 'this' would in some cases change the meaning of the code. For example:
var x = 10;
class Foo {
x = 20;
f() {
console.log(x);
}
}
var foo = new Foo();
foo.f();
In ES6 this is supposed to output '10', but it would output '20' with an implicit 'this'. We would basically break perfectly valid ES6 code!
Anders
|
|
|
|
|
On Sun, Jan 13, 2013 at 4:32 PM, BjornBacklund <notifications@codeplex.com> wrote:
From: BjornBacklund
One switch to turn TS more into C# would be sufficient 😊
Honestly, I’m working on a larger project with TS for the UI and C# for the backend and it would be great to be able to use the same style of programming in both worlds. TS is so much better than JS but it could be made even better if the “ES6 alignment
goal” would be dropped (or overridden by aforementioned switch)
---bjorn
From: markrendle
Sent: January 13, 2013 7:21 AM
To: bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: markrendle
How many compiler switches do you want!?
On Sat, Jan 12, 2013 at 7:07 PM, BjornBacklund <notifications@codeplex.com> wrote:
From: BjornBacklund
I get this but for people like me that only does TS programming (and C#), this wouldn’t matter, I would love to have a switch in the compiler that would enable ‘implicit this”.
Another related issue is the lack of nested block scope as in C#, it's somewhat frustrating that you cannot use blocks to introduce new variable like below, any chance support for this could be added as a switch to the compiler?
{
From: ahejlsberg
Sent: January 12, 2013 9:30 AM
To: bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: ahejlsberg
Also, a real problem is that an implicit 'this' would in some cases change the meaning of the code. For example:
var x = 10;
class Foo {
x = 20;
f() {
console.log(x);
}
}
var foo = new Foo();
foo.f();
In ES6 this is supposed to output '10', but it would output '20' with an implicit 'this'. We would basically break perfectly valid ES6 code!
Anders
|
|
|
|
|
Yes looked at Script# but I don’t want to bet on something not backed by a larger player (such as MS in this case).
From: markrendle
Sent: January 13, 2013 10:00 AM
To: bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: markrendle
On Sun, Jan 13, 2013 at 4:32 PM, BjornBacklund <notifications@codeplex.com> wrote:
From: BjornBacklund
One switch to turn TS more into C# would be sufficient 😊
Honestly, I’m working on a larger project with TS for the UI and C# for the backend and it would be great to be able to use the same style of programming in both worlds. TS is so much better than JS but it could be made even better if the “ES6 alignment
goal” would be dropped (or overridden by aforementioned switch)
---bjorn
From: markrendle
Sent: January 13, 2013 7:21 AM
To:
bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: markrendle
How many compiler switches do you want!?
On Sat, Jan 12, 2013 at 7:07 PM, BjornBacklund <notifications@codeplex.com> wrote:
From: BjornBacklund
I get this but for people like me that only does TS programming (and C#), this wouldn’t matter, I would love to have a switch in the compiler that would enable ‘implicit this”.
Another related issue is the lack of nested block scope as in C#, it's somewhat frustrating that you cannot use blocks to introduce new variable like below, any chance support for this could be added as a switch to the compiler?
{
From: ahejlsberg
Sent: January 12, 2013 9:30 AM
To:
bjorn@backlund.org
Subject: Re: Make "this" the default context inside classes [typescript:429350]
From: ahejlsberg
Also, a real problem is that an implicit 'this' would in some cases change the meaning of the code. For example:
var x = 10;
class Foo {
x = 20;
f() {
console.log(x);
}
}
var foo = new Foo();
foo.f();
In ES6 this is supposed to output '10', but it would output '20' with an implicit 'this'. We would basically break perfectly valid ES6 code!
Anders
|
|
|
|
|
Just some wild idea, how about allowing lambda like function declaration within a class where this would be the default context (of course this would not be 100% aligned with the ES6 proposal, but who knows they are willing to include it ;). So in the above
example:
var x = 10;
class Foo {
x = 20;
f() {
console.log(x); // prints 10
}
g() => {
console.log(x); // prints 20
}
}
var foo = new Foo();
foo.f();
// Peter
|
|
|
|
|
Coffeescript provides a shorthand for this.foo in the form @foo, but my vote is for implicit this, if I do manage to shadow a member inside a class, which is pretty rare, its a simple matter to change it. Having to constantly think about 'this' in classes and have every single member access qualified is a real pain point.
|
|
|
|
|
What if in this case TS compiler would generate an error message about ambiguous expression, so the programmer would specify "this" explicitly (only) in this case?
I think that "this." - polluted code will cause serious programmer productivity slowdown and will scare-off many newcomer programmers.
Thank you.
ahejlsberg wrote:
Also, a real problem is that an implicit 'this' would in some cases change the meaning of the code. For example: var x = 10; class Foo { x = 20; f() { console.log(x); } } var foo = new Foo(); foo.f(); In ES6 this is supposed to output '10', but it would output '20' with an implicit 'this'. We would basically break perfectly valid ES6 code! Anders
|
|
|
Mar 6 at 9:35 AM
Edited Mar 6 at 10:30 AM
|
As a C# Programmer, even I am beginning to tire of these "make it more like C#" requests.
There is plenty of things still to desire from TS, but making it more like C# is not one of them.
It is true that you trip up every now and then when your use to that world, but the more this stay true to JavaScript and ECMA6, the better in my mind and Anders and his team is doing a great job at this in my mind.
And as Anders says, this would break working code... Although odd code maybe.
var greet = "Global says Hello to";
module mod {
var greet = "Module says Hello to";
export class cls {
//var greet = "Class says Hello to";
name: string;
greet = "Class says Hello to"; //This is not the thing being used.
constructor(name: string) {
this.name = name;
}
speak() {
return greet + " " + this.name;
}
}
}
var x = new mod.cls("Anders");
$("#msg").html(x.speak());
One thing about the above though, we allow to define scoped variables up until classes, outside of typescript this would work:
var greet = "Global says Hello to";
var mod;
(function (mod) {
var greet = "Module says Hello to";
var cls = (function () {
var greet = "Class says Hello to";
function cls(name) {
this.name = name;
};
cls.prototype.speak = function (element) {
return greet + " " +this.name;
};
return cls;
})();
mod.cls = cls;
})(mod || (mod = {}));
var x = new mod.cls("Anders");
$("#msg").html(x.speak());
http://jsfiddle.net/bCNzN/1/
So maybe the ability to defined scoped variables inside "classes" is missing and maybe we should allow for that like so:
class cls {
var scoped_var = "scoped variable";
public pub_var = "public variable";
private pri_var = "Private in TS, but still public variable";
}
}
var x = new mod.cls("Anders");
$("#msg").html(x.speak());
Not sure if that would have any implications.
In any case, that is a very different subject to the one this thread is about.
|
|
|
|
|
I agree. The ES6 compatibility pledge is one of the things that gives TypeScript credibility in the non-MS world. I'm far happier knowing that the team are hard at work on generics, and hoping that a 1.0 release will follow shortly after they release
that feature.
On 6 Mar 2013 10:35, "jmelgaard" < notifications@codeplex.com> wrote:
From: jmelgaard
As a C# Programmer, even I am beginning to tire of these "make it more like C#" requests.
There is plenty of things still to desire from TS, but making it more like C# is not one of them.
It is true that you trip up every now and then when your use to that world, but the more this stay true to JavaScript and ECMA6, the better in my mind and Anders and his team is doing a great job at this in my mind.
And as Anders says, this would break working code... e.g.
var greet = "Global says Hello to";
module mod {
var greet = "Module says Hello to";
export class cls {
//var greet = "Class says Hello to";
name: string;
constructor(name: string) {
this.name = name;
}
speak() {
return greet + " " + this.name;
}
}
}
var x = new mod.cls("Anders");
$("#msg").html(x.speak());
One thing about the above though, we allow to define scoped variables up until classes, outside of typescript this would work:
var greet = "Global says Hello to";
var mod;
(function (mod) {
var greet = "Module says Hello to";
var cls = (function () {
var greet = "Class says Hello to";
function cls(name) {
this.name = name;
};
cls.prototype.speak = function (element) {
return greet + " " +this.name;
};
return cls;
})();
mod.cls = cls;
})(mod || (mod = {}));
var x = new mod.cls("Anders");
$("#msg").html(x.speak());
http://jsfiddle.net/bCNzN/1/
So maybe the ability to defined scoped variables inside "classes" is missing, but that is in my mind a very different subject to the one this thread is about.
|
|
|
|
|
I agree it is minorly burdensome to write this all over the place, but on the other hand, TS is not C# and as Anders illustrated, it's very clear why it's necessary. Modules in TS are closer to static classes in C# than they are to namespaces. The fact that modules, and indeed, the global scope, can contain variables and functions makes some kind of qualification for class members necessary.
If anything, I'd support a shortcut @ to access member variables/functions, though this seems pretty low priority on a wish list of features.
|
|
|
|
|
I vote for explicitly forcing developers to type "this" . It forces us to be responsible in how we code our scopes!.
I've been slowly building my own UI framework on top of TypeScript, and as painful as it is to keep writing "this. " its forcing me to think about the scope within my functions/methods/classes/modules etc.
|
|
|
|
|
Hello, Anders and everybody!
Stop, stop, stop! This is TypeScript or not TYPE Script? And what type this is? Who knows?
We BADLY need to bind this keyword to object context somehow. ECMAScript was ugly bastard (as well as ECMAScript 6) and we do not want another peace of s... but just strongly typed. Every JavaScript developer sooner or later makes this hack:
function MyClass() {
var _this = this;
...
}
Every one and every time.
If you do not want to break existing behavior yo can use another keyword: 'me', 'self', '@', '@this' or bind with alternative syntax: method() =>{ ... }. You know it. But please DO SOMETHING or TypeScript will fail against CoffeeScript. We need syntax sugar.
Thanks.
|
|
|
|
|
I will vote for explicit this keyword.
As a functional programming language ECMAScript, the class SHOULD NOT be the most important thing. This in ECMASCRIPT make a lot thing dynamic and convinent. For example, if I want to make some function general for all of class, everything I shou do is just create a function, and use it like
Func.call( someObj )
And the this in the function will be the someObj.
For the method in a class, it's shoule be a same FUNCTION. Anyhow the TypeScript is a syntax sugar of ECMAScript, not another language like c# or coffee script etc.
|
|
|
Apr 11 at 2:36 PM
Edited Apr 11 at 2:40 PM
|
I would LOVE to see something like @this or self to exist, or some way of not having to shoe horn almost all my code into the constructor which is AWFUL (imo). As I currently make heavy use of event systems to relay messages throughout the systems and lawnchair, knockout, jquery etc they all swap and change the this context. In the case of lawnchair there was no nice solution to the problem:
http://stackoverflow.com/questions/15679838/using-lawnchair-with-typescript
As some of my view models are pretty big, even after they have been broken up into smaller components it is horrible to look at the constructor having reams of code in it, and then there is the documentation comments put on above to generate the documentation for plugin developers to use. It just ends up looking like a huge mess.
Currently for me Typescript has worse this handling than raw JS only because it stills allows the overwriting of the keywords scope but also forces you to use this as a prefix for calling any class methods. So you are unable to use the old JS trick of:
function SomeClass()
{
var self = this;
this.AlertSomething = function(something) { alert(something); };
this.SomeCallbackWithScopedThis = function() { self.AlertSomething(this); }
}
As the same example in typescript would not work, as shown here:
class SomeClass
{
private self: any;
constructor() { this.self = this; }
public AlertSomething = function(something) { alert(something); };
public SomeCallbackWithScopedThis = function() { this.self.AlertSomething(this); } // you need the this prefix making it pointless
}
So it is like Typescript is forcing you to write your code with the this always meaning the context of the class when you want to invoke its methods, but also allowing others to play with the this scope so you can NEVER be sure as to where your methods are being invoked from and what scope has been tampered with, as even our simple methods which do business logic and never touch the UI may be triggered from an ajax callback which was triggered from a UI event which ends up invoking with an altered scope.
If you could at least have lambda style class level methods to have a locally inferred this it would solve a huge amount of these problems, but for me it seems like the current implementation is too unstable for serious development of large UI projects... and yes I know I could put it all in the constructor, but that to me is a work around, not a solution.
== Edit ==
Just to be clear I am not really for having the default scope of this being the current class instance, I think it should be left as it is in JS. I am however for another means to access the current instance or at least cache it for usage... just some way of being able to guarentee the context of the instance OUTSIDE of the constructor.
|
|
|
|
|
I like that TypeScript is basically just JavaScript (or ECMAScript 6) with type extensions. Changing the way "this" works would break that distinction. Then TypeScript would be some other language like AS3. If you want that kind of functionality, might as well use one of those (Jangaroo and FalconJx can compile AS3 to JS if you want!).
That said, maybe we can at least get the coffeescriptesque @ operator to cut down on some of the typing? this.prop would become @prop. Clean and simple.
Also, you should never have to shoehorn everything into a constructor. I've seen that a couple of times on these forums (and I'm not here often). You can use a local reference in the current scope chain and method.call (the way vanilla JS users do it) or you can use the "arrow function" syntax (aka the "fat arrow") which basically sets that up for you. It's cleaner than stuffing everything into a constructor.
|
|
|
|
|
@CaptainN Could you please show me some examples of what you mean in the latter paragraph? I know that the lambda style methods should set the this scope correctly, however I am unable to define my methods using that mechanism as it tells me that the this keyword cannot be used in that context i.e:
class SomeClass
{
private SomeObject: any;
public SomeCallbackMethod = (result) => { this.SomeObject.InvokeSomething(result); }
}
Not sure what you mean by the method.call way, but if you could post examples of what you mean in both cases it would be very helpful to me and im sure others, as there is VERY LITTLE useful information on the ways to access this correctly outside of the constructor and guarantee the scope would be fine regardless of where it is invoked from.
I have an SO question along these lines (Although not 100% relevant), which I would be happy to upvote if you put the examples in.
http://stackoverflow.com/questions/15925500/issue-with-child-scoping-of-this-in-typescript
|
|