Javascript ES6消除了类中各处使用“this”关键字

5anewei6  于 2023-01-08  发布在  Java
关注(0)|答案(5)|浏览(116)

我现在使用Traceur来编写一些未来的javascript,这是我在某个类中的一个函数

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;
}

当然,与任何传统的javascript代码一样,它到处都覆盖着this关键字,来自Java之类的语言,对我来说,在引用类内部的字段时指定这个关键字是非常不自然的,而我并不需要这样做。
有没有办法让Traceur像Java一样解释类呢?(例如,在没有指定时自动插入,等等)

iih3973s

iih3973s1#

阿法克,不。
在Java、C#、C++等中,这是编译器的一个特性,而不是执行。这意味着它是隐式完成的,编译器所做的是将正确的地址放入this并以正确的方式引用变量。大多数编译器中有一个规则,即如果您有一个同名的局部变量(在局部范围内),则它优先于成员变量。
在javascript中,你可以很容易地用call替换thisapplybind,并在作者不打算使用的对象上调用函数(例如,this可能是一个具有不同结构的对象)。我认为这就是为什么语言语法要求您始终显式指定是否"重新引用范围或this
javascript函数体中的more实际上可以读取全局作用域,因此如果不使用显式的this,定义window.member(如果在浏览器中)可能会改变函数的行为

jexiocij

jexiocij2#

据我所知,ES6中没有这样的功能。
由于Javascript允许引用父作用域中的变量,这类特性会变得复杂,因此,它必须以某种方式辨别是否有如下代码行:

ticks = 0;

手段

this.ticks = 0;

或者它是否意味着通过名称ticks引用当前或父作用域中的变量。
仅仅是给对象添加一个属性,就会在属性引用和同名的局部变量或父作用域变量之间产生冲突,从而使之前运行良好的代码变得混乱。这可能会很混乱。现在,你不得不为局部变量命名作用域,以避免与属性名发生冲突。而且,如果你不得不为局部变量命名作用域,你刚刚重新引入了一段你想去掉的语法。
Java可以容忍这一点,因为编译器事先知道,所有属性名称,以便在发生冲突时报告错误。Javascript允许动态添加属性(随时添加),因此解析器在解析时并不知道哪些属性名将出现在或不出现在任何给定对象上,因此无法警告冲突。编译和工作,并因此导致表达代码时的一些不同的能力或要求。
可以使用with结构来避免某些类型,但由于此处详细说明的原因,with将从Javascript中删除(严格模式下不允许),而不是增强,因此不推荐使用此方法。

ar7v8xwq

ar7v8xwq3#

如果您希望在构造函数中(或任何地方)赋值示例变量时避免输入this,可以使用_.extend()

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

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

kcwpcxri4#

作为一个简单的例子,你可以预处理你的类,为一组预定义的属性名插入this.,例如,通过为每个类定制静态 meta配置,这对gulp构建文件是可用的。

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

从指定的属性名,现在我构造一个正则表达式来预处理类。这是非常脆弱的,因为它不是基于令牌的。稍后,我想尝试通过AST上的巴别塔转换器做一些类似的事情。

mwg9r5ms

mwg9r5ms5#

许多人建议使用函数代替类(在我的例子中放在模块中)来避免this关键字,但是这样你就必须在每个属性前面使用function关键字以及letvar,所以你必须决定你最喜欢哪一个。

export function createPerson {
  var name;

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

  function doStuff() {
    //...
  }

  return {
    setName, doStuff
  }
}

由于你还必须返回你想要的函数,以达到“示例”,它可能会感觉更混乱的整体超过一个类。而且,由于你不使用这个关键字,你将不得不使用不同的名称为参数比你的属性。许多人喜欢这样,然后,因为它是明确的,你是指什么,它是不太可能的,你会指错属性或函数。

相关问题