Advanced-Frontend / Daily-Interview-Question

我是依扬(木易杨),公众号「高级前端进阶」作者,每天搞定一道前端大厂面试题,祝大家天天进步,一年后会看到不一样的自己。

Home Page:https://muyiy.cn/question/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

第 41 题:考察作用域的一道代码题

gto999 opened this issue · comments

分别为undefined 10 20,原因是作用域问题,在内部声名var a = 20;相当于先声明var a;然后再执行赋值操作,这是在IIFE内形成的独立作用域,如果把var a=20注释掉,那么a只有在外部有声明,显示的就是外部的A变量的值了。结果A会是10 5 5

依次输出:undefined -> 10 -> 20

解析:

在立即执行函数中,var a = 20; 语句定义了一个局部变量 a,由于js的变量声明提升机制,局部变量a的声明会被提升至立即执行函数的函数体最上方,且由于这样的提升并不包括赋值,因此第一条打印语句会打印undefined,最后一条语句会打印20

由于变量声明提升,a = 5; 这条语句执行时,局部的变量a已经声明,因此它产生的效果是对局部的变量a赋值,此时window.a 依旧是最开始赋值的10

undefined,10,20。用var生命的变量存在变量提升,a在作用域里提前声明,但是没有定义,第一个输出undefined,a = 5,定义a的值,局部作用域修改为5,但是window全局对象下的a变量没有改变,输出10,最后var a = 20,给局部作用域赋值,输出20.

执行解析步骤:
var a = undefined;
a = 10;
(function () {
// 变量提升(预解析)
var a = undefined;
console.log(a); // 输出undefined
a = 5;
console.log(window.a); // 找window(全局)对象的a, 输出10
a = 20;
console.log(a); // 输出20
})()

var a = 10;
(function () {
	console.log(a)
	a = 5
	console.log(window.a)
	var a = 20
	console.log(a)
})()

// undefined
// 10
// 20

执行代码步骤

  1. 变量提升
  2. 形参赋值
var a = 10;
(function () {
    console.log(a); 
    a = 5;
    console.log(window.a);
    var a = 20;
    console.log(a); 
})();
//  ===
var a = 10;
(function () {
    var a;
    console.log(a); // undefined
    a = 5;
    console.log(window.a);  //  此时是window.a => 10
    a = 20;
    console.log(a); //  20
});

var a = 10;
(function () {
console.log(a) //undefined 变量提升 这之前 var a
a = 5 //全局变量
console.log(window.a) // 5 这里我有问题 10
var a = 20; // a =20
console.log(a) //20
})()

commented

1,变量提升;2,window.a 为 10

undefined 10 20
代码执行过程:
var a; // undefined
a = 10;
(function () {
var a; // undefined
console.log(a)
a = 5
console.log(window.a)
a = 20;
console.log(a)
})()

首先这段代码有两个作用域,window和function。在function作用域内,同样存在变量提升,当第一次console时,这时变量a只定义未赋值,所以打印undefined。在window作用域中,a的值为10,所以window.a的值为10。最后一次打印之前,a被赋值为20,所以打印结果为20。

问题:
其实在这里,我不是很理解window和function这两个作用域之间的关系,希望能看到详细的解说~~~

commented

undefined 10 20
代码执行过程:
var a; // undefined
a = 10;
(function () {
var a; // undefined
console.log(a)
a = 5
console.log(window.a)
a = 20;
console.log(a)
})()

首先这段代码有两个作用域,窗口和功能。在功能作用域内,同样存在变量提升,当第一次控制台时,这时变量一个只定义未赋值,所以打印未定义。在窗口作用域中,一个的值为10,所以window.a的值为10最后一次打印之前,一个被赋值为20,所以打印结果为20。

问题:
其实在这里,我不是很理解窗口和功能这两个作用域之间的关系,希望能看到详细的解说~~~

(function(){
  var window = this
  var a = '123'
  (function(){
    var a = '234'
    console.log(window.a)
    console.log(this.a)
  }())
}())

如果看的懂的话我就不解释了,如果还看不懂的话我在解释

懂的

