在学习ES6函数一章时,发现了一个有意思的现象,原文描述如下:

这段话主要state了3个事实:

①函数参数有默认值时,会在声明初始化阶段形成一个单独的作用域

②这个作用域在初始化结束后消失

③没默认值的情况下,没有①②的现象发生。

这就很有意思了,我们一般说函数作用域,一般就是和全局作用域、局部作用域相爱相杀,这下来了个“声明时作用域”,更热闹了,这3者之间到底什么关系呢?

让demo自己来说话吧。

例子1:

    var x = 10;
function f( x,y=()=>{x=20;console.log(x);} ){//2
console.log( x );//1
y();
var x = 30;
console.log( x );//3
}
f();
console.log( x );//4

大家觉得上述代码运行会输出什么呢?不卖关子了,直接看结果再来分析吧。

结果从上到下分别对应代码里面的1、2、3、4输出语句。在主句分析以前,我们先回顾一下 “函数内变量提前声明” 的知识和上述的 “函数声明作用域”的概念,基于这些理论,我们可以得出如下作用域模型:

在此基础上,我们分析每个结果的由来。

//1: 函数体内声明了与参数同名的变量x,此时根据“变量提前”原则,函数作用域内的x被提前到function头部声明,此时参数x也无默认值传递给它所以,函数内的x是undefined.

//2. 有默认值的函数作用域,在声明是,分别开辟了自己独有的存放x,y的作用域,这里的x与函数体内的x没任何关系,有值的情况下,只是用值初始化一下内部的那个x,执行y访问的当然是自己作用域内的x了,也就是被变成了20的那个x。

//3. 函数体内声明了与参数x同名的变量x,但这个x与参数x没有任何关系,只存在一个初始化赋值的操作。因此此处的x是函数体内作用域的那个存30的x变量

//4. 全局量就不说了,和上述两个作用域都没有关系,不会被改变。

我们再看看下面的例子,有助于加深理解:有默认值的函数声明作用域和函数作用域有什么关系!

function f1( x=1,y=()=>{x=10;} ){
y();
console.log( x );
var x = 'abc';
}
f1();
function f2( x=1,y=()=>{x=10;} ){
y();
console.log( x );//
//var x = 'abc';
}
f2();

运行结果分别如下:

分析如下:

f1中,因为参数有默认值,所以参数开辟了自己的作用域,函数体内声明了自己的x,也开辟了自己的作用域,这俩x没任何关系,只是参数用自己的值初始化了函数体内的x,所以它打印了1

f2中,函数体内未声明自己的同名变量,在变量解析的时候就顺着"作用域链"爬到了参数声明作用域内,此时访问的时候就是访问的参数声明作用域内的x。

综上,得到Final conclusion:

1. 有默认值的函数,的确是开辟了单独的“参数声明作用域A”,这个作用域与函数体内的作用域是互不相干的,独立的。

2. 函数体内的同名变量接受来自同名参数的默认赋值,并单独开辟函数体内的一个作用域B.

3. 在作用域B中找不到变量时,程序会攀援“scope-chain”找到作用域A中的变量,并加以操作。

所以,在没有let之前的作用域A和作用域B是互相独立又有“上溯”查找的关系,比较难以理解,虽然没人在传参后再声明一个同名的局部变量,但我们要理解js底层对这种行为的处理方式。

好在,ES6诞生了!let声明重名变量会报错,从根本上杜绝了这种现象的发生。

———学无止境,may stars guide your way

