不同函数中定义的变量可以重名两个变量重名怎样覆盖

js中变量名与函数名重名的问题
网上有很多的博客有谈到这个重名的问题,但是我觉得将不算是很全面,至少我看了还是不懂下面这道题到底是怎么回事。那在讲解这个问题的时候,我们先来看看下面这道题,一道面试题(南山西丽xx研究院):
var a = 1;&
function b(){&
function a(){&
console.log(a);&
console.log(a);
这题打印出a的值为多少呢?可能会有很多的同学认为打印出的值为10,但其实并不是,为什么呢?
误区1:变量提升
我想大家都明白,在执行函数b的时候,由于其内部有一句a=10,前面并没有var,所以在执行完函数b之后,认为变量a提升为全局变量,并且10这个值覆盖了之前的1。所以打印出的值为10。我想的话这是多数新手的思路。
这里有个知识点:
显示声明:var a = 1;
隐式声明:a = 1;
隐式声明会变量提升为全局变量
误区2:不知道函数声明也是有提升的
多数新手认为在执行函数b的时候,js执行代码自上往下,执行到return的时候退出函数,不再执行函数a,所以认为这个函数a根本不起作用。
js知识盲区:js预解析与解析变量声明的顺序
js预解析:在执行代码之前,js会预解析代码,代码中如果有变量声明和函数声明的话,那么便将变量声明和函数声明置顶,网上多数人认为函数声明置顶比变量声明置顶更优先。(事实上是如此吗?这里先埋一个坑,稍后再来讨论)
js解析声明变量的顺序:js在解析变量声明的时候,是分为两个步骤的。
比如这句代码:var a =
1;其实是分为(1)(2)a=1;两个解析步骤来进行的。
好,讲完两个知识点,那么我将原代码改写成如下形式:
function b(){&
&function a(){& &//函数声明置顶&
& &console.log(a);&
console.log(a);
那么大家再来看看这段代码,觉得你们心目中的答案是多少呢?若是还是觉得等于10的话,那么就说明你们还没有考虑到本文要讲的重点:重名问题!
在讲解这段代码前,我还要给大家要普及一个知识点:作用域链(若是有不懂的同学,可以查阅链接:https://blog.csdn.net/Charles_Tian/article/details/)。
好,懂作用域链的同学应该明白,在调用变量或者一个对象属性等的时候,查找的顺序是由里向外的,js执行代码是自上往下的。
那么我们再来分析刚才修改过后的代码:
1)先声明变量a,系统给变量a分配一个内存,注意,这里变量a暂时还不知道它的变量类型,因为还没有赋值;
2)a=1,给变量赋值为1,变量类型为number;
3)开始执行函数b,函数b内有一个函数名为a的函数声明,且函数a下面有一个变量名为a的变量,且赋值为10,这里便开始了难点分析。首先看函数a,由于在执行函数b的时候,并没有调用函数a,因此函数a并没有起作用;但是执行到a=10的时候,js是这样做的:1.首先查找变量a的地址,从系统内存中开始按照作用域链查找;2.由于作用域链的查找顺序是由里向外的,故要先从函数b里面开始查找;3.在查找的过程中,发现函数b中已经声明了一个函数名为a的函数(重名问题!),所以查找到函数名为a的函数后,这里便不再往外查找;4.所以这里的a=10其实是将10赋值给了函数名为a的这个函数对象!
有的同学会问为什么了。这样说吧,在函数b里面的时候,函数a提升置顶,跟变量类似(都在js中声明了),Js给这个函数a分配了内存,而恰巧的是在执行a=10的时候,优先查找的是与变量a同名的函数a,因为它所在的作用域最近!讲到这里,我想绝大多数的同学已经明白了这题为什么会打印1了吧?
因为既然a=10这个值10赋值给了函数对象a,那么在全局环境下运行console.log(a),访问的是全局变量a,而全局变量a在系统内存中查找的值为1,所以打印的值为1.
那么同学们可以自行将函数b中的函数a给注释掉,看看打印的结果是什么?看代码:
function b(){
console.log(a);
答案很明显是10,为什么?大多数同学都知道的吧,是的,这里在函数b里的作用域里没有查找到名为a的对象或者变量,那么继续向外查找,发现在全局作用域里发现了有变量a的内存地址,于是将10这个值赋值给了全局变量a。
懂了?好,我们再将代码再修改一次,如下:
function b(){
console.log(a);
这个很简单的吧?打印的值为多少呢?依旧是10对吧,为什么呢?是这样的,在执行函数b的时候,发现有一个隐式声明a=10,它在函数b里的作用域中查找不到有关于名为a的地址,于是向外查找,发现全局作用域下也没有,那么变量提升,系统默认给变量a提供一个内存,并将值赋值给变量a,所以变量a变量提升为全局变量了。所以打印出的值为10.
好,讲完这个,我们继续看看我刚才埋下的坑,现在大家来运行这两段代码:
function&a(){&&
&&console.log(10);&&
console.log(a);
function&a(){&&
&&console.log(10);&&
console.log(a);
运行之后我们会发现,两段代码运行的结果是一样的,均为:function
a(){console.log(a)}。
按之前网上的说法:函数声明置顶比变量声明置顶更优先。那么第二段代码应该打印undefined,可是为什么打印出的却是函数a呢?这个例子是否告诉我们变量声明置顶比函数声明置顶更优先(这个是我同学研究出来的)?这个不得而知,我也不太确定,但是总归一句话,变量赋值肯定是在两个声明的下面的,所以这并不妨碍我们编写代码,或者做面试题。当然如果刚好出了这么一道题,我希望大家把它当特殊例子对待吧。或者可以直接这么记:变量声明置顶比函数声明置顶更优先
变量名与函数名重名的总结:
1.要知道js解析变量声明的顺序
2.函数声明和变量声明会置顶
3.作用域链的查找顺序是由里向外,js执行代码顺序是自上往下
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。发布于 07/12 16:11
大家都知道,所谓重载,就是一组相同的函数名,有不同个数的参数,在使用时调用一个函数名,传入不同参数,根据你的参数个数,来决定使用不同的函数!重载这个在JAVA这些经典的编程语言里面都很好用,可以说调用同一个方法名用不同的参数就可以为所欲为了。
但是我们知道JavaScript中是没有重载的(为什么没重载?不是JAVA的特性JavaScript也会有的吗?),因为后面定义的函数会覆盖前面的同名函数,但是重载那么好用,我们想在JavaScript实现函数重载该怎么办呢?
今天就来给大家讲讲在JavaScript里面实现函数重载的两个思路。(零基础的同学打扰了,这篇不太适合你,需要点面向对象基础。)
第一种方法:
这种方法比较简单,给一个思路,大家肯定都能理解,就是函数内部用switch语句,根据传入参数的个数调用不同的case语句,从而功能上达到重载的效果。
这种方法简单粗暴。但是对于一个正在学习js的人来说,这种方法未免太敷衍了。(那么没技术含量,怎么能让我变成前端开发大神呢?)
下面重点介绍一下第二种,老实说我第一次看的时候很吃力,看了一个小时才捋清楚,因为有的知识点虽然看过了但是不熟悉。(干货很足,别看走神)
第二种方法:
我们这个例子,是如果你不传入参数,就会输出所有的人,输入firstname,就会输出匹配的人,如果输入全名的人,也会输出匹配的人。如果用重载的话,用户体验确实会很好(这个例子是我以前学习时从网上扒下来的,很经典,具有代表性,但是他们都没有写实现过程,所以今天我来给大家说讲一下)
这段代码第一眼看的时候肯定是懵的,再看一次好像有点思路,再看就又懵了。
其实呢,这种方法巧妙的运用了JavaScript的闭包原理(重点),既然js后面的函数会覆盖前面的同名函数,我就强行让所有的函数都留在内存里,等我需要的时候再去找它。
有了这个想法,是不是就想到了闭包,函数外访问函数内的变量,从而使函数留在内存中不被删除。这就是闭包的核心作用。
实现过程:
我们看一下上面这段代码,最重要的是method方法的定义:这个方法中最重要的一点就是这个old,这个old真的很巧妙。它的作用相当于一个指针,指向上一次被调用的method函数,这样说可能有点不太懂,我们根据代码来说,js的解析顺序从上到下为。
  1.解析method(先不管里面的东西)
  2.method(people,"find",function() ) 执行这句的时候,它就回去执行上面定义的方法,然后此时old的值为空,因为你还没有定义过这个函数,所以它此时是undefined。
然后继续执行,这时候我们才定义 obj[name] = function()。
然后js解析的时候发现返回了fnc函数,更重要的是fnc函数里面还调用了method里面的变量,这不就是闭包了!
因为fnc函数的实现是在调用时候才会去实现,所以js就想,这我执行完也不能删除啊,要不外面那个用啥,就留着吧先(此处用apply函数改变了fnc函数内部的this指向)
3.好了第一次method的使用结束了,开始了第二句,method(people,"find",function(firstname) 然后这次使用的时候,又要执行old = obj[name]。
此时的old是什么,是函数了,因为上一条语句定义过了,而且没有删除,那我这次的old实际上指向的是上次定义的方法,它起的作用好像一个指针,指向了上一次定义的 obj[name]。
然后继续往下解析,又是闭包,还得留着。
4.第三句的method调用开始了,同理old指向的是上次定义的 obj[name] 同样也还是闭包,还得留着。
5.到这里,内存中实际上有三个 obj[name],因为三次method的内存都没有删除,这是不是实现了三个函数共存,同时还可以用old将它们联系起来是不是很巧妙
6.我们 people.find() 的时候,就会最先调用最后一次调用method时定义的function,如果参数个数相同 也就是 arguments.length === fnc.length 那么就执行就好了,也不用找别的函数了,如果不相同的话,那就得用到old了 return old.apply(this,arguments);
old指向的是上次method调用时定义的函数,所以我们就去上一次的找,如果找到了,继续执行 arguments.length === fnc.length 如果找不到,再次调用old 继续向上找,只要你定义过,肯定能找到的。
运用闭包的原理使三个函数共存于内存中,old相当于一个指针,指向上一次定义的function,每次调用的时候,决定是否需要寻找。
最后来看看执行输出结果:
执行过程很容易说明这一点:首先第一次调用的时候 old肯定不是函数,所以instance判断是false,继续调用的话就会为true。
然后,我们调用method的顺序,是从没有参数到两个参数,所以我们最先调用find方法,是最后一次method调用时定义的,所以fnc的length长度是2.然后向上找,length为1,最后终于找到了length为0的然后执行,输出。
好了,今天的内容就那么多吧!要是你也喜欢,就转发给更多朋友学习吧!
喜欢的朋友也可以关注我的公众号:网页前端开发学习,发现更多好文哦!
推荐好文:
& 著作权归作者所有
人打赏支持
领取时间:
领取条件:参与过开源中国“源创会”的 OSCer 可以领取
码字总数 8056
js的作用域和java有很大的区别;在一个java类中,类的成员变量不可能和方法新建的变量重名;js则无此问题. 总的来说,js创建对象的作用域的特点有三条: 1.每var 一次 就在当前作用域中添加一个变...
函数 函数的定义 函数的调用 函数名 要遵循驼峰命名法。 不能同名(函数重载),否则后面的函数会覆盖前面的函数。 形参和实参 形参不需要写 var. 形参的个数和实参的个数可以不一致 。 返回...
fengdaoting
函数 函数是JavaScript中任意应用程序的基本构件块。可以在函数基础上建立抽象层,模拟类,信息隐藏,模块。在TypeScript中,虽然已经有类和模块,但函数函数仍然扮演着如何做事的关键角色。...
参数默认值是指在调用函数时,若省略了某个实参,函数会自动为该参数分配一个默认值,使得函数调用的方便性和灵活性大大提高。 举个例子,比如PHP中的字符串截取函数substr(string,start,len...
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程。此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注。在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间...
fengdaoting
jQuery.noConflict()函数用于让出jQuery库对变量$(和变量jQuery)的控制权。 一般情况下,在jQuery库中,变量$是变量jQuery的别名,它们之间是等价的,例如jQuery("p")和$("p")是等价的。由于...
文章截图 - 更好的排版 这一章我们将会重点介绍JavaScript中几个重要的属性(this、constructor、prototype), 这些属性对于我们理解如何实现JavaScript中的类和继承起着至关重要的作用。 ...
javascript 本身虽是一门面向对象的编程语言, 但并没有明确提供继承方式.二十多年间,众多高手提供很多模拟继承的实现, 主要的有:对象冒充,call/apply,prototype,以及深复制等. 网上有很多此类...
前言 WKWebView是iOS8 出来的浏览器控件,用来取代UIWebView.对于WKWebView与UIWebView的对比特点,这里就不过多的叙述,都算是老生常谈的问题了,网上的说明也很多.近来在做Web端,需要植入移动端...
编写Js代码时你是否厌烦了window.alert,window.confirm所弹出来单一的对话框? 接下来的日子里,我们一起来学习利用JS来开发属于自己的js对象。嘿嘿! 老鸟请移步别处,小弟不喜欢被批:) ...
没有更多内容
加载失败,请刷新页面
2017年Python开发大事件年度盘点 作者:马哥教育 来源:http://www.magedu.com/74664.html 在马哥Python的万人学习社群做了个调研,盘点了一下2017年Python的重要事件,希望抛砖引玉。 1.Py...
可分迭代器 package com.example.demo.import java.util.Simport java.util.function.Cimport java.util.stream.IntSimport java.util.stream.Str......
前言 前面写了这么多章节,都是通过浏览器访问的形式,进行接口方法访问进而验证方法的正确与否。显然在服务或者接口比较少时,这么做没有啥问题,但一旦一个项目稍微复杂或者接口方法比较多...
1.冒泡排序 冒泡排序算法运行起来非常慢,但在概念上它是排序算法中最简单的。 以排列一排人员的身高为例: 1.比较两个队员 2.如果左边的队员高,两个队员交换位置 3.向右移动一个位置,比较...
沉迷于编程的小菜菜
安装 #3.4.2sudo apt-get install opencvsudo apt-get install golang-1.9vi ~/.profileexport GOPATH=$HOME/Desktop/GoPathexport PATH=$PATH:$GOPATH/bin:wq!#https://github.c......
SQL优化的思路: 1.优化更需要优化的sql; 2.定位优化对象的性能瓶颈:优化前需了解查询的瓶颈是IO还是CPU,可通过PROFILING很容易定位查询的瓶颈。 3.明确优化目标; 4.从Explain入手; 5....
tt.txt文件内容: &table name="RRR1"& 4.here is need to be repalce content! 5.here is need to be repalce content! 6.here is need to be repalce content! &/table& &table na......
问题后期会有次序的整理,目前整理一小部分 1.部署之后出现403问题。 403权限问题的修改: (1)打开nginx.conf文件 vim /etc/nginx/nginx.conf (2)按键盘“i”进入编辑模式,修改第一行为...
xiaoge2016
大数据在近几年的发展速度确实超出人们的预料,自2014年3月“大数据”首次出现在《政府工作报告》中以来,国务院常务会议一年内6次提 及大数据运用,而且不管是在数博会还是今年的G20当中,大...
转载地址 TypeScript基础入门 - 基础类型 项目实践仓库 https://github.com/durban89/typescript_demo.gittag: 1.0.2 为了保证后面的学习演示需要安装下ts-node,这样后面的每个操作都...
没有更多内容
加载失败,请刷新页面
文章删除后无法恢复,确定取消删除此文章吗?
亲,自荐的博客将通过私信方式通知管理员,优秀的博客文章审核通过后将在博客推荐列表中显示
确定推荐此文章吗?
确定推荐此博主吗?
聚合全网技术文章,根据你的阅读喜好进行个性推荐
指定官方社区
深圳市奥思网络科技有限公司版权所有博客分类:
在页面引用的多个JS文件时,当多个文件中存在相同函数名时,执行的函数是最后一个引用的文件名中的函数。
例如在ABC文件中都有getParams函数时,如果页面引用的顺序是ABC文件.那么在页面中执行getParams函数时,都是执行的C文件中的函数,本人猜想js函数存在函数覆盖问题。
但是我的情况是在AB两js文件中均有getParams函数时,在A中调用getParams函数时,执行的不是A文件中的getParams函数,而是B文件中的getParams函数..请高手指点一二。
window.getParams()这样引用的就是本文件中的函数吗?
wsyinhuaxing
浏览: 1988 次
来自: 珠海
&div class=&quote_title ...
window.getParams()
(window.slotbydup=window.slotbydup || []).push({
id: '4773203',
container: s,
size: '200,200',
display: 'inlay-fix'如何访问被覆盖的同名变量?
[问题点数:20分,结帖人odisey]
本版专家分:203
结帖率 100%
CSDN今日推荐
本版专家分:69
本版专家分:4959
2015年8月 硬件/嵌入开发大版内专家分月排行榜第一2015年7月 VC/MFC大版内专家分月排行榜第一2015年5月 VC/MFC大版内专家分月排行榜第一2015年4月 VC/MFC大版内专家分月排行榜第一2015年3月 VC/MFC大版内专家分月排行榜第一2015年1月 硬件/嵌入开发大版内专家分月排行榜第一2013年12月 VC/MFC大版内专家分月排行榜第一2013年11月 VC/MFC大版内专家分月排行榜第一2013年6月 VB大版内专家分月排行榜第一2013年5月 VB大版内专家分月排行榜第一2013年1月 VB大版内专家分月排行榜第一2012年12月 VB大版内专家分月排行榜第一
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
本版专家分:3614
本版专家分:3614
本版专家分:203
本版专家分:3614
本版专家分:1157
本版专家分:369035
2017年 总版技术专家分年内排行榜第一
2014年 总版技术专家分年内排行榜第二
2013年 总版技术专家分年内排行榜第三
2012年 总版技术专家分年内排行榜第七
本版专家分:4959
2015年8月 硬件/嵌入开发大版内专家分月排行榜第一2015年7月 VC/MFC大版内专家分月排行榜第一2015年5月 VC/MFC大版内专家分月排行榜第一2015年4月 VC/MFC大版内专家分月排行榜第一2015年3月 VC/MFC大版内专家分月排行榜第一2015年1月 硬件/嵌入开发大版内专家分月排行榜第一2013年12月 VC/MFC大版内专家分月排行榜第一2013年11月 VC/MFC大版内专家分月排行榜第一2013年6月 VB大版内专家分月排行榜第一2013年5月 VB大版内专家分月排行榜第一2013年1月 VB大版内专家分月排行榜第一2012年12月 VB大版内专家分月排行榜第一
2015年9月 VC/MFC大版内专家分月排行榜第二2015年7月 硬件/嵌入开发大版内专家分月排行榜第二2014年5月 VC/MFC大版内专家分月排行榜第二2014年3月 VC/MFC大版内专家分月排行榜第二2013年10月 VB大版内专家分月排行榜第二2013年7月 VB大版内专家分月排行榜第二2012年5月 VB大版内专家分月排行榜第二2012年4月 VB大版内专家分月排行榜第二2012年2月 VB大版内专家分月排行榜第二2011年11月 VB大版内专家分月排行榜第二
2015年11月 VC/MFC大版内专家分月排行榜第三2015年6月 VC/MFC大版内专家分月排行榜第三2015年2月 VC/MFC大版内专家分月排行榜第三2014年1月 VC/MFC大版内专家分月排行榜第三2012年3月 VB大版内专家分月排行榜第三2011年12月 VB大版内专家分月排行榜第三2011年10月 VB大版内专家分月排行榜第三
本版专家分:6309
本版专家分:69
本版专家分:69
本版专家分:203
本版专家分:16913
本版专家分:197
本版专家分:203
本版专家分:203
本版专家分:336
本版专家分:197
本版专家分:1157
本版专家分:1157
本版专家分:14613
本版专家分:203
本版专家分:203
本版专家分:0
本版专家分:203
本版专家分:203
本版专家分:297
本版专家分:16913
本版专家分:18975
本版专家分:18975
本版专家分:203
本版专家分:203
本版专家分:2058
匿名用户不能发表回复!|
其他相关推荐31 条评论分享收藏感谢收起ecma-international.org/ecma-262/6.0/#sec-functiondeclarationinstantiation27. If hasParameterExpressions is false, thena. NOTE Only a single lexical environment is needed for the parameters and top-level vars.b. Let instantiatedVarNames be a copy of the List parameterNames.c. For each n in varNames, doi. If n is not an element of instantiatedVarNames, then1. Append n to instantiatedVarNames.2. Let status be envRec.CreateMutableBinding(n).3. Assert: status is never an abrupt completion.4. Call envRec.InitializeBinding(n, undefined).d. Let varEnv be env.e. Let varEnvRec be envRec.按这个流程走一遍,可以发现在运行时,func1等同于function func1(){
var v = 'ccc';
console.log("v:",v);
v = 'bbb';
var是比较简单的情况,如果涉及到let / const / 默认参数那就略复杂一些了。赞同 2添加评论分享收藏感谢收起写回答

我要回帖

更多关于 java 同一个函数声明重名变量 的文章

 

随机推荐