undefined 10 20
代码执行过程:
var a; // undefined
a = 10;
(function () {
var a; // undefined
console.log(a)
a = 5
console.log(window.a)
a = 20;
console.log(a)
})()
首先这段代码有两个作用域,窗口和功能。在功能作用域内,同样存在变量提升,当第一次控制台时,这时变量一个只定义未赋值,所以打印未定义。在窗口作用域中,一个的值为10,所以window.a的值为10最后一次打印之前,一个被赋值为20,所以打印结果为20。
问题:
其实在这里,我不是很理解窗口和功能这两个作用域之间的关系,希望能看到详细的解说~~~

(function(){
  var window = this
  var a = '123'
  (function(){
    var a = '234'
    console.log(window.a)
    console.log(this.a)
  }())
}())

如果看的懂的话我就不解释了,如果还看不懂的话我在解释

运行了一下,打印结果报错:Uncaught TypeError: "123" is not a function。

还是没有很理解,求详细解释~

commented

undefined undefined 20, try it!

commented
(function(){
  b = 5
})()

这一段是否可以理解为

var b;
(function(){
 b =5
})

因为没有加var 所以为global作用域声明提升,而不是函数作用域声明提升。

commented
(function(){ // ①
  var window = this
  var a = '123'
  (function(){ // ②
    var a = '234'
    console.log(window.a)
    console.log(this.a)
  }())
}())

@Yana5417 可能并没有说清楚吧。

作用域

我们都知道window是一个全局对象,在我的例子中①是假象出来的,为的是让你看到window的作用域,及全局作用域,然后下来是②,它是一个函数作用域

关系

1、函数作用域可以访问全局作用域

var a = 123;
(function(){
  console.log(a) // 123
  a = 456
}());
console.log(a) // 456

步骤解析:

var a = undefined;
a = 123;
(function(){
  console.log(a) // 函数作用域寻找变量a
  console.log(window.a) // 结果没找到,那么他会向上寻找,直到找到该变量,若最后没有找到,那么就会报该变量未定义
  window.a = 456 // 因为找到的是window的变量`a`所以此处会修改window的变量`a`
}());
console.log(a) // 456
在这里实际还涉及到隐式声明,所以我在下面会说明

2、全局作用域中无法访问局部作用域的变量

(function(){
  var a = 456
}());
console.log(a) // Error: a is not defined

步骤解析:

(function(){
  var a = 456
}());
console.log(a) // window已经是全局作用域了,在这里并没有发现变量`a`所以不会继续向上寻找,直接输出 a is not defined

3、当局部作用域中进行隐式声明时,默认会在全局作用域中声明该变量

(function(){
  a = 456
}());
console.log(a) // 456
// 局部变量捡到十块钱,然后找不到失主,然后全局变量说,那算了,找不到我就先拿着把。然后局部变量说,好吧,那就给你吧!

最后我们开始看你解析完后这道题

var window = this; // 再次声明此处可忽略,只是为了让你看到window是全局this的别名
var a; // undefined
a = 10; 
(function () {
var a; // undefined
console.log(a) //  此处因为是显式声明所以你在函数作用域中访问到的,一定是他内部声明变量`a`
a = 5 // 显式声明的变量`a` = 5
console.log(window.a) // 直接找的是`window`的`a`则不在函数作用域中寻找 有趣的是,`function`中不通过`call`或`apply`修改`this`指针,此处输出 `this.a` 的效果是一致的
a = 20;// 显式声明的变量`a` 由 5 变成 20
console.log(a)
})()

这次应该可以看明白了吧!

明白了,非常感谢🙏

分别为undefined 10 20,原因是作用域问题,在内部声名var a = 20;相当于先声明var a;然后再执行赋值操作,这是在IIFE内形成的独立作用域,如果把var a=20注释掉,那么a只有在外部有声明,显示的就是外部的A变量的值了。结果A会是10 5 5

为什么window.a的值不是10而是5了

var a = 10;
(function () {
console.log(a) //undefined 变量提升 这之前 var a
a = 5 //全局变量
console.log(window.a) // 5 这里我有问题 10
var a = 20; // a =20
console.log(a) //20
})()

a=5是局部变量吧

分别为undefined 10 20,原因是作用域问题,在内部声名var a = 20;相当于先声明var a;然后再执行赋值操作,这是在IIFE内形成的独立作用域,如果把var a=20注释掉,那么a只有在外部有声明,显示的就是外部的A变量的值了。结果A会是10 5 5

为什么window.a的值不是10而是5了

明白了a快速执行函数内没有声明,所以赋值到全局变量了

