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

javascript - Class Decorator in Typescript - Stack Overflow

programmeradmin0浏览0评论

I'm trying to understand how class decorators work in Typescript when we wish to replace the constructor. I've seen this demo:

const log = <T>(originalConstructor: new(...args: any[]) => T) => {
    function newConstructor(... args) {
        console.log("Arguments: ", args.join(", "));
        new originalConstructor(args);
    }
    newConstructor.prototype = originalConstructor.prototype;
    return newConstructor;
}

@log
class Pet {
    constructor(name: string, age: number) {}
}

new Pet("Azor", 12);
//Arguments: Azor, 12

Everything is understood but this line:

newConstructor.prototype = originalConstructor.prototype;

Why do we do that?

I'm trying to understand how class decorators work in Typescript when we wish to replace the constructor. I've seen this demo:

const log = <T>(originalConstructor: new(...args: any[]) => T) => {
    function newConstructor(... args) {
        console.log("Arguments: ", args.join(", "));
        new originalConstructor(args);
    }
    newConstructor.prototype = originalConstructor.prototype;
    return newConstructor;
}

@log
class Pet {
    constructor(name: string, age: number) {}
}

new Pet("Azor", 12);
//Arguments: Azor, 12

Everything is understood but this line:

newConstructor.prototype = originalConstructor.prototype;

Why do we do that?

Share Improve this question asked Jun 13, 2017 at 10:44 RiskXRiskX 5916 silver badges22 bronze badges 2
  • Let's start with the fact that your code doesn't really do what you think it does. It doesn't work. Change the ctor to constructor(public name: string, public age: number) and then try to access the instance members (name and age) and you'll get undefined. Check this question for the right way of doing it: stackoverflow./questions/39198811/… – Nitzan Tomer Commented Jun 13, 2017 at 11:03
  • Hi, This code is from the internet, I don't care if it works I just need to know why we need this line because I've seen it in more examples – RiskX Commented Jun 13, 2017 at 11:27
Add a ment  | 

1 Answer 1

Reset to default 3

The classes like:

class Pet {
    constructor(name: string, age: number) {}
    dosomething() {
        console.log("Something...");
    }
}

Are piled into functions when targeting ES5:

var Pet = (function () {
    function Pet(name, age) {
    }
    Pet.prototype.dosomething = function () {
        console.log("Something...");
    };
    return Pet;
}());

As you can seem when we use functions to define classes. The methods are added to the function's prototype.

This means that if you are going to create a new constructor (new function) you need to copy all the methods (the prototype) from the old object:

function logClass(target: any) {

  // save a reference to the original constructor
  const original = target;

  // a utility function to generate instances of a class
  function construct(constructor: any, args: any[]) {
    const c: any = function () {
      return constructor.apply(this, args);
    };
    c.prototype = constructor.prototype;
    return new c();
  }

  // the new constructor behaviour
  const newConstructor: any = function (...args: any[]) {
    console.log("New: " + original.name);
    return construct(original, args);
  };

  // copy prototype so intanceof operator still works
  newConstructor.prototype = original.prototype;

  // return new constructor (will override original)
  return newConstructor;
}

You can learn more at "Decorators & metadata reflection in TypeScript: From Novice to Expert (Part I)"

Update

Please refer to https://github./remojansen/LearningTypeScript/tree/master/chapters/chapter_08 for a more recent version.

发布评论

评论列表(0)

  1. 暂无评论