待整理01-JS 形参与变量声明和函数声明同名怎么办?

1. 简介

前两天遇到一道很有意思的题目,乍看起来是一道考声明提升和变量提升的题目的,但事实上还包含了更多的知识点。下面我们一起来看一下。

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

f(1);

2. 详细讲解

这道题目初看上去很简单。首先,你要能解答如下问题:

function f(b) {
    console.log(a);  // function a() {}
    var a = 2;
    function a() {}
    console.log(a);  // 2
}

f(1);

如果,形参与函数内部的变量声明或者函数声明不同名,这道题很容易解答。如果你不会,可以看一下这两篇文章。JS入门难点解析2-JS的变量提升和函数提升JS入门难点解析5-变量对象,我剖析了函数声明和变量声明的表现和原理。

但是这里很特别,这题除了考察函数声明,变量声明的提升以外,还考察了同名变量和同名形参的覆盖问题,这种情况该如何分析呢?

我们要分成三种情况,第一种传入变量是具体的值,第二种传入变量是函数声明,第三种传入变量是函数赋值的变量。

2.1 传入变量是具体的值

这种就是题目所述的情况。我们再试着分解题目。看下面两代码:

function f(a) {
    console.log(a);  // 1
    var a = 2;
    console.log(a);  // 2
}

f(1);
function f(a) {
    console.log(a);  // function a() {}
    function a() {}
}

f(1);

这是什么原因呢?试着回忆一下,函数进入执行流程的步骤是什么?首先是执行环境进行准备工作,这一阶段,变量对象会包括:函数的所有形参 (如果是函数上下文),函数声明,变量声明。我们已经比较过函数声明和变量声明内部与之间的优先级,当这些变量同名时。 1. 函数声明 替换 变量声明 2.后面的函数声明替换前面的函数声明 3.后面的变量声明无效 此外,从这里我们可以看到,f(1)的其实等同于如下效果:

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

等于在函数内部第一行执行了一个变量赋值,大家看一下,是不是这样变化以后,结果仍然是遵循之前的规则。

2.2 传入的是函数声明

如下:

function f(a) {
    console.log(a);  // ƒ a() {  console.log('outer'); }
    var a = 2;
    function a() {}
    console.log(a);  // 2
}
f(a);
function a() {
    console.log('outer');
}
function f(a) {
    console.log(a);  // function a() {}
    var a = 2;
    console.log(a);  // 2
}
f(a);
function a() {
    console.log('outer');
}

可以看出,函数f内部等同于如下效果:

function a() {
    console.log('outer');
}
console.log(a);
var a = 2;
function a() {}
console.log(a);

这样看,是不是一目了然呢?

2.3 传入函数赋值的变量

进一步思考,如果这是一个赋值为函数的变量呢?

function f(a) {
    console.log(a);  // function a() {}
    var a = 2;
    function a() {}
    console.log(a);  // 2
}
f(a);
var a = function b() {
    console.log('outer');
}

聪明的你应该猜到了,是的,效果就等同于如下:

var a = function b() {
    console.log('outer');
}
console.log(a);  // function a() {}
var a = 2;
function a() {}
console.log(a);  // 2

3. 总结

综上,其实传参这一步,我们可以将其转化到函数内的第一行,改写为变量声明赋值或者函数声明。当这些变量同名时,应用的规则仍然是以下三条: 当这些变量同名时。 1. 函数声明 替换 变量声明 2.后面的函数声明替换前面的函数声明 3.后面的变量声明无效

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏猿人谷

C++ STL算法系列4---unique , unique_copy函数

 一.unique函数 类属性算法unique的作用是从输入序列中“删除”所有相邻的重复元素。 该算法删除相邻的重复元素,然后重新排列输入范围内的元素,并且返回...

21160
来自专栏云瓣

走近 Python (类比 JS)

Python 是一门运用很广泛的语言,自动化脚本、爬虫,甚至在深度学习领域也都有 Python 的身影。作为一名前端开发者,也了解 ES6 中的很多特性借鉴自 ...

489100
来自专栏Bingo的深度学习杂货店

Q792 Number of Matching Subsequences

Given string S and a dictionary of words words, find the number of words[i] that...

10530
来自专栏PHP实战技术

你应该这个姿势学习PHP(2)

2、is_array(),is_bool,is_int(),is_integer(),is_numeric(),is_string(),is_object(),...

40960
来自专栏生信小驿站

python-运算符与表达式

你所编写的大多数语句(逻辑行)都包含了表达式(Expressions)。一个表达式的简单例子便是 2+3。表达式可以拆分成运算符(Operators)与操作数(...

20720
来自专栏蓝天

Linux内核list/hlist解读

Linux内核实现了一批优雅而功能强大的双向循环列表操作宏,它们位于/usr/include/linux/list.h(请注意直接#include会报编译错误...

13610
来自专栏河湾欢儿的专栏

第五节正则

9120
来自专栏Java帮帮-微信公众号-技术文章全总结

第四天 数组【悟空教程】

21990
来自专栏mathor

二分查找与二分答案(2)

14540
来自专栏一“技”之长

分分钟使用正则表达式 原

        从概念上来说,正则表达式也是一门小巧而精炼的语言,它可以用来简化检索特定的字符串,替换特定字符等功能,有许多开发语言工具,都内嵌支持正则表达式。...

8030

扫码关注云+社区

领取腾讯云代金券