第 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
执行代码步骤
- 变量提升
- 形参赋值
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
})()
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这两个作用域之间的关系,希望能看到详细的解说~~~
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。
还是没有很理解,求详细解释~
undefined undefined 20, try it!
(function(){
b = 5
})()
这一段是否可以理解为
var b;
(function(){
b =5
})
因为没有加var 所以为global作用域声明提升,而不是函数作用域声明提升。
(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
在js使用了模块导入的方式下,输出的结果是undefined,undefined,20。有大佬知道是为什么吗
是因为第一句var a=10;中的a 不是挂载在window上的 ,所以立即执行函数中的 window.a的值是 undefined
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)
})()
var a = 10;
(function () {
console.log(a)
a = 5
console.log(window.a)
var a = 20;
console.log(a)
})()
- 由于var会进行变量提升,但不赋值,返回undefined,类似于 var a = undefined,所以第一个会输出 undefined;
- a = 5,只是把函数内的局部变量a赋值成了5,所以输出window.a的时候还是10;
- 局部变量变成20,所以输出了20;
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