var a = 10;
(function () {
    console.log(a)
    a = 5
    console.log(window.a)
    var a = 20;
    console.log(a)
})();
// 前提浏览器中执行,node中window.a会报错 window is not defined

// undefined  函数中的a,先会找函数中是否存在该变量,因为存在声明前置,所以这里的第一个a为undefined
// 10  指定了是window上的a变量,说明是函数外部的a
// 20  此时函数内的a已经赋值为20了,所以输出为20。可以转为如下代码

window.a = 10;
(function() {
  var a;
  console.log(a);
  a = 5;
  console.log(window.a);
  a = 20;
  console.log(a);
})();
(function(){
  a = 456
}());
console.log(a) // 456

a 不是全局变量吗??
局部变量你应该是使用let声明
同样使用var也能在外面打印
因为var存在变量提升什么的所以出了let
如果不声明变量那么他就会作为全局变量
个人理解~

undefined undefined 20 中间的自定义属性,未赋值 (个人理解 )

window.a是个坑

在js使用了模块导入的方式下,输出的结果是undefined,undefined,20。有大佬知道是为什么吗

我感觉这得非情况讨论吧:
1.如果在浏览器中执行这个就是undefined, 10, 20
2.如果直接在编辑器直接执行这段js,window.a就会报错。因为在node.js的环境中没有dom,和dom操作。

undefined 10 20
涉及知识点有:
1、自执行函数会形成块级作用域
2、作用域链是自内向外查找
3、作用域形成与js引擎编译阶段,并不会做负值操作
4、var声明的全局变量会赋值给window对象

第一 undefined

因为函数内部声明过a, 导致变量提升,但不负值,返回undefined。如果内部没有声明a 则作用域继续向外查找,找到a= 10:

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

第二 10

参照第四点直接读取全局变量 a=10

第三 20

常规作用域查找,a=20

commented

在js使用了模块导入的方式下,输出的结果是undefined,undefined,20。有大佬知道是为什么吗

是因为第一句var a=10;中的a 不是挂载在window上的 ,所以立即执行函数中的 window.a的值是 undefined

commented
 var a = 10;
    (function () {
        console.log(a) // undefined
        a = 5
        console.log(window.a) // 10
        var a = 20; 
        console.log(a) // 20
    })()
var a = 10;
(function () {
    console.log(a)
    a = 5
    console.log(window.a)
    var a = 20;
    console.log(a)
})()
commented
var a = 10;
(function () {
    console.log(a)
    a = 5
    console.log(window.a)
    var a = 20;
    console.log(a)
})()
  1. 由于var会进行变量提升,但不赋值,返回undefined,类似于 var a = undefined,所以第一个会输出 undefined;
  2. a = 5,只是把函数内的局部变量a赋值成了5,所以输出window.a的时候还是10;
  3. 局部变量变成20,所以输出了20;
commented

undefined 10 20
代码执行过程:
var a; // undefined
a = 10;
(function () {
var a; // undefined
console.log(a)
a = 5
console.log(window.a)
a = 20;
console.log(a)
})()
首先这段代码有两个作用域,窗口和功能。在功能作用域内,同样存在变量提升,当第一次控制台时,这时变量一个只定义未赋值,所以打印未定义。在窗口作用域中,一个的值为10,所以window.a的值为10最后一次打印之前,一个被赋值为20,所以打印结果为20。
问题:
其实在这里,我不是很理解窗口和功能这两个作用域之间的关系,希望能看到详细的解说~~~

(function(){
  var window = this
  var a = '123'
  (function(){
    var a = '234'
    console.log(window.a)
    console.log(this.a)
  }())
}())

如果看的懂的话我就不解释了,如果还看不懂的话我在解释

运行了一下,打印结果报错:Uncaught TypeError: "123" is not a function。

还是没有很理解,求详细解释~

如果在浏览器console执行的话, 第三行末尾没有分号"; " 认为执行的是 var a = '123'(自执行函数), 把'123' 当function了,所以会报错.

这里关键点是变量提升,代码等价于

    var a = 10;
    (function() {
        var a;  //变量声明会提到作用域最前面
        console.log(a)  //undefined
        a = 5
        console.log(window.a)  //全局变量a-10
        a = 20;
        console.log(a)         //作用域内a-20
    })()

这样的提升并不包括赋值

借用楼上解释:如果把var a=20注释掉,那么a只有在外部有声明,显示的就是外部的A变量的值了。结果A会是10 5 5