Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

关于Decorator中"为什么修饰器不能用于函数"的一个小疑问 #399

Closed
MrErHu opened this issue May 10, 2017 · 3 comments
Closed

Comments

@MrErHu
Copy link
Contributor

MrErHu commented May 10, 2017

阮老师:
您的书中是如下描述的
修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升
并举出了一个示例:

var counter = 0;

var add = function () {
  counter++;
};

@add
function foo() {
}

实际的执行的效果为:

@add
function foo() {
}

var counter;
var add;

counter = 0;

add = function () {
  counter++;
};

Decorator只能用于类和类的方法中,这个我知道,但是对于您的这个解释我不太理解,如果仅仅是因为是方法存在提升,那么下面的代码不就避免了Decorator的赋值晚于方法的编译:

var counter = 0;

function add() {
  counter++;
};

@add
function foo() {
}

对这个点不是很理解,麻烦您能解释一下吗?

@ruanyf
Copy link
Owner

ruanyf commented May 11, 2017

这样就必须保证,add始终在foo之前定义。

原始的设计者不希望有这样的复杂性。你看一下这篇讨论。wycats/javascript-decorators#4

@ruanyf ruanyf closed this as completed May 11, 2017
@MrErHu
Copy link
Contributor Author

MrErHu commented May 11, 2017

@ruanyf 谢谢阮一峰老师

@hax
Copy link

hax commented Mar 2, 2018

事实上decorator用于function(解决hoisting的问题)是可能的,只不过要推迟到以后再进一步讨论。

简单来说,至少有两种方法:

  1. 引入不hoisting的新语法
@deco let f() {}
@deco const f() {}
  1. 延迟到函数被第一次执行或者到声明本来所在行的时候才执行decorator
@deco function f() {
  funcBody
}

转换为

function f(...args) {
  if (!$decorated_f) $do_decorate_f()
  return $decorated_f.call(this, ...args)
}
var $decorated_f
function $do_decorate_f() {
  $decorated_f = deco(function f() {
    funcBody
  })
}
$do_decorate_f()

UPDATE: 上面这个转换有个小问题,只考虑了执行,而没有考虑对函数本身的修饰。改进版本见:
tc39/proposal-decorators#40 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants