【JS基础】饭都喂到你嘴边了!作用域和作用域链的基础面试题解答

前言

也没啥好说的,就拉几个关于作用域和作用域链的基础面试题出来遛遛,解答过程有误还望指出。基础知识默认掌握,刚学JS的小伙伴建议先别看,容易弄晕。


有哪些作用域类型

  • 全局作用域(window下)
  • 函数作用域(函数里头)
  • 块级作用域({}里头),这是es6后才有的。

作用域的访问规则

  • 内部的作用域只能往外一层层的访问
  • 只要是内部访问到了外部就会产生闭包(和网上说的不一样?)
  • 内部作用往外访问时,只看定义的时候,不看执行的时候

补充1:var和let的作用域问题

关于var

var是函数级的作用域,还涉及到了变量提升。

var name = 'hello';
(function(){
	if(typeof name ==='undefined'){
		var name = 'jack';
		console.log("true"+name);
	}else{
		console.log('false'+name);
	} 
})()
// 问:控制台打出啥?
// 解答

var name = 'hello';
(function(){
    var name // undefined
	if(typeof name ==='undefined'){ // true
		var name = 'jack'; // var声明的变量是函数级作用域,变量提升到外部
		console.log("true"+name);
	}else{
		console.log('false'+name);
	} 
})()
var bar = 1;
function test(){
	console.log(bar);//undefined 因为变量提升
	var bar = 2;
	console.log(bar);//现在函数内部找局部变量 2
}
test()

关于let

是块级作用域

function demo(){
	let n=2;
	if(true){
		let n =1;
	}
	console.log(n); //输出几? 如果改成var就是输出啥
}
demo(); // 2

具体可以看【es6入门】变量声明


补充二:自由变量

通过作用域链获取到的变量可以被叫做自由变量

其实就是遵循上面说的作用域的访问规则的第三条。自由变量的查找,是在函数定义的地方,向上级作用域查找,不是在执行的地方!

自由变量的题一般都喜欢结合闭包来考察。咱们来举例(例子来源于慕课网):

// 函数作为返回值
function create() {
    const a = 100
    return function () {
        console.log(a)
    }
}

const fn = create()
const a = 200
fn() // 100

// 函数作为参数被传递
function print(fn) {
    const a = 200
    fn()
}
const a = 100
function fn() {
    console.log(a)
}
print(fn) // 100

作用域链和原型链是俩个东西

虽然都涉及到找东西,但是作用域链是在找一个独立的变量,而原型链更像在找对象上的东西


a = 1形式的作用域与作用域链判断

例题一

function test(){
	console.log(bar);//因为作用域链,在局部中没有变量声明,js不知道bar是什么,直接报错
	bar = 2 // js执行到这才能认识bar
}
test()

例题二

var f = true;
if(f===true){
	var a = 10;
}
function fn(){
	var b = 20;
	c=30;  // 这种没有声明的形式没有变量提升机制,js执行到了才认得
	// 注意如果 var b = c =20 ,c也是个全局变量
}
fn();
console.log(a,c) // c是全局变量
console.log(b) // b是var声明的变量,为函数级作用域,所以报错

例题三

function fn() {
	var a = 10
	window.a = 20
	console.log(a)
	//因为作用域链,先找本层的变量,再找外部的,虽然window.a是在本层的,但是它是一个全局变量所以是找的是本层的变量a = 10
}

例题四

function fn() {
	var a = 10
	window.a = 20
	a = 30 //作用域链关系,先找局部变量,找到,修改值
	console.log(this.a) //而这里打印的是全局变量 20
}

例题五

window.onload = function fn() {
	window.a = 20
	a = 30 //因为作用域链,先找内部的变量,没有局部变量,有个全局window.a的,那就修改全局的
	console.log(a) //局部变量没有,打印全局的 30
}

例题六

function fn() {
	window.a = 20
	a = 30 //因为作用域链,先找内部的变量,没有局部变量,有个全局window.a的,那就修改全局的
	console.log(this.a) //此时this指window 30
}

例题七

function fn() {
    window.a = 20
	a = 30 // 下面有局部变量的声明,变量提升,所以a=30 改的是局部的
	var a
	console.log(this.a) //20
}

例题八

var a = 10
function fn(a) {
	alert(a)
	a = 20 // 此时改的是参数a的值,不是修改全局变量
}
fn(30) //弹出30
alert(a) //弹出10

例题九

var a = 10
function fn() {
	alert(a)
	a = 20
}
fn() //因为作用域链,函数内找不到变量声明,只能向函数外找,弹出10
alert(a) //此时外部的a变量已经和函数内部关联了(也就是作用域链),所以a的赋值生效,弹出20;

未完待续~

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值