javascript连等赋值法, var a = b = 3, 你真的懂么

相信大家很多时候会遇到这样定义变量的方法:var a = b = 3; 结果大家也都知道,a b的值都是3,但是他们有什么区别呢?

 

 var a = b = 3;发生了什么?

  说这个问题之前,我们先了解一些基础知识

声明

JavaScript中有六条声明用的语句:

  1. let x
  2. const x
  3. var x
  4. function x
  5. class
  6. import

除了这6种声明语句之外,还有两个语句可以隐式声明标识符

  1. for ()
  2. try ... catch(x) {}

 

除了这几种声明方法,再没有别的方法可以声明一个标识符,并且声明有以下两个特点:

1 意味着JavaScript将可以通过"静态"语法分析发现那些声明的标识符

2 标识符对应的变量“一定”会在用户代码执行前已经被创建在作用域中

 读取值到赋值

声明是在语法分析阶段处理的,所以代码执行的时候,肯定是可以保证已经存在了。

var 声明的标识符被约定称为"变量声明varDelcs", 并且有初始值undefined,而"let、const"则称为"词法声明(lexicalDelcs)", 没有初始值

其实函数声明是varDelcs, class内部是let, import是const规则

 

赋值的正确表达式是:

lRef = rValue

将右操作数的值赋给左做操作数的引用,严格表达应该是:

LeftHandSideExpression < = | AssignmentOperator> AssignmentExpression

向一个不存在的变量赋值

ES6之前向一个不存在的变量赋值,结果是:JavaScript 会在全局范围内创建它,这带来的副作用是造成“变量泄漏

当向一个不存在的变量赋值的时候,由于全局对象的属性表是可以动态添加的,因此 JavaScript 将变量名作为属性名添加给全局对象。而访问所谓全局变量时,就是访问这个全局对象的属性

使用var声明的变量和动态添加 到全局对象的属性有什么不一样呢?

var a = 100;
x = 200;

// `a`和`x`都是global的属性
Object.getOwnPropertyDescriptor(window, 'a');
// { value: 100, writable: true, enumerable: true, configurable: false }
Object.getOwnPropertyDescriptor(window, 'x');
// { value: 200, writable: true, enumerable: true, configurable: true }

//  `a`不能删除, `x`可以被删除
delete a; // false

delete x; // true

a; // 100

x; // ReferenceError: x is not defined

从上面的代码可以看到:表面上使用var声明的全局变量,和泄漏到全局的全局变量,都是全局变量

并且都实现为window的属性,但事实上还是有不同,能不能删除和该属性的configurable有关系

 

回到正题

现在回到今天讨论的这行代码var x = y = 100,在这行代码中,等号的右边是一个表达式y = 100,它发生了一次“向不存在的变量赋值”,所以它隐式地声明了一个全局变量y,并赋值为 100。

赋值表达式操作本身也是有结果的,是右操作数的值,但也只是值,不是引用, 下面的例子中,a是一个函数


// 调用obj.f()时将检测this是不是原始的obj
> obj = { f: function() { return this === obj } };

// false,表明赋值表达式的“结果(result)”只是右侧操作数的值,即函数f
> (a = obj.f)();
false

 

声明和语句的区别在于发生的时间点不同,声明发生在编译期,语句发生在运行期。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值