全局变量名、局部变量名和形参名冲突时,覆盖情况

以前错误的认为,全局变量名、局部变量名和形参名相同时,全局变量(也就是外部变量)被形参覆盖,形参被局部变量覆盖。

今天发现这样理解并不对。比如

function foo(num){
  var num;
  console.log(num);
}
foo(1)   //  1

//如果错误的理解为局部变量会覆盖形参的话,会认为会输出undefined

那事实是什么呢。实际上变量名冲突分两种,一种是函数外的变量和函数里的局部变量的冲突,一种是函数内部的冲突。

第一种冲突,我把它理解为是作用域链的上游(最上游是全局对象的命名空间)会被下游函数的局部变量覆盖。

其实我觉得这就是一种继承关系,好比原型链里离目标对象近的新的方法覆盖远的旧的方法,甚至是好比HTML/CSS里字体、颜色等属性的继承。

只不过这里继承的是一个上下文环境。

它们都有一个特点,自己有,用自己的;自己没有,用父级的;父级没有,再逐级向上。

//和HTML/CSS属性继承不同的是,JS作用域链还涉及变量/函数声明

//简单说,就是子元素一旦声明了变量,不管有没有赋值,都算做是有自己的了
//也就不会操作到父级了

var b;
function foo2() {
    console.log(b);
    var b;
}
foo2();//undefined

第二中是函数内部的冲突,即同一作用域内的冲突。

形参和局部变量其实就是同一作用域的。只不过JS里的形参省略了声明(像是Java就需要和变量一样做类型声明)。

而在JS里有:同一作用域,重复申明但不赋值,不会对变量有影响

var a=1;
console.log(a);  //1
var a;
console.log(a);  //1

这也就解释了,为什么局部变量申明但不赋值,不影响形参。

或许你会有我之前的另一种猜测,局部变量声明但不赋值,不会覆盖形参,但赋值了不是改变形参,而是覆盖。

那我们再看看这个

var b;
function foo2(b) {
    var b=2;
    console.log(b);
    console.log(arguments[0]);
}
foo2(1);

//假如是局部变量名覆盖形参名的话,那应该打印‘2 1‘
//而事实是‘2 2‘
//所以其实局部变量和形参冲突,就是重复定义个变量
//所以我觉得其实可以把形参理解为一个特殊的局部变量
//只不过它在函数定义时被申明,而且申明的var 被省略
function foo2(var b){
}
时间: 2024-10-07 03:30:31

全局变量名、局部变量名和形参名冲突时,覆盖情况的相关文章

c语言全局变量与局部变量(当变量重名时)的使用情况

在c语言中,变量有全局变量和局部变量之分,这一点和很多高级语言类似,如c#,java等.不过与c#,java中的局部变量如在全局变量作用域内则不允许与全局变量名相同,而c语言是允许这样做的.这样的做法极不提倡,但是c语言既然允许这么做,就分析一下其变量名相同时在不同位置调用该变量名时所实际调用的是哪个变量值. 代码如下: #include <stdio.h> //全局变量 //作用域:从定义开始到文件结束 //默认初始值为0 int c = 1; int test() { int c = 2;

MyBatis学习总结(四)——解决字段名与实体类属性名不相同的冲突

在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体类属性名不相同的冲突. 一.准备演示需要使用的表和数据 CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSERT INTO orders(order_no, order_price) VALUES('aaaa'

MyBatis——解决字段名与实体类属性名不相同的冲突

原文:http://www.cnblogs.com/xdp-gacl/p/4264425.html 在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体类属性名不相同的冲突. 一.准备演示需要使用的表和数据 CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSER

Mybatis解决字段名与实体类属性名不相同的冲突

在平时的开发中,我们表中的字段名和表对应实体类的属性名称不一定都是完全相同的,下面来演示一下这种情况下的如何解决字段名与实体类属性名不相同的冲突. 一.准备演示需要使用的表和数据 CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSERT INTO orders(order_no, order_price) VALUES('aaaa'

尚硅谷-mybatis-解决字段名与实体类属性名不相同的冲突

项目结构: 准备表和数据: CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23); INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33); INSERT

idea取消参数名称(形参名)提示

idea取消参数名称(形参名)提示 IDEA会自动显示形式参数的变量名称,这在一开始使用时感觉很方便,友好.有时候也会显得排版很乱,下面是取消自动显示形式参数名称的方式 取消前是这个样子. "File" -> "Settings" "Editor" -> "General" -> "Appearance" 把"Show parameter name hints"选项前面

小发现: C/C++函数形参名可加括号

有一次我发现下面这段代码无法通过编译. #include <iostream> using namespace std; struct A { A(int n) {} }; struct B { B(A a) {} int foo() const { return 1; } }; int main() { int n = 1; B b(A(n)); cout << b.foo() << endl; } 错误信息如下. 错误信息显示b是一个非类类型对象.但是我看了半天都不

MyBatis学习总结_04_解决字段名与实体类属性名不相同的冲突

一.准备演示需要使用的表和数据 CREATE TABLE orders( order_id INT PRIMARY KEY AUTO_INCREMENT, order_no VARCHAR(20), order_price FLOAT ); INSERT INTO orders(order_no, order_price) VALUES('aaaa', 23); INSERT INTO orders(order_no, order_price) VALUES('bbbb', 33); INSER

myBatis-- 字段名与实体类属性名冲突解决办法

一.创建订单表 order_id         order_name          order_price 1                        苹果                      6.5 2                        香蕉                        3 3.                       桔子                         2 二.定义实体类 public Order { private In