精华内容
下载资源
问答
  • js在执行时会对相同变量宣告作归纳的处理,以最近的变量指定作为变量在执行时的值。以第一例来说,第二行的 var a 只是个宣告,而不是赋值,除非在执行前的语句,都没有对a变量赋值的其他语句,a才会被js引擎当作...

    原文:https://segmentfault.com/q/1010000007278354?_ea=1295176

    问题:

    function f1(a) {
        console.log(a);// 10;  这里我开始觉得是undefined的
        // 我以为var a=1会先把var a=undefined 放在函数的最前面 但是好像并没有
        var a=1;
        console.log(a);// 1 
        console.log(arguments[0])// 1;  这里我觉得也是10
    }
    f1(10)
    按照f1这个打印看来 var 声明的a 好像和形参a是有联系的 但是他们不是应该没有联系吗?
    function f2(a) {
        console.log(a); //10
        var a;
        console.log(a);//10
        console.log(arguments[0])//10
    }
    f2(10)
    f2 里面的a好像什么事都没做
    


    这个问题所造成的结果,主要有两个源头,一个是函数中的arguments对象,另一个是变量在函数中的提升。

    函数中的arguments对象

    先看arguments对象,它是个函数中的隐性对象,是一个类数组(array-like)的对象。它有一些特性在这里看到,实际都是很细的特性,以下几个例子来说明:

    第一个例子是一般函数,只是把传入的形参(参数)输出在主控台:

    function foo(a, b){
       console.log(a, b); //1, 10
    }
    
    foo(1, 10); 

    a与b改为用arguments,这很正常的用法如下:

    function foo(a, b){
       console.log(arguments[0], arguments[1]); //1, 10
    }
    
    foo(1, 10);

    在函数中改arguments对象中的值,对原本的a与b会不会一起更动。有。:

    function foo(a, b){
       arguments[0] = 9;
       arguments[1] = 99;
       console.log(a, b); //9, 99
    }
    
    foo(1, 10);

    在函数中改a与b的值,对arguments对象中的值会不会一起更动。有。:

    function foo(a, b){
       a = 8;
       b = 88;
       console.log(arguments[0], arguments[1]); //8, 88
    }
    
    foo(1, 10);

    题外话,另一个新特性是加上ES6(ES2015)的函数参数的预设值,只要用了这个特性,arguments必无法再改变形参:

    function foo(a=1, b=10){
       arguments[0] = 9;
       arguments[1] = 99;
       console.log(a, b); //1, 10
    }
    
    foo();

    函数中的变数提升(Hoisting)

    变数提升是只提升定义,赋值(指定值)部份不会提升。以下为简单的例子,在函数中也是同样的情况:

    console.log(x); //undefined,而不是报错
    var x = 5;

    相等于下面这样:

    var x;
    console.log(x);
    x = 5;

    解题

    第一个函数

    问题的第一例的代码是像下面这样,我把注解先去掉:

    function f1(a) {
        console.log(a);
        var a=1;
        console.log(a);
        console.log(arguments[0]);
    }
    
    f1(10)

    f1中首先看到的是var的变数提升,所以在执行时,第1个console.log(a)前面,应该会有var a的定义出现,但没有赋值部份。这里可以先写出在a=1之后的console.log(a)必然是1,然后根据上面关于arguments对象的测试结果,最后一个也是输出1

    function f1(a) {
        var a;
        console.log(a);
        a=1;
        console.log(a); //1
        console.log(arguments[0]); //1
    }
    
    f1(10)

    另一个问题来了,a以10传入时,遇到一个var a,会变为undefined吗?先说结论,结论是"不会"。

    在js中对于变量的宣告,是对剖析器的指示(directive),而不是在执行期的命令(command),不要忘了js是个直译式的脚本语言,所有的真实执行,是由js引擎中的剖析器(或分析器),先对代码作整理剖析完了,才会执行。有个最明显的特性是变量的类型是动态的,要看赋给变量什么值,才会决定这个变量的类型,你给变量一个数字,变量就变为数字类型,给它个字串,它就是个字串类型。

    那么,像这里的重覆宣告,js又是怎么认为的?看下面的例子:

    //第一例
    var a = 10;
    var a;
    console.log(a); //10
    
    //第二例
    var b = 10;
    var b = undefined;
    console.log(b); //undefined

    js在执行时会对相同变量宣告作归纳的处理,以最近的变量指定作为变量在执行时的值。以第一例来说,第二行的var a只是个宣告,而不是赋值,除非在执行前的语句,都没有对a变量赋值的其他语句,a才会被js引擎当作undefined值,也就是"不知道是什么东西,没定义"。第二例则是直接赋给b变量个undefined,js引擎当然是就认为b是个undefined类型。

    所以,以本问题的在函数中的第一个console.log(a);来说,它a的值是10,而不是你认为的undefined

    第二个函数

    function f2(a) {
        console.log(a); 
        var a;
        console.log(a);
        console.log(arguments[0])
    }
    f2(10)

    这个函数也一样有变量提升,所以相当于下面的代码:

    function f2(a) {
        var a;
        console.log(a); 
        console.log(a);
        console.log(arguments[0])
    }
    f2(10)

    依照第一个函数的最后说明,变量宣告var a被合并(归纳)掉,所以全部的console.log都是打印出10,收工。

    风格建议

    这个例子可以看出几个建议的撰写风格。

    第1: 变量的宣告都要在函数的最上面,提高可阅读性以避免在执行语句中间宣告。
    第2: 不要重覆宣告变量,尤其常见是在for语句中。用var宣告的变量作用域是以函数为分界,而不是区域语句(for、if…)。
    第2: 不要在函数的区块中间,宣告与形参同名的变量。除非你很确定在这是什么与在作什么,形参预设值自然有预设值的写法。
    第3: 不要再用arguments对象,它的行为是怪异的,而且设计有问题,又是"隐性"对象。与其你花时间研究它,不如把时间花在学其馀参数写法。arguments对象是js中有名的坏设计,连js的发明者都自己说了,参考:https://brendaneich.com/2011/...


    展开全文
  • 形参局部变量相同且局部变量有赋值时,局部变量的赋值会覆盖形参的值。 function fn ( a ) { console . log ( a ) ; // 1 console . log ( arguments [ 0 ] ) ; // 1 var a = 2 ; ...

    前几天遇到一个问题,大致就是形参名与局部变量名相同了,导致后续代码取值出错。唉,感觉大多数的坑都可以归结为基础知识的不扎实啊。

    当形参与局部变量相同且局部变量有赋值时,局部变量的赋值会覆盖形参的值。

    function fn(a) {
        console.log(a); // 1
        console.log(arguments[0]); // 1
    
        var a = 2;
    
        console.log(a); // 2
        console.log(arguments[0]); // 2
    }
    
    fn(1)
    

    这里,当改变函数形参的值时,arguments对象中的值也会一起变动。

    当形参与局部变量相同且局部变量只有声明时,js不会覆盖局部变量。

    function fn(a) {
        console.log(a); // 1
        console.log(arguments[0]); // 1
    
        var a;
    
        console.log(a); // 是 1 不是 undefined
        console.log(arguments[0]); // 1
    }
    
    fn(1)
    

    强行解释一波

    var a = 1;
    

    当机器执行上边代码时,其实分两步执行。

    var a; // 声明提升
    a = 1; // 变量赋值
    

    js执行时,除非在执行前的语句,都没有对a变量赋值的其他语句,a才会被js引擎当作undefined值。

    所以这里当遇到var a时,js只是做了声明,并没有赋值,就不会出现a为undefined的情况了。

    展开全文
  • #include int d(int s){  int s = 9;  return s; } int main(void) {  printf("test");...提示出错,形参和局部变量一样,c语言的函数执行时形参先入栈,然后是eip,ebp等指针入栈,局部变量最后入栈。
    #include <stdio.h>
    int d(int s){
        int s = 9;
        return s;
    }
    int main(void) { 
    printf("test");
    printf("%d",d(2));
    return 0;

    }

    提示出错,形参和局部变量一样,c语言的函数执行时形参先入栈,然后是eip,ebp等指针入栈,局部变量最后入栈。

    展开全文
  • 实参、形参局部变量和全局变量

    千次阅读 2020-09-15 16:53:39
    目录实参和形参实参数据传递函数调用过程形参实参和形参的关系局部变量和全局变量局部变量局部变量的作用域说明:全局变量全局变量说明: 实参和形参 实参 实际参数简称“实参”。在调用有参函数时,函数后面括号...

    实参和形参

    实参

    实际参数简称“实参”。在调用有参函数时,函数名后面括号中的参数称为“实际参数”,实参可以是常量、变量或表达式。

    在调用有参函数时,主调函数和被调函数之间有数据传递关系。在主调函数中调用一个函数时,函数名后面括号中的参数称为“实际参数”(简称“实参”)。

    实参可以是常量、变量或表达式, 无论实参是何种类型的量,在进行函数调用时,它们都必须具有确定的值, 以便把这些值传送给形参。 因此应预先用赋值,输入等办法使实参获得确定值。

    数据传递

    在调用函数过程中,系统会把实参的值传递给被调用函数的形参。或者说,形参从实参得到一个值。该值在函数调用期间有效,可以参加该函数中的运算。

    在调用函数过程中发生的实参与形参间的数据传递,常称为“虚实结合”。

    函数调用过程

    1. 函数的形参列于函数声明中,在函数定义的函数体内使用。在未出现函数调用时,形参不占内存中的存储单元;当函数调用时,形参(任何种类的)是一类将被填充的空白或是占位符。
    2. 将实参的值传递给形参。当函数被调用时,实参列在函数名后面的括号里。执行函数调用时,实参被传递给形参。
    3. 在执行函数期间,由于形参已经有值,可以利用其进行相关运算。
    4. 通过return语句将函数值带回到主调函数。
    5. 调用结束,形参单元被释放。实参单元仍保留并维持原值(值传递)。

    形参

    全称为“形式参数”是在定义函数名和函数体的时候使用的参数,目的是用来接收调用该函数时传递的参数。

    形参的作用是实现主调函数与被调函数之间的联系,通常将函数所处理的数据,影响函数功能的因素或者函数处理的结果作为形参。

    没有形参的函数在形参表的位置应该写void.main 函数也可以有形参和返回值,其形参也称为命令行参数,由操作系统在启动程序时初始化,其返回值传递给操作系统。

    实参和形参的关系

    1. 形参变量只有在被调用时才分配内存单元,在调用结束时,即刻释放所分配的内存单元。因此,形参只在函数内部有效。函数调用结束返回主调用函数后则不能再使用该形参变量。
    2. 实参可以是常量、变量、表达式、函数等,无论实参是何种类型的量,在进行函数调用时,它们都必须有确定的值,以便把这些值传送给形参。因此应预先用赋值,输入等办法使参数获得确定值。
    3. 实参和形参在数量上,类型上、顺序上应严格一致,否则就会发生类型不匹配的错误。
    4. 在一般传值调用的机制中只能把实参传送给形参,而不能把形参的值反向地传送给实参。因此在函数调用过程中,形参值发生改变,而实参中的值不会变化。而在引用调用的机制当中是将实参引用的地址传递给了形参,所以任何发生在形参上的改变实际上也发生在实参变量上。

    局部变量和全局变量

    局部变量

    局部变量,也称内部变量,是指在一个函数内部或复合语句内部定义的变量。

    局部变量的作用域是定义该变量的函数或定义该变量的复合语句。局部变量的生存期是从函数被调用的时刻算起到函数返回调用处的时刻结束。

    int f1(int a)
    {
    int b,c;
    ……
    }a,b,c作用域
    main()
    {
    int m,n;
    }

    在函数f1内定义了三个变量,a为形参,b,c为一般变量。在f1的范围内a,b,c有效,或者说a,b,c变量的作用域限于f1内。m,n作用域 m,n的作用域限于main函数内。

    局部变量的作用域说明:

    1. 主函数中定义的变量也只能在主函数中使用,不能在其它函数中使用。同时,主函数中也不能使用其它函数中定义的变量。因为主函数也是一个函数,它与其它函数是平行关系。这一点是与其它语言不同的,应予以注意。
    2. 形参变量是属于被调函数的局部变量,实参变量是属于主调函数的局部变量。
    3. 允许在不同的函数中使用相同的变量名,它们代表不同的对象,分配不同的单元,互不干扰,也不会发生混淆。形参和实参的变量名都为n,是完全允许的。
    4. 在复合语句中也可定义变量,其作用域只在复合语句范围内。

    全局变量

    全局变量也称外部变量,它是在函数外部定义的变量。它不属于哪一个函数,而是属于一个源程序文件:其作用域是整个源程序。

    几乎程序中的所有函数都能使用全局变量,客观上全局变量就起到了在函数间传递数据的作用,甚至可以减少形参和实参的数量。当然在享用它的好处时,也要慎重,避免全局变量过多带来的降低函数通用性及存储空间的浪费。

    全局变量说明:

    1. 全局变量从程序运行起即占据内存,在程序整个运行过程中可随时访问,程序退出时释放内存。与之对应的局部变量在进入语句块时获得内存,仅能由语句块内的语句访问,退出语句块时释放内存,不再有效。
    2. 局部变量定义后不会自动初始化,除非程序员指定初值。全局变量在程序员不指定初值的情况下自动初始化为零。
    3. 在同一源文件中,允许全局变量和局部变量同名。在局部变量的作用域内,全局变量不起作用。
    int a,b;
    void f1()
    {
    ……
    }
    float x,y;
    int f2()
    {
    ……
    }
    main()
    {
    ……
    }

    从上例可以看出a、b、x、y 都是在函数外部定义的外部变量,都是全局变量。但x,y定义在函数f1之后,而在f1内又无对x,y的说明,所以它们在f1内无效。a,b定义在源程序最前面,因此在f1,f2及main内不加说明也可使用。

    展开全文
  • 2、形参和内部同名变量是同一个参数; function f1(a) {//相当于首先var a=10; console.log(a);// 10; var a=1; console.log(a);// 1 console.log(arguments[0])// 1; } f1(10) var x=2,y=0,...
  • 以前错误的认为,全局变量名、局部变量名和形参相同时,全局变量(也就是外部变量)被形参覆盖,形参局部变量覆盖。 今天发现这样理解并不对。比如 function foo(num){ var num; console.log(num); } ...
  • 举个简单的函数例子 function getNum(num){  num =100;  console.log(num); ...结果是:100Uncaught ...虽然在函数中声明了一个隐式全局变量,可是函数的形参跟隐式全局变量的名字是相同的,而函数...
  • cout cout 编译器分配的局部栈变量是自动释放的,堆变量则必须自己释放。 这些对象变量实际上是指向实例的指针,过程...“我想请问MystringList这个变量应该属于局部变量吧”这个myStringList当然是局部变量
  • 一道面试题引发的问题,首先要知道[]的优先级高于*,题目: char **p,a[6][8];...指针做形参,指针做局部变量,数组做形参,数组做局部变量之类的题目非常容易考到,而且容易迷糊,得不断学习...
  • c语言中形参与实参: 形参 form parameter ...//在函数中,形参就可以当作是一个局部变量。 if ( a>b ) return a; else return b; } 函数调用 int main() { int a=3,b=5 ; printf( "max=%d\n" , max(a,b) )
  • function xxx(id){ var id = 9;...js中,执行一个函数时,形参和局部变量是存在一个活动对象里的,或者叫变量对象,如果在局部变量中定义了一个和形参相同名字的变量,编译器会忽略这个定义,而所有对
  • 1.相同点: **1.1定义变量的格式:**数据类型 变量=变量值 ...**局部变量:**声明在方法、方法形参、代码块内、构造器形参、构造器内部的变量。 class User{ public void talk(String language){
  • 在我们自己写代码时,一般不会做这种蠢事情,把形参和局部变量定义为同名,可如果真的这样做了呢? 那就要分析下JS执行上下文中的变量对象了,这个知识点不牢固的同学可以移步这里:重拾ECMAScript基础——变量、...
  • 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量 2.2 关于权限修饰符的不同 成员变量:可以在声明成员变量时,指明其权限,使用权限修饰符。 常用的权限修饰符:private、public...
  • 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内部的变量 2.2 关于权限修饰符的不同 属性:可以在声明属性时,指明其权限,使用权限修饰符。 常用的权限修饰符:private、public、
  • 一个完整的方法通常包括方法名称、方法主体、方法参数方法返回值类型,其结构如图 1 所示。 图1 方法组成元素 成员方法一旦被定义,便可以在程序中多次调用,提高了编程效率。声明成员方法的语法格式如下: ...
  • 关于java成员变量和局部变量

    万次阅读 多人点赞 2018-09-14 10:46:45
    1、成员变量和局部变量简述 在Java语言里,根据定义变量位置的不同,可以将变量分成两大类:成员变量(存在于堆内存中,类一起创建)和局部变量(存在于栈内存中,当方法执行完成,让出内存,让其他方法来使用内存)...
  • 成员变量与局部变量相同点与不同点(易错) package com.happy.bean; /* * 成员变量与局部变量的相同点与不同点、 * * (1)相同点 * ①定义变量的格式:数据类型 变量 = 变量值 * ②先声明,后使用 * ③变量都...
  • 成员变量和局部变量同名 在同一个作用域内不允许定义同名的多个变量。   在一个方法内,可以定义成员变量同名的局部变量或参数,此时成员变量被屏蔽。此时如果想要访问成员变量,可以通过 this 关键字来...
  • Java成员变量与局部变量 文章目录Java成员变量与局部变量1 相同点2 不同点 1 相同点 ...​ 局部变量:声明在方法内、方法形参、代码块内、构造器形参、构造器内 class Person{ /* 这两个是成员变量
  • 变量名、函数形参相同的情况

    千次阅读 2018-02-26 19:08:08
    1. 变量和函数重名时,如果变量声明未赋值,则变量名被忽略,取函数(function (a) { console.log(a); var a = 10; function a(){} }( 100 ))结果:function a(){}2.(function (a) { console.log(a); var a = ...
  • 成员变量和局部变量

    2019-11-26 17:48:21
    局部变量:声明在方法内,方法的形参部分,代码块内 2.成员变量的修饰符有四个:public private protected 缺省 局部变量没有修饰符,与所在的方法修饰符相同。 3.初始化值:一定会有初始化值。 成员变量:如...
  • 1.标识符命名规则: 定义 就是给类,接口,方法,变量等起名字的字符序列 组成规则 英文大小写字母数字$_ ...形参可以是常量,变量或表达式 实参可以为任何类型 形参应与其对应的实参类型一
  • 在讨论函数的形参变量时曾经提到,形参变量只在被调用期间才分配内存单元,调用结束立即释放。...C语言中的变量,按作用域范围可分为两种,即局部变量和全局变量。 8.1.1局部变量  局部变量也称为内部变

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 45,246
精华内容 18,098
关键字:

形参和局部变量名相同