代码在javascript中返回语句后执行?

时间:2017-04-25 17:52:38

标签: javascript return evaluation

我在网络上找到了这个简短的JavaScript代码段:

var foo = 1;
function bar() {
    foo = 10;
    return;
    function foo() {}
}
bar();
console.log(foo);

我希望忽略函数 bar()中return语句之后的内容,并将变量 foo 结尾等于10。然而,令我惊讶的是,控制台输出了一些非常不同的东西:

1

现在,当我在return语句后删除该行

var foo = 1;
function bar() {
    foo = 10;
    return;
}
bar();
console.log(foo);

控制台按预期打印出来:

10

有谁能解释一下导致foo在前一版代码中返回1的原因是什么?

4 个答案:

答案 0 :(得分:6)

函数声明被提升到其包含上下文的顶部。您实际上是在var foo功能的顶部创建bar

foo中操纵的bar是该函数的本地操作,不会影响全局上下文foo

http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

答案 1 :(得分:2)

归功于hoisting

编译器基本上将其转换为:

function bar() {
    function foo() {}
    foo = 10;
    return;       
}

因此在分配之前有一个本地foo,您只会覆盖本地。函数foo()也将消失。

答案 2 :(得分:2)

tl; dr它是由于函数表达式和函数声明如何工作(也是函数提升):https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

更详细的回复:

将以下console.log放在代码中将帮助您可视化正在发生的事情,我想回答您的问题。

apollo-angular@0.13.0
apollo-client@1.0.4

输出如下:

//same es6 module, above my class definition
const RecentSearchesQuery = gql`
  query recentSearch {
    recentSearch {
      id
      query
      lastUpdated
      userId
    }
  }
`;

const RecentSearchesMutation = gql`
  mutation recentSearchSave($query:String!) {
    recentSearchSave(query: $query)
  }
`;

...

//my class method
updateRecentSearches(query: string) {
const updateQueries: MutationQueryReducersMap = {
  RecentSearch: (prev: Object, {mutationResult}) => {
    //execution doesn't get here
    debugger;
    alert('updateQueries handler in RecentSearchesMutation mutation for recentSearch');
    ...
  }
};

return new Promise((resolve, reject) => {
  this.apollo.mutate<any>({
    mutation: RecentSearchesMutation,
    variables: {query},
    updateQueries
  })
  .subscribe({
    next: ({data}) => {
      resolve();
    },
    error: (error: ApolloError) => {
      reject(error);
    }
  });
});

所以你怀疑,console.log('3',foo)和console.log('4',foo)永远不会在return语句之后被调用,这是预期的。你现在的问题可能是“为什么我的console.log('1',foo)被分配给函数foo(){}”,这可以通过以下SO问题回答,该问题描述函数声明与函数表达式,即< / p>

var foo = 1;
console.log('0', foo)
function bar() {
    console.log('1', foo)
    foo = 10;
    console.log('2', foo)
    return;
    console.log('3', foo)
    function foo() {}
    console.log('4', foo)
}
console.log('5', foo)
bar();
console.log('6', foo)

VS

'0' 1
'5' 1
'1' function foo() {}
'2' 10
'6' 1

Why can I use a function before it's defined in Javascript?

基本上执行function foo(){} 时,var foo = function(){} 的直接定义变为function(){},但这里的关键概念是bar的定义是foo内的本地定义1}}函数,在foo范围之外,它仍然被赋值为1。

关于函数声明和表达式的另一个好读物:https://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

答案 3 :(得分:0)

这是因为代码转换为;

var foo = 1;
function bar() {
    var foo;
    foo = 10;
    return;
    function foo() {}
}
bar();
console.log(foo);

这是因为JavaScript总是将变量声明而不是初始化移动到范围的顶部。