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

第 108 题:请写出如下代码的打印结果 #190

Open
yygmind opened this issue Jul 18, 2019 · 54 comments
Open

第 108 题:请写出如下代码的打印结果 #190

yygmind opened this issue Jul 18, 2019 · 54 comments

Comments

@yygmind
Copy link
Contributor

yygmind commented Jul 18, 2019

var name = 'Tom';
(function() {
    if (typeof name == 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();
@yygmind yygmind added the 京东 label Jul 18, 2019
@twotwoba
Copy link

Goodbye Jack

@ldlcoder
Copy link

ldlcoder commented Jul 18, 2019

Goodbye Jack

var name = 'Tom';
(function(name) {
if (typeof name == 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})(name);
Hello Tom
var name = 'Tom';
(function() {
if (typeof name == 'undefined') {
        let name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

Hello Tom

@slowlydd
Copy link

Goodbye Jack

@caiyongmin
Copy link

caiyongmin commented Jul 18, 2019

var name = 'Tom';
(function() {
    console.info('name', name);
    console.info('typeof name', typeof name);
    if (typeof name == 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();
name undefined
typeof name undefined
Goodbye Jack

var 声明的变量没有块作用域,变量会提升到最近的 function 作用域的上层,但此时只是声明了变量,并没有赋值,到实际运行了赋值语句之后才有值,在之前值为 undefined

@ckjie
Copy link

ckjie commented Jul 18, 2019

Goodbye Jack;
IIFE内的var穿透了块作用域,name被提升至if()之前,且此时name为undefined。

@jinjunss
Copy link

Goodbye Jack

@lhj767382286
Copy link

Goodbye Jack建立阶段以及代码执行阶段的详细分析、变量提升

@Tiramisupxl
Copy link

为什么把var name改成let name,结果就变成Hello Tom了呢,求大佬解答

@sunhua-2217
Copy link

var 变量提升,所以 name 是 undefined, 答案是 goodbye jack

@zhenujt
Copy link

zhenujt commented Jul 18, 2019

为什么把var name改成let name,结果就变成Hello Tom了呢,求大佬解答

var 存在提升关系, let不会提升。
链接 http://es6.ruanyifeng.com/#docs/let#let-%E5%91%BD%E4%BB%A4

@cnhekai
Copy link

cnhekai commented Jul 18, 2019

先说答案Goodbye Jack;
var name存在变量提升,此时if (typeof name == 'undefined')的结果为true,所以走true分支,直接打印出Goodbye Jack
如果将var name改为let name,将打印Hello Tom,因为let声明不会变量提升,所以走false分支就会找到IIFE外的name的值

@zhenujt
Copy link

zhenujt commented Jul 18, 2019

var name = 'Tom';
(function() {
// var name 提升到函数最顶端
if (typeof name == 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
Goodbye Jack

@DINLiang
Copy link

为什么把var name改成let name,结果就变成Hello Tom了呢,求大佬解答

你改的哪个var啊 怎么地 他也输出不了 hello Tom

@sunpcm
Copy link

sunpcm commented Jul 18, 2019

我感觉和是不是自动执行函数没什么关系,var 会先声明,导致函数作用域内在var声明之前的name都是undefined.

var bb = 2
function a(){
 if(0){
  console.log(bb) 
  var bb = 1  
 }else{
  console.log(bb)
 }
}
a()

就像这个一样,菜鸟小白个人理解,不知道对不对,话说,怎么高亮然后格式化代码。。。

@caiyongmin
Copy link

我感觉和是不是自动执行函数没什么关系,var 会先生命,导致函数作用域内在var声明之前的name都是undefined.
var bb = 2

function a(){
if(0){
console.log(bb)
var bb = 1
}else{
console.log(bb)
}
}
a()

就像这个一样,菜鸟小白个人理解,不知道对不对,话说,怎么高亮然后格式化代码。。。

https://help.github.com/en/articles/creating-and-highlighting-code-blocks

@sunpcm
Copy link

sunpcm commented Jul 18, 2019

我感觉和是不是自动执行函数没什么关系,var 会先生命,导致函数作用域内在var声明之前的name都是undefined.
var bb = 2
function a(){
if(0){
console.log(bb)
var bb = 1
}else{
console.log(bb)
}
}
a()
就像这个一样,菜鸟小白个人理解,不知道对不对,话说,怎么高亮然后格式化代码。。。

https://help.github.com/en/articles/creating-and-highlighting-code-blocks

吼猴,谢谢

@quhongqiang
Copy link

为什么把var name改成let name,结果就变成Hello Tom了呢,求大佬解答

因为let声明的变量仅仅在自己的块级作用域起作用,出了这个块级作用域就不起作用

@dingLeiOnly
Copy link

这道题会了能不能上京东?

@DINLiang
Copy link

这道题会了能不能上京东?

想啥呢

@104gogo
Copy link

104gogo commented Jul 18, 2019

这道题会了能不能上京东?

可以的,www.jd.com

@ligoudan1
Copy link

        var name = 'Tom';
        (function () {
            if (typeof name == 'undefined') {
                console.log('Goodbye ' + name);
            } else {
                console.log('Hello ' + name);
            }
        })();
        // Hello Tom

@habc0807
Copy link

这道题会了能不能上京东?

不然呢?你是觉得这题low

@ligoudan1
Copy link

        var name = 'Tom';
        (function () {
            console.log(name);
            if (typeof name == 'undefined') {
                let name = 'Jack';
                console.log('Goodbye ' + name);
            } else {
                console.log('Hello ' + name);
            }
        })();
// Tom
//hello Tom

let存在于{}作用域内,不存在作用域提升,此题考的是作用域提升问题,自执行函数只是干扰

@Chorer
Copy link

Chorer commented Jul 18, 2019

用执行上下文来解释:自执行函数调用后,首先进入执行上下文的创建阶段,该阶段找到函数内的变量声明name,此时为undefined(所以不管if语句是否成立,这个声明都是生效的);之后进入执行阶段,该阶段开始执行if判断,试图为name赋值,由于name在上一阶段刚好为undefined,所以判断通过,成功赋值为jack,最后输出goodbye jack。这道题里如果if判断不满足,那就只能输出undefined了,不会输出全局变量name,因为作用域查找的时候首先找到的是局部变量name

@ma-lihui
Copy link

我感觉和是不是自动执行函数没什么关系,var 会先声明,导致函数作用域内在var声明之前的name都是undefined.

var bb = 2
function a(){
 if(0){
  console.log(bb) 
  var bb = 1  
 }else{
  console.log(bb)
 }
}
a()

就像这个一样,菜鸟小白个人理解,不知道对不对,话说,怎么高亮然后格式化代码。。。

你说的对。而且变量提升是在执行之前的,所以即使if条件不会执行,里面定义的变量也会提升

@niexia
Copy link

niexia commented Jul 18, 2019

Goodbye Jack

var 关键字有变量提升,它定义的变量会提升到函数的顶部。题目中立即执行函数的中的变量 name 的定义被提升到了顶部,并在初始化赋值之前是 undefined,所以 typeof name == 'undefined

那么下面的答案又是多少?

var name = 'Tom';
(function() {
  if (typeof name == 'undefined') {
    let name = 'Jack';
    console.log('Goodbye ' + name);
  } else {
    console.log('Hello ' + name);
  }
})();

Hello Tom

let 声明的变量将被绑定到块级作用域。

ES6 规定,如果区块中存在 letconst 命令,这个区块对这些声明的变量,从一开始就形成了封闭的作用域。凡是在声明之前使用这些变量,就会报错。

总之,在代码块内,使用 let 声明变量之前,该变量是不可用的。这在语法上称为“暂时性死区”(temporal dead zone,简称 TDZ)。

var tmp = 'bar';
function foo() {
  console.log(tmp); // bar
  if (tmp) {
    // 在let命令声明变量tmp之前,都属于变量tmp的“死区”。
    // TDZ开始
    tmp = 'abc'; // ReferenceError
    console.log(tmp); // ReferenceError

    let tmp; // TDZ结束
    console.log(tmp); // undefined

    tmp = 123;
    console.log(tmp); // 123
  }
}

@ypf0088
Copy link

ypf0088 commented Jul 18, 2019

Goodbye Jack

var name = 'Tom';
(function() {
    if (typeof name == 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

改一下,应该就方便看懂了

var name = 'Tom';
(function() {
    var name;
    if (typeof name == 'undefined') {
        name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

@kvchen95
Copy link

var name = 'Tom';
(function() {
    if (typeof name == 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

这题考点:JS的预编译(敲重点!敲重点!敲重点!)
第一步创建AO对象 拿到所有变量声明和函数声明并且初始值为undefined
第二步下面因为是一个立即执行函数 声明即执行 所以现在任何变量都是undefined
第三步打印 Goodbye Jack

@EnergySUD
Copy link

var name = 'Tom';
(function() {
if(typeof name == 'undefined') {
var name = 'Jack'; //上面判断的是这里的name,然而判断之后才赋值,所以就是undefined
//如果var name = 'Jack'换成let name = 'Jack',因为let是块级作用域,所以上面判断会找已经赋Tom值得name,最后输出会是Hello Tom
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
//所以最后输出的值是Goodbye Jack

@wzpxx
Copy link

wzpxx commented Jul 18, 2019

变量提升

@luhaifeng666
Copy link

为什么把var name改成let name,结果就变成Hello Tom了呢,求大佬解答

let 存在区域死锁,不会有变量提升,所以name不会是undefined,所以会执行console.log('Hello ' + name); 然后就会找name,在当前function作用域找不到name,就会去外层找name,一直找到window下面的name,此时name是Tom,所以会打印Hello Tom,这个是作用域链的关系。我描述清楚了吗?

@Weizi-Luo
Copy link

Weizi-Luo commented Jul 18, 2019

这题考的是变量提升与作用域的知识点,大家都毫无疑问的知道。让人纠结的只是if花括号内的name要不要提升。对于javaScript语言里的var来说没有块级作用域,只有函数作用域!所以函数内的var name会提升到该函数作用域的顶端,而if花括号内的作用域并不是函数作用域,因此能穿透花括号提升到if之前。而let有自己的语法,只要是花括号都会被当作自己的作用域,在作用域外无法访问且不会变量提升。

最终形式: console.log('Goodbye' + 'Jack');

var name = 'Tom';
(function() {
    var name;
    if (typeof name == 'undefined') {
        name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

@xiaokeqi
Copy link

Goodbye Jack

var name = 'Tom'; //定义全局变量name, 即window.name = tome
// 定义立即执行函数。在js(es6块级作用域中let、const除外)中,只存在函数作用域和全局作用域
(function() {
     //函数作用域中,声明提升。故等于 var name; 函数作用域中name值 undefined
    // undefined ==undefined 走true逻辑
    if (typeof name == 'undefined') { 
        var name = 'Jack'; // 赋值,相当于name =‘Jack’
        console.log('Goodbye ' + name); // 输出 Goodbye Jack
    } else {
        console.log('Hello ' + name);
    }
})();

@MoveZZG
Copy link

MoveZZG commented Jul 18, 2019

如果你清楚JS中的作用域和变量提升,那么这题将不是问题。

@NANAYWY
Copy link

NANAYWY commented Jul 18, 2019

函数执行过程分为两步,创建执行环境和执行代码,创建执行环境的时候声明变量,在执行代码阶段给变量赋值。
本例中,函数内部使用var 声明了name,所以在创建执行环境时,函数声明了一个私有变量name,函数执行阶段,if中的name找到了私有变量name,此时没有赋值,所以走的是true的分支。

var name = 'Tom';
(function() {
    if (typeof name == 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

如果在函数内部的if语句中使用let 声明name,则在创建执行环境的时候不会声明内部变量name(if花括号中name被认为是if的局部变量),在执行代码阶段,找到了全局变量name(全局变量name已经赋值了),所以此时if判断走false分支。

var name = 'Tom';
(function() {
    if (typeof name == 'undefined') {
        let name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

如果在函数内部if语句之前使用let声明name,那么同情况一一样,也会在函数内部声明私有name。所以走true分支

var name = 'Tom';
(function() {
  let name
  if (typeof name == 'undefined') {
    console.log('Goodbye ' + name);
  } else {
    console.log('Hello ' + name);
  }
})();


@liangchaofei
Copy link

Goodbye Jack

@maosm
Copy link

maosm commented Jul 18, 2019

typeof 优先级等级高于 ==, name 进行了变量声明提升,name变成了undefined,typeof name相当于typeof undefined,typeof undefined相当于undefined。因此typeof name == 'undefined'为true。所以输出Goodbye Jack。

@ghost2113
Copy link

为什么把var name改成let name,结果就变成Hello Tom了呢,求大佬解答

let声明变量会建立块级作用域,不会产生变量提升

@superermiao
Copy link

Goodbye Jack,变量声明提升

@Nina0408
Copy link

var 变量声明提升
Goodbye Jack

@862881015
Copy link

我有个问题,undefined == 'undefined' 是false啊

@jackchenl
Copy link

jackchenl commented Jul 19, 2019

我有个问题,undefined == 'undefined' 是false啊

虽然 == 会隐式的转换 js的数据类型,但一个是字符串,一个是undefined 既变量的默认空值(它只和 null 在两个等于情况下相等),所以是false, 这边你只需要 记住 undefined和null 之间是会相互之间转换的。其他的情况下,它都不会进行 转换的

@jackchenl
Copy link

jackchenl commented Jul 19, 2019

在执行 某段js语句时, 首先 编译器会生成 js 引擎运行时所需要的代码,所以在这段 IIFE中 编译器首先会在当前作用域中 查找是否有声明过 变量name,发现当前作用域内没有,帮你声明变量name,之后再执行赋值操作,其中的最主要的是 用var关键字 声明 会导致变量提升。如果使用 let 就不会这样了。

@monic-shixi
Copy link

@prefertwo
Copy link

为什么把var name改成let name,结果就变成Hello Tom了呢,求大佬解答

因为,对 let来说,if 也算是块儿作用域,不会发生变量提升。此时,name 就是 外面的 name ,string类型,执行 else 分支。

@prefertwo
Copy link

我有个问题,undefined == 'undefined' 是false啊

var tt;
console.log( typeof tt) // undefined
console.log( typeof (typeof tt) ) // string

@james9527
Copy link

james9527 commented Jul 22, 2019

结果为'Goodbye Jack' 分析:执行到typeof name时,取的是函数体内局部变量name,值为'undefined',因此console打印的值为'Goodbye Jack',题目分解如下:

var name = 'Tom';
console.log(name) // 'Tom'
(function() {
    var name;
    if (typeof name == 'undefined') {
        name = 'Jack';
        console.log('Goodbye ' + name); // 'Goodbye Jack'
    } else {
        console.log('Hello ' + name);
    }
})();
console.log(name) // 'Tom'

@chaoranfeng
Copy link

答案都知道,但是关于换成let的问题 解释一下
首先先不说let是否会提升,为什么换成let会打印hello tom,并不是他不会提升的原因,是因为他是在if的块作用域里面啊,即使能提升 他也是提升在if() { }内部,并不是在立即执行函数的 根作用域内
其次 let是会提升的 ,只是没有初始化

@hanzc0106
Copy link

输出Goodbye Jack

var name = 'Tom';
(function() {
    if (typeof name == 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

等价于

var name = 'Tom';
(function() {
    var name;
    if (typeof name == 'undefined') {
        name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }
})();

@soraly
Copy link

soraly commented Jul 20, 2020

请写出如下代码的打印结果

var name = 'Tom';
(function() {
if (typeof name == 'undefined') {
  var name = 'Jack';
  console.log('Goodbye ' + name);
} else {
  console.log('Hello ' + name);
}
})();
  • var会变量提升到作用域的顶端,也就是if前面,所以此时访问name就是undefined
  • if为true,输出goodbye

@XuedaoYuan
Copy link

Goodbye Jack
陷阱在于匿名函数里面var name的变量提升

@hbli1
Copy link

hbli1 commented May 12, 2021

var name = 'Tom';
(function() {
    if (typeof name == 'undefined') {
        var name = 'Jack';
        console.log('Goodbye ' + name);
    } else {
        console.log('Hello ' + name);
    }  
    console.log(name) // Jack, var穿透块级作用域,
})();
// 
(function(){
  console.log(a);
  i=1;
  while(i--){
    var a = 1
  };
  console.log(a)
})()
console.log(i)
// 
(function(){
  console.log(a);
  for(let i = 0; i < 1;i++){
    var a = 1
  };
  console.log(a)
})()
console.log(i)

@tangli06
Copy link

为什么把var name改成let name,结果就变成Hello Tom了呢,求大佬解答
var name = "Jack"; 存在变量提升,var name = undefined; 被提升到函数作用域顶部,覆盖外部作用域var name = 'Tom';
let name = "Jack"; 存在暂时性死区,不能进行变量提升, 即 var name = 'Tom';

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

No branches or pull requests