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

varDeclare逻辑是不是有问题? #3

Open
deqwin opened this issue Dec 8, 2018 · 6 comments
Open

varDeclare逻辑是不是有问题? #3

deqwin opened this issue Dec 8, 2018 · 6 comments

Comments

@deqwin
Copy link

deqwin commented Dec 8, 2018

varDeclare中,在递归查找父作用域之后,不是应该定义到最终查找到的父作用域上吗,怎么还是赋给了this.declaration?

varDeclare (name, value) {
let scope = this
// 若当前作用域存在非函数类型的父级作用域时,就把变量定义到父级作用域
while (scope.parentScope && scope.type !== 'function') {
scope = scope.parentScope
}
this.declaration[name] = new SimpleValue(value, 'var')
return this.declaration[name]
}

@jrainlau
Copy link
Owner

注意这一句scope = scope.parentScope。由于Scope是一个实例对象,所以当执行到这一句的时候,this所指向的scope其实已经是parentScope

@deqwin
Copy link
Author

deqwin commented Dec 10, 2018

我试了一下好像不是耶?

var x = 1;
if (true) {
var y = 2;
if (true) {
var z = 3;
}
}
console.log(x+y+z);

就用这个例子测试。y=2成功赋值到父作用域是es5.js line 22

nodeIterator.scope.parentScope.declare(name, value, kind)

这行的作用,不是issue中的递归实现的,所以z=3并不能成功赋值到最外层的作用域上。

@deqwin
Copy link
Author

deqwin commented Dec 10, 2018

另外还有个疑问:BlockStatement中是不是在声明提前的过程中,不小心把变量赋值也提前了?

@jrainlau jrainlau reopened this Dec 11, 2018
@jrainlau
Copy link
Owner

我试了一下好像不是耶?

var x = 1;
if (true) {
var y = 2;
if (true) {
var z = 3;
}
}
console.log(x+y+z);

就用这个例子测试。y=2成功赋值到父作用域是es5.js line 22

nodeIterator.scope.parentScope.declare(name, value, kind)

这行的作用,不是issue中的递归实现的,所以z=3并不能成功赋值到最外层的作用域上。

已经在最新的commit里面修复了。确实是varDeclaration函数的问题。

至于你的第二个问题没有很懂,有具体代码体现吗?

@deqwin
Copy link
Author

deqwin commented Dec 11, 2018

(function(){
console.log(a);
var a = 1;
})()

这里应该是打印出undefined,不是1

@JonathanLee-LX
Copy link

(function(){
console.log(a);
var a = 1;
})()

这里应该是打印出undefined,不是1

var a = 1这行代码对应的AST

{
    "type": "VariableDeclaration",
    "start": 3,
    "end": 12,
    "declarations": [ {
      "type": "VariableDeclarator",
      "start": 7,
      "end": 12,
      "id": {
        "type": "Identifier",
        "start": 7,
        "end": 8,
        "name": "a"
      },
      "init": {
        "type": "Literal",
        "start": 11,
        "end": 12,
        "value": 1,
        "raw": "1"
      }
    } ],
    "kind": "var"
  }

所以在声明的时候会直接求值,并且赋值
const value = declaration.init ? nodeIterator.traverse(declaration.init) : undefined
如果要正确的实现js的声明提前特性,可能需要将字符串形式的代码进行一次预编译,将var a = 1这样的语句编译成

var a = undefined
a = 1

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