Typescript和Javascript ES6之间的比较类构造函数参数,ES.NEXT

时间:2018-02-08 17:40:42

标签: javascript class typescript oop ecmascript-6

我一直在研究TypeScript作为Angular2 / 5的要求,我遇到了一些疑问。 几个月前,我还升级了我对JS ES6的了解等等。 我很确定我没有错,但为了全面了解TS我还是会问你。

这是您可以在此处找到的代码:

  

https://www.typescriptlang.org/docs/handbook/classes.html#parameter-properties

{
    class Octopus {
       readonly numberOfLegs: number = 8;
       constructor(readonly classAttr: string) { ... } // name attribute 
    }
    console.log( (new Octopus('spicylemoned')).classAttr ); // It works
}

在最近的JS更新中是否有一种方法可以像在TS中那样在vanilla中定义类'构造函数内的属性? (没有通过this实例隐式分配)

{
    class Test{
        constructor({ passedVar : classAttr } ) { ... };
    };
    console.log( (new Test({ passedVar : 'sweety' })).classAttr ); 
    //it doesnt work
}

3 个答案:

答案 0 :(得分:3)

在JS中没有任何类似的语法。最简单的方法是使用Object.assign()

class Test {
  constructor({ passedVar }) {
    Object.assign(this, { classAttr: passedVar });
  }
}

console.log(new Test({ passedVar: 'sweety' }).classAttr);

如果你有很多属性,这种方式会更好;如果只有一个,您只需分配到thisthis.classAttr = passedVar

答案 1 :(得分:0)

我想到了一种使用自定义Proxy将对象初始值设定项传递给类的非常人为的方法。它可能看起来很冗长,但Proxy可以根据需要重复使用多个类定义:



// mem initializer list
const list = (() => {
  let props = new WeakMap()

  // this: class instance
  // o: initializer object
  function initialize(o = {}) {
    if (props.has(this)) {
      return this[props.get(this)] = o;
    }

    return new Proxy(o, {
      get: (o, p) => (props.set(this, p), this[p] = o[p])
    });
  }

  // .call.bind() allows initialize(this, o)
  // to pass a context and one argument
  // instead of two arguments
  return initialize.call.bind(initialize);
})();

// example usage
class Test {
  constructor (o, { classAttr = list(this, 'foo'), undefinedParameter = list(this, 'bar') } = list(this, o)) {
    /* ... */
  }
}

console.log(new Test({ classAttr: 'sweety', excessParameter: 'oops' }));
console.log(new Test());




请注意,undefinedParameter始终使用其默认值'bar'进行初始化,而excessParameter永远不会添加到类实例中。

注意:这绝不是一个高效的解决方案。这是一个纯粹的噱头,但证明可以在某种程度上隐式初始化一个类实例。

使用这种方法的缺点是无法拦截默认参数,如

{ classAttr = 'defaultValue' }

所以你必须使用有点令人讨厌的语法

{ classAttr = list(this, 'defaultValue') }

以提供默认参数。

如果要扩展另一个类,则必须使用Proxy返回的list(super(), o)初始化该实例:



const list = (() => {
  let props = new WeakMap()

  function initialize(o = {}) {
    if (props.has(this)) {
      return this[props.get(this)] = o;
    }

    return new Proxy(o, {
      get: (o, p) => (props.set(this, p), this[p] = o[p])
    });
  }

  return initialize.call.bind(initialize);
})();

// example usage
class Test extends Object {
  constructor (o, { classAttr = list(this, 'foo'), undefinedParameter = list(this, 'bar') } = list(super(), o)) {
    /* ... */
  }
}

console.log(new Test({ classAttr: 'sweety', excessParameter: 'oops' }));
console.log(new Test());




答案 2 :(得分:0)

ES6类的语法禁止直接在类定义中的原型对象上分配属性。

您可以使用吸气剂来达到同样的效果。只定义一个getter也会使它只读。

但是,vanilla javascript中没有隐式语法来处理类型检查,这意味着必须使用函数内的 id name parentid ------ ---------- -------- 1 A NULL 2 B 1 3 C 2 (3 row(s) affected) typeof <variable> === '<primitiveType>'手动完成。

使用Octopus类将产生以下结果:

<variable> instanceof <Class>