Es6函数默认参数作用域详解

es5中只有两种作用域,一个是全局作用域,另外一个是函数作用域,这个大家应该都知道,es6中多了个块级作用域(这里不多作解释,不懂的自己去找资料),最近看es6发现函数默认参数会产生作用域,发现有点绕,查了些资料,把自己的思路和推断写下来(个人理解,勿喷,愿意接受指正)。

es6默认参数作用域

首选我们来看个例子
例子1:

var x = 1;
function foo(x, y = function() { x = 3; }) {
  var x = 5;
  y();
  console.log(x);
};
foo();//5
console.log(x);//1

如果设置了参数的默认值,函数进行声明初始化时,参数会形成一个单独的作用域(context)。等到初始化结束,这个作用域就会消失。这种语法行为,在不设置参数默认值时,是不会出现的。这个阮玉峰老师的话,拿上面例子来推断,那么x, y = function() { x = 3; }会形成以个单独的作用域(但是我现在还不知道是不是属于块级作用域),foo函数有个函数作用域,最外层有个全局作用域,初步推断有3个作用域,一个全局的作用域,一个默认参数作用域,一个函数作用域,看到foo()输出为5,上面var =5,所以我认为这个x和默认参数的x应该不是用一个作用域内,是两个作用域,再次肯定我刚才的推断,接着我修改一下代码 。
例子2:

var x = 1;
function foo(x, y = function() { x = 3; }) {
   x = 5;
  y();
  console.log(x);
};
foo();//3
console.log(x);//1

把var x=5 改成x =5后,foo()输出为3,x居然能读取到默认参数作用域的值,所以我大胆猜测,默认参数作用域和函数作用域应该是个父子关系,默认参数作用域为父作用域,函数作用域为子作用域。于是我模拟下代码
例子1的代码模拟:

var x = 1;
function foo() {
	{
		let x;
	    let y = function() { x = 3;};
	    {
	        var  x=5;
	    	 y();
	    	console.log(x);
	    }
	};
};
foo();
console.log(x);

结果发现这样模拟有问题,报错“Uncaught SyntaxError: Identifier ‘x’ has already been declared”,于是想函数作用域和默认参数作用域是两个作用域,可以没有关联的,于是我把函数里面的 var 该成了let

var x = 1;
function foo() {
	{
		let x;
	    let y = function() { x = 3;};
	    {
	        let  x=5;
	    	 y();
	    	console.log(x);
	    }
	};
};
foo();//5
console.log(x);//1

结果打印出来是正确的,这样看起来视乎合理了,可以解释的通,当把let x=5换成x=5(也就是例子2),这里函数中的x和参数作用域的x是同一个值,所以结果一个是3,外层还是1,是没有问题的,这样看上去一切都解释的通,于是我在源代码上打断点看了下,看下面图:
在这里插入图片描述
当运行foo()函数进入函数内,右边Block显示x为underfined,Local作用域x也为undefined,再往下走一步,看下面图:
在这里插入图片描述
右边Block显示x为5,Local作用域x也为undefined,所以再次确定函数作用域是一个块级作用域,默认参数作用域不是块级作用域,所以之前模拟的代码应该是这样的:

var x = 1;
function foo() {
	{
		var  x;
	    var  y = function() { x = 3;};
	    {
	          let x=5;
	    	 y();
	    	console.log(x);
	    }
	};
};
foo();
console.log(x);

我们再在我模拟的代码上打断点看下:
在这里插入图片描述
在这里插入图片描述
效果是一样,再次验证我的推断是对的!看完我的推断过程,你应该知道了函数默认参数作用域原理了吧,看下你是不是和回家一样?
在这里插入图片描述
在没语法的问题下,你可以按我之前的推断模拟代码:

var x=1;
function foo() {
  var y=function() { x = 2; };
  let x = 3;
  y();
  console.log(x);
};
foo();
console.log(x);

语法是没有问题的,然后在按我的推断模拟代码:

var x=1;
function foo() {
	{
		var y=function() { x = 2; };
		{
			let x = 3;
			y();
            console.log(x);
		};
	};
};
foo();
console.log(x);

很明显当当执行y()后,x=2改变了全局的变量x,所以输出foo()还是3,外面全局变量x为2;
再看一个面试题:
在这里插入图片描述
同样先看下语法有没有问题

var x=1;
function foo() {
  var x;
  var y=function() { x = 2;};
  let x = 3;
  y();
  console.log(x);
};
foo();
console.log(x);

重复声明x会报错,所以首先语法是有问题的,如果语法没有问题,再按我上面的推断分析。

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值