ES6—带默认值的函数参数及其作用域的更多相关文章

  1. C++带参数默认值的函数

    定义形式: void fun(int a = 1 ,int b = 2 ,int c = 3 ,int d = 4){ //函数定义 cout<<"a="<< ...

  2. 函数的默认值与动态参数arguments的总结

    在js函数与作用域,了解函数基本概念中,我们发现当函数的实参有一个没有上传的时候,对应的形参time展示的值就是undefined,如下代码所示: <!DOCTYPE html> < ...

  3. C# 方法中带默认值的参数

    设计一个方法的参数时,可为部分或全部参数分配默认值.然后,调用这些方法的代码可以选择不指定部分实参,接受其默认值.除此之外,调用方法时,还可通过指定参数名称的方式为其传递实参.以下代码演示了可选参数和 ...

  4. C++——带默认参数值的函数

    函数在声明时可以预先给出默认的形参值,调用时如给出实参,则采用实参值,否则采用预先给出的默认参数值. ,) { return x + y;} int main() { add(,);//10+20 a ...

  5. python--函数的返回值、函数参数的使用、名称空间与作用域、函数嵌套、函数对象

    今天学习内容有函数的返回值.函数参数的使用.名称空间与作用域.函数嵌套. 下来我们一一查看. 函数的返回值 看几个栗子: def func(x): y=func() print(y) def foo( ...

  6. C#语法糖之第二篇: 参数默认值和命名参数 对象初始化器与集合初始化器

    今天继续写上一篇文章C#4.0语法糖之第二篇,在开始今天的文章之前感谢各位园友的支持,通过昨天写的文章,今天有很多园友们也提出了文章中的一些不足,再次感谢这些关心我的园友,在以后些文章的过程中不断的完 ...

  7. es6(三):es6中函数的扩展(参数默认值、rest参数、箭头函数)

    1.函数可以设置参数默认值 function test1(x,y=1){ console.log(x,y) } test1(10)//10 1 2.rest参数:形式为...变量名 function ...

  8. ES6参数默认值,剩余参数及展开数组

    一.函数的参数默认值 在ES6之前,想要给参数设置默认值得话,只能在函数体内部加判断设置,比如如果传递参数为undefined时为true, 否则为false,如下图example1,ES6出现语法可 ...

  9. Js基础知识5-函数返回值、函数参数、函数属性、函数方法

    函数返回值 所有函数都有返回值,没有return语句时,默认返回内容为undefined,和其他面向对象的编程语言一样,return语句不会阻止finally子句的执行. function testF ...

随机推荐

  1. 哈希表---线性探测再散列(hash)

    //哈希表---线性探测再散列 #include <iostream> #include <string> #include <stdio.h> #include ...

  2. ping 和 远程桌面 与防火墙的关系

    现象: 初始化服务器时,人们为了方便,常常关闭防火墙,这样做很危险.我们经常遇到问题是,防火墙一旦打开,ping和远程桌面就会有问题. 有时ping不通,但能远程:但有时ping通,又远程不了:有时都 ...

  3. 接口_简单get接口_第一个接口

    import flask,json # print(__name__) ##__name__代表当前这个python文件 server = flask.Flask(__name__) #把咱们当前的这 ...

  4. 2018.8.10Yukimai模拟Day1

    这的确是最惨的一次模拟了……不会再惨了(10pts除非爆零orz) 总结一下吧…… T1 .章鱼 众所周知,雪舞喵有许多猫.由于最近的天气十分炎热,雪舞城的大魔法师雪月月根本不想出门,只想宅在家里打隔 ...

  5. table中tr或者td的点击事件

    直接把时间添加到table或者tbody上,只有下面的tr或者td才能促发事件,通过e.target可以获得当前点击tr或者td,这样就可以进行查询或者删除操作了 如果是删除,直接e.target.r ...

  6. cas单点登录系统:客户端(client)详细配置(包含统一单点注销配置)

    最近一直在研究cas登录中心这一块的应用,分享一下记录的一些笔记和心得.后面会把cas-server端的配置和重构,另外还有这几天再搞nginx+cas的https反向代理配置,以及cas的证书相关的 ...

  7. Sublime Text 常用的16 个 Sublime Text 快捷键

    在我做了一次包含一些现场编码的演示后,一些观众问我是如何操作这么快.当然这里没有唯一的答案,答案是一堆简单的快捷键和大量的实践的组合.为了回应那些询问,我觉得有必要看看我每天想都不用想且使用的快捷键. ...

  8. ASP.NET Core MVC 2.x 全面教程_ASP.NET Core MVC 17. 基于Claim和Policy的授权 上

    首先补一下昨天没有讲的东西 只有管理员才能访问UserController RoleController都加上这个角色 Cliam 不是管理员角色的用户访问 cliam是name个Value值的键值对 ...

  9. 关于Android ListView组件中android:drawSelectorOnTop含义(转载)

    转自:http://yangguangfu.iteye.com/blog/902559 When set to true, the selector will be drawn over the se ...

  10. liteos 中断机制(四)

    1. 概述 中断是指出现需要时, CPU暂停执行当前程序,转而执行新程序的过程.即在程序运行过程中,系统出现了一个必须由CPU立即处理的事务,此时, CPU暂时中止当前程序的执行转而处理这个事务,这个 ...