对于js操作符的一些特性和有趣题目的整理。
逗号操作符有两个作用,一个是用于当你想要在期望一个表达式的位置包含多个表达式时,可以使用逗号操作符。这个操作符最常用的一种情况是:for 循环中提供多个参数。另一个使用逗号操作符的例子是在返回值前处理一些操作。如同下面的代码,只有最后一个表达式被返回,其他的都只是被求值。
function myFunc () {
var x = 0;
return (x += 1, x); // the same of return ++x;
}
赋值多个变量用var a = 3, b = 4, c = 5;和var a = 3; var b = 4; var c = 5;本质并没有什么不同,只是一种编码习惯,用知乎上一位朋友的话说,前者是高耦合,低冗余,后者是低耦合,高冗余,后者更严谨一点,在维护的时候也不容易出错。
关于逗号的第二个用法,有时会引起一些现象,比如下面的代码就改变了函数中的this指向,因为表达式(0, obj.fun)返回了obj.fun的引用,相当于window调用这个函数,所以this发生了变化:
var obj = {
fun: function () {
console.log(this);
}
}
obj.fun(); //输出obj
(0, obj.fun)() //输出window对象
我的赋值是可以用链式的方法把一个值赋值给多个变量,当所有变量都被声明,这样做并没有什么问题,但是如果是函数作用域内这样做有时候会引起一些奇怪的现象:
function test() {
var a;
a = b = 3;
}
test();
console.log(b); //3
console.log(a); //报错
从结果我们可以看出b成为了一个全局变量,要明白原因我们先要知道js引擎是如何解析a = b =3;这条表达式的,我们知道赋值是基于右值的值给左值赋值。根据这个规则我们可以知道,引擎的第一步是把a当作左值,b = 3当作右值,因为b = 3是一个表达式,算出值以后才能赋值,所以计算b = 3的值,此时引擎发现变量b并没有声明,也就是在当前执行环境的变量对象找不到这个变量,于是b被处理成了var b = 3,成了一个全局变量。
变量声明提前不能跨<script>标签,更不能跨文件,也就是说变量提升仅仅是把当前js文件或标签中的var声明变量或function的声明提升到当前文件或标签的开头。并且当函数和变量重名的时候,被提升的声明会是函数。
上面的代码赋值表达式的右值都是js的基本类型,如果右值是对象的时候,情况会更复杂一些。因为对象被保存在堆中,我们对对象的赋值只是把对象的引用赋值给变量,而引用的变化不会引起对象的变化,堆中的对象不会因为变量之间引用的传递而发生改变,记住这一点就不太容易被迷惑。不过有时候情况比我们想象的还要复杂一下,比如下面这道经典的题目:
var a = {n: 1};
var b = a;
a.x = a = {n: 2};
console.log(a.x);//undefined
console.log(b.x);//{n: 2};
如果用上面那一套方式来想这道题,第一步左值为a.x,右值为a = {n: 1},第二步计算a = {n: 2},左值为a,右值为{n: 2},把{n: 2}的引用给a就可以了,然后赋值给第一步的左值,得到结果a.x = {n: 2}。流程其实没什么问题,但是在第一步的时候忘记一件事,就是a对象并没有x属性,而且.运算符的优先级是仅次于括号的,在还没开始进行赋值分析的时候,已经对a.x进行了处理,就是在a对象中加入x属性,虽然此时并没有对该属性初始化,a.x应该为undefined。有了这个思路我们再按刚才的流程走一遍,当完成第二步a = {n: 2}的时候a的引用已经改变,此时a.x代表的是{n:1, x: undefined}中的x(可能有人疑惑a已经改变引用,a.x中的a应该也变了,但因为a.x和a在同一个表达式内,a.x已经在前面被引擎解析,a.x此时应被理解成堆中对象的属性),最后把这个{n: 2}的引用赋给x属性。
我们可以发现赋值运算的解析是从左向右,但是计算是从右向左的。链式赋值有时候会遇到这样的副作用,所以还是尽量避免使用。
原文来自:https://www.clloz.com/programming/front-end/js/2019/04/23/js-operator-supplements/
剩余操作符和展开操作符的表示方式一样,都是三个点 \\\'...\\\',但是他们的使用场景会不同。定义函数的时候,如果函数的参数以… 为前缀,则改参数是剩余参数(rest parameter)。剩余参数表示参数个数不确定的参数列表
本文主要讲Gabriel Isenberg撰写的ES提案“Nullish coalescing for JavaScript”。 它提出?? 替换||的运算符,并提供默认值。这里先把这相提案叫作双问号操作符,双问号 ?? 的操作符跟 || 类似,如果给定变量值为 null 或者 undefined
ES6 新增了...操作符,通常用于在函数中提取剩余参数和展开数组。但其实它的用途不止于此,本文就介绍几个技巧,用它来操作 JavaScript 对象。复制对象的同时,为其添加新的属性。例子中复制了user对象到userWithPass,并添加了 password 属性。
delete操作符用于删除对象的某个属性;如果没有指向这个属性的引用,那它最终会被释放。对于所有情况都是true,除非属性是一个自己不可配置的属性,在这种情况下
在 TypeScript 中, typeof 操作符可以用来获取一个变量或对象的类型。在上面代码中,我们通过 typeof 操作符获取 sem 变量的类型并赋值给 Sem 类型变量,之后我们就可以使用 Sem 类型
JS 里的操作符大家每天都在使用,还有一些 ES2020、ES2021 新加的实用操作符,这些共同构成了 JS 灵活的语法生态。本文除介绍常用的操作符之外
?.和??估计是Javascript两个最为有用并且最经常被忽略的操作符了。这两个操作符最大的作用,就是对于undefined和null的应对,在没有lodash等库的情况下,直接桶过Javascript自身的机制就可以很大的程度上提高程序的健壮性。
上述代码规定 staffCount 是一个对象,属性名为 roles 约束的三个,值为 number 类型:类型变量 k,以此绑定到对象的每一个属性,遍历三个字符串字面量组成的联合类型 roles,number 为每个属性的值的类型
这是一个普通的 JavaScript 对象,在 TypeScript 中你可以使用 type 或 interface 来定义该对象的类型。有了该对象类型之后,你就可以利用 TypeScript 内置的工具类型
与逻辑或操作符(||)不同,逻辑或操作符会在左侧操作数为假值时返回右侧操作数。也就是说,如果使用 || 来为某些变量设置默认值,可能会遇到意料之外的行为。比如为假值(例如0)时。见下面的例子。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!