最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

ecmascript 6 - Javascript ES6 eliminate usage of 'this' keyword everywhere in classes - Stack Overflow

programmeradmin0浏览0评论

I am using Traceur to be able to write some javascript of the future right now and this is a function that I have in some class

create() {
    this.game.physics.startSystem(Phaser.Physics.ARCADE);

    this.segmentcache = new SegmentCache(this.game);
    this.segments = new Segments(this.game);
    this.segments.cache = this.segmentcache;
    this.segments.seek(3);

    this.guy = new Guy(this.game, 140 + 8, 80);
    this.guy.anchor.set(0.5, 1.0);
    this.game.add.existing(this.guy);

    this.game.camera.x = 100;
    this.ticks = 0;
    this.cross = 0;
}

Of course, as with any traditional javascript code, it is covered with the this keyword all over the place. Coming from Java and the likes, it is very unnatural for me to have to specify this when referring to a field inside of a class when I don't have to.

Is there any way of getting Traceur to interpret classes the same way as Java? (i.e auto insert this when not specified, etc.)

I am using Traceur to be able to write some javascript of the future right now and this is a function that I have in some class

create() {
    this.game.physics.startSystem(Phaser.Physics.ARCADE);

    this.segmentcache = new SegmentCache(this.game);
    this.segments = new Segments(this.game);
    this.segments.cache = this.segmentcache;
    this.segments.seek(3);

    this.guy = new Guy(this.game, 140 + 8, 80);
    this.guy.anchor.set(0.5, 1.0);
    this.game.add.existing(this.guy);

    this.game.camera.x = 100;
    this.ticks = 0;
    this.cross = 0;
}

Of course, as with any traditional javascript code, it is covered with the this keyword all over the place. Coming from Java and the likes, it is very unnatural for me to have to specify this when referring to a field inside of a class when I don't have to.

Is there any way of getting Traceur to interpret classes the same way as Java? (i.e auto insert this when not specified, etc.)

Share Improve this question edited Mar 20, 2015 at 0:58 Felix Kling 817k181 gold badges1.1k silver badges1.2k bronze badges asked Mar 20, 2015 at 0:45 Nicolas MartelNicolas Martel 1,7213 gold badges21 silver badges34 bronze badges 6
  • 1 That would not be valid JavaScript anymore. Traceur does not define a new language, it sticks to the ES6 spec. I don't think you are approaching this correctly. If you want to write JavaScript than do that, and don't try to treat it like Java (because it's very different anyway). For me it's exactly the other way round: I find it very confusing that you don't have to specify this in Java. I find this "implicitness" makes it more difficult to follow the code. – Felix Kling Commented Mar 20, 2015 at 0:56
  • 3 function() { with(this) { ... } } ;) – Jeremy Banks Commented Mar 20, 2015 at 0:59
  • 1 @JeremyBanks - I almost missed the winky at the end. Would serve him right though. – barry-johnson Commented Mar 20, 2015 at 1:01
  • More seriously: this is probably not possible to implement efficiently in a language as dynamic as JavaScript. It might be possible to implement in the 'SoundScript' subset that is being proposed, but that's several steps beyond ES6. Maybe one day. – Jeremy Banks Commented Mar 20, 2015 at 1:01
  • 2 I don't believe it would be a good idea. If you want to write Java, write Java. Perhaps pile it down to Javascript. But don't force the language to be something it isn't. – Ross Presser Commented Mar 20, 2015 at 1:01
 |  Show 1 more ment

5 Answers 5

Reset to default 4

AFAIK, no.

In Java, C#, C++, etc. this is a feature of piler, not execution. This means it is done implicitly and what the piler does is putting correct address into this and referencing variables in a correct way. There is a rule in most pilers that if you have a local variable (in local scope) with same name it has precedence of member variables.

While in javascript you can easily substitute this via call, apply or bind and have your function being called over an object which the author didn't intend to work with (i.e. this may be an object with different structure). And I think this is the reason why the language syntax requires from you to always explicitly specify if you're referring scope or this.

More in javascript function body actually can read global scope, so defining window.member (if in browser) may change the behavior of you functions if you don't use explicit this

As far as I know, there is no such feature in ES6.

This type of feature would be plicated by the fact that Javascript allows referencing variables in the parent scope. So, it would have to somehow discern whether a line of code like:

ticks = 0;

means

this.ticks = 0;

or whether it means to reference a variable in the current or parent scope by the name of ticks.

The mere adding of a property to an object could mess up code that was working just fine before by creating a conflict between a property reference and a local variable or parent scoped variable of the same name. That would likely be a mess. Now, you'd have to name scope your local variables just to avoid ever having a conflict with a property name. And, if you're having to scope local variables, you've just reintroduced an extra piece of syntax that you were trying to get rid of.

Java can tolerate this because the piler knows, in advance, all property names so it can report an error if there is a conflict. Javascript allows dynamically added properties (added at any time) so the parser does not really have any idea what property names will or will not be on any given object at parse time so it can't warn about conflicts. This is just an inherent difference in how the languages parse/pile and work and thus leads to some different capabilities or requirements in expressing the code.

It is possible to use the with structure to avoid some typing, but with is being removed from Javascript (not permitted in strict mode) for reasons detailed here, not enhanced, so not a remended approach.

As an unsophisticated illustration what might be possible, you can preprocess your classes to insert this. for a predefined set of property names, e.g. via custom static meta configuration for each class, that is available to a gulp build file.

DEBUG ClassPreprocessor: buildSync [ 'logger',
  'context',
  'config',
  'startedComponents',
  'ponents',
  'requiredComponents' ] 
regex ([^a-z\.'])(logger|context|config|startedComponents|ponents|requiredComponents)([^a-z:'])
replaceWith $1this.$2$3

where from the specified prop names, for now i'm constructing a regex to preprocess the class. This is terribly fragile though, since it's not token based. Later, I'd like to try something similar via a Babel transformer on the AST.

If you want to avoid having to type this when you're assigning instance variables in the constructor (or anywhere, really), you can use _.extend()

// this, this, this
this.a = true;
this.b = 2;
this.c = "three";

// bees...
_.extend(this, {
  a: true,
  b: 2,
  c: "three"
});

Many remend using a function instead (put inside a module in my example) of class to avoid this keyword, but it then you will have to use function keyword as well as let or var in front of every property. So you will have to decide which one you like best.

export function createPerson {
  var name;

  function setName(nameParam) {
     name = nameParam;
     doStuff();
  }

  function doStuff() {
    //...
  }

  return {
    setName, doStuff
  }
}

Since you also have to return the functions you want to be reachable for the "instance" , it could feel more cluttered in total over a class. Also since you don't use this keyword you would have to use different names for parameters than your properties. Many people prefer this then as it is clear what you are referring to and it is less probable you will refer to the wrong property or function.

发布评论

评论列表(0)

  1. 暂无评论