运算符
赋值运算符
**赋值操作简单分为三类:
- 简单赋值
- 复合赋值
- 解构赋值(这种功能类似于perl和python等语言中存在的特性)
//最简单的赋值运算是'='
x=y
//表示将右边的操作数的值赋给他左边的操作数,也就是y赋值给x
//而复合赋值运算则是,搭配着各类运算符后的赋值操作,让我们在赋值的同时执行运算,例如:
x +=y
x<<=y # 左移位赋值,x = x << y
x&=y # 按位与赋值,x = x & y
x &&= f() # 逻辑与赋值,x && (x = f())
// 结构赋值比较特殊,它是从数组或对象对应的结构中,或字面量中提取数据的js表达式
//取值时,解构赋值使用与数组和对象类似的语法,并从中取值,数组会按照次序取值,而对象则会根据检索在对应对象中的属性名来取值,数据类型为值的数据类型
const obj = { a: 1, x: 2 };
const { x, b } = obj; # x=2,b=undefined
// is equivalent to:
// const a = obj.a;
// const b = obj.b;
const z = [1,2,'string']
const [a,u,...ok] =z # a=1,u=2,...ok=string
console.log(typeof x)
console.log(typeof obj)
console.log(...ok)
console.log(typeof a)
> "number"
> "object"
> "string"
> "number"
解构赋值:绑定与赋值
由于解构赋值的内容过于丰富,所以除去上面讲述的内容以外,在这里单独开一个标题来讲述,解构赋值的作用是让我们可以从完整的某一种结构且不影响该结构中的数据时,从中获取到我们想要的数据信息。并方便我们赋值提升了代码的可读性
绑定:
当我们声明了一个对象或数组后,我们可以通过解构赋值中绑定的方式,将对象字面量中的属性和数组字面量中的值绑定到变量中。所有变量可以共享相同的声明,意思是我们可以在一次声明中同时绑定多个值,或者进一步解构,用变量单独绑定某些值,例如:
// 所有变量共享相同的声明
const obj = { a: 1, b: { c: 2 } };
const {
a, // 1
b: { c: d }
} = obj;
// `a` 直接从 `obj` 中提取属性 `a` 的值,并赋值给变量 `a`,因此 `a` 的值为 `1`。
// `b: { c: d }` 表示从 `obj` 中提取属性 `b`,然后再从 `b` 中提取属性 `c`,并将其值赋值给变量 `d`,因此 `d` 的值为 `2`。
// 如果尝试打印 `b` 或 `c`,则会报错表示没有定义,因为它们没有被单独声明为变量。
console.log(a); // 输出: 1
console.log(d); // 输出: 2
如果我们需要将某些变量单独的作用,比如让a为只读的,则可以这样:
const obj = { a: 1, b: { c: 2 } };
// 将 `a` 声明为只读
const { a } = obj;
// 将 `c` 的值绑定到 `d`
let {
b: { c: d }
} = obj;
console.log(a); // 输出: 1
console.log(d); // 输出: 2
// 试图修改 `a` 会报错,因为 `a` 是一个常量
// a = 10; // Uncaught TypeError: Assignment to constant variable.
d = 3; // 可以修改,因为 `d` 使用的是 `let` 声明
console.log(d); // 输出: 3
赋值:
赋值模式可以将字面量中的值直接赋值给一个赋值目标,赋值目标可以不以任何关键字开头,也可以事先用let,var进行声明,也可以是另一个对象属性,一般来说可以是被允许出现在赋值表达式左侧的所有东西:
let number = []; // 初始化 number 数组
const obj = { a: 1, b: 4 };
const saves = [0, 1, 2, 3, 4]; // 初始化 saves 数组
// 解构赋值
[number[0], number[1]] = saves;
x=saves;
console.log(number[0]); // 输出: 0
console.log(number[1]); // 输出: 1
console.log(x); //输出:Array [0, 1, 2, 3, 4]
值得注意的是,如果是对象作为解构赋值的目标,那么我们需要正确表达其内容,当使用对象文字解构赋值而不带声明时,需要再赋值语句周围添加()
const numbers = [];
const obj = { a: 1, b: 2 };
({ a: numbers[0], b: numbers[1] } = obj);
默认值:
在属性不存在或值为undefined时使用,这时将会使用默认值进行替代,如果属性值为null,则不使用默认值。
const number=[,,null];
[a=1,b,c]=number;
console.log(a); //input:1
console.log(b); //input:undefined
console.log(c); //inupt:null
剩余属性:
我们可以使用剩余属性来结束结构,此操作会把对象和数组的所有剩余的属性存储到新的数组中去,**注意的是:剩余属性必须是最后一个,且不能有尾随逗号
比较运算符:
比较任意类型的两个操作符并返回逻辑值,在多数情况下,除了使用了全等和不全等的情况外,如果两个操作数类型不一样,js会自动进行转换为恰当的类型进行比较。
**以下是从mdn中找到的关于比较运算符的详细解释:
运算符 | 描述 | 返回 true 的示例 |
---|---|---|
等于 Equal (== ) | 如果两边操作数相等时返回 true。 | 3 == var1 "3" == var1 3 == '3' |
不等于 Not equal (!= ) | 如果两边操作数不相等时返回 true | var1 != 4 var2 != "3" |
全等 Strict equal (=== ) | 两边操作数相等且类型相同时返回 true。参见 Object.is and sameness in JS. | 3 === var1 |
不全等 Strict not equal (!== ) | 两边操作数不相等或类型不同时返回 true。 | var1 !== "3" 3 !== '3' |
大于 Greater than (> ) | 左边的操作数大于右边的操作数返回 true | var2 > var1 "12" > 2 |
大于等于 Greater than or equal (>= ) | 左边的操作数大于或等于右边的操作数返回 true | var2 >= var1 var1 >= 3 |
小于 Less than (< ) | 左边的操作数小于右边的操作数返回 true | var1 < var2 "2" < 12 |
小于等于 Less than or equal (<= ) | 左边的操作数小于或等于右边的操作数返回 true | var1 <= var2 var2 <= 5 |
算术运算符:
除了日常使用的四则运算外,还有‘%’求余运算,自增和自减运算‘++,–’,以及表达数字为负数的一元负值符,‘-’,表达为正数的‘+’,以及次幂运算符,也就是指数运算* *
位运算符:
位运算符是将操作数看作为32位的二进制串,位运算符在二进制串上执行运算,返回的是标准的数值。
位运算符无非包含为,与或非,异或,非,左移,算数右移,无符号右移几种运算:
Operator | Usage | Description |
---|---|---|
按位与 AND | a & b | 在 a,b 的位表示中,每一个对应的位都为 1 则返回 1,否则返回 0. |
按位或 OR | a | b | 在 a,b 的位表示中,每一个对应的位,只要有一个为 1 则返回 1,否则返回 0. |
按位异或 XOR | a ^ b | 在 a,b 的位表示中,每一个对应的位,两个不相同则返回 1,相同则返回 0. |
按位非 NOT | ~ a | 反转被操作数的位。 |
左移 shift | a << b | 将 a 的二进制串向左移动 b 位,右边移入 0. |
算术右移 | a >> b | 把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位。(译注:算术右移左边空出的位是根据最高位是 0 和 1 来进行填充的) |
无符号右移 (左边空出位用 0 填充) | a >>> b | 把 a 的二进制表示向右移动 b 位,丢弃被移出的所有位,并把左边空出的位都填充为 0 |
字符运算符:
在js中可以对字符串进行拼接操作,用’+‘进行两个字符串的拼接,当然也可以用’+=‘的方式完成字符串的拼接操作
条件(三元)运算符:
在很多程序设计语言中都有这个运算符,基本表示如下:
条件?值1:值2
一元操作符:
delete 操作符
delete,能够删除定义中的一个数组中的某一个键值、对象的属性等,使用了var声明的除外,如果该属性可被删除则会返回为true,否则为false,利用mdn上面的举例说明:
x = 42;
var y = 43;
myobj = new Number();
myobj.h = 4; // create property h
delete x; // returns true (can delete if declared implicitly)
delete y; // returns false (cannot delete if declared with var)
delete Math.PI; // returns false (cannot delete predefined properties)
delete myobj.h; // returns true (can delete user-defined properties)
delete myobj; // returns true (can delete if declared implicitly)
在数组中,使用delete删除一个元素,该元素会被删除,并产生一个空位,会被undefined替代,且数组整体的长度不会发生变化,而如果我们希望该元素存在,则可以使用undefined的关键字对该键值进行替换,这不会创建一个空位,元素也会被认定为存在。例如:
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
delete trees[3];
console.log(trees); // 输出: ["redwood", "bay", "cedar", undefiend, "maple"]
console.log(trees[3]); // 输出: undefined
console.log(trees.length); // 输出: 5
if (3 in trees) {
console.log("Index 3 exists"); // 不会被执行
} else {
console.log("Index 3 does not exist"); // 输出: Index 3 does not exist
}
使用undefined关键字进行替换:
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
trees[3] = undefined;
console.log(trees); // 输出: ["redwood", "bay", "cedar", undefined, "maple"]
console.log(trees[3]); // 输出: undefined
console.log(trees.length); // 输出: 5
if (3 in trees) {
console.log("Index 3 exists"); // 输出: Index 3 exists
} else {
console.log("Index 3 does not exist");
}
typeof
我们可以使用该操作符返回所需要知道的数据的数据类型,其返回结果为标注js数据类型
声明方式:
typeof operand;
typeof (operand);
void
和c一样表示运算没有任何返回值,声明方式为:
void expression;
void (expression);
关系运算符:
它的作用是对操作符进行比较并返回一个布尔值:
in操作符
js中,用in操作符检查一个属性或索引是否存在于对象或数组中,对于数组而言in操作符检查的是数组的索引而不是值,如果要查看值是否包含在数组中,则使用include方法检查。
声明:
propNameOrNumber in objectName;
//prop代表属性名或数组索引
//objectname表示对象名
常用用法:
// Arrays
var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
0 in trees; // returns true
3 in trees; // returns true
6 in trees; // returns false
//此处是表示的对应位置的元素是否存在,和delete讲的示例参考理解
"bay" in trees; // returns false (you must specify the index number,
// not the value at that index)
"length" in trees; // returns true (length is an Array property)
// Predefined objects
"PI" in Math; // returns true
var myString = new String("coral");
"length" in myString; // returns true
// Custom objects
var mycar = { make: "Honda", model: "Accord", year: 1998 };
"make" in mycar; // returns true
"model" in mycar; // returns true
instanceof
我们可以用该操作符判别对象是否属于指定的类型,返回值为布尔型:
objectname instanceof objecttype
运算符的优先级:
操作符类型 | 具体操作符 |
---|---|
成员 | . [] |
调用/创建实例 | () new |
取反/增减 | ! ~ - + ++ – typeof void delete |
乘法/除法 | * / % |
加法/减法 | + - |
位移 | << >> >>> |
关系操作符 | < <= > >= in instanceof |
相等操作符 | == != === !== |
位与 | & |
位异或 | ^ |
位或 | |
逻辑与 | && |
逻辑或 | |
条件运算 | ?: |
赋值 | = += -= *= /= %= <<= >>= >>>= &= ^= |
逗号 | , |
表达式:
表达式就是一组会返回一个值的代码的集合,它有算数、字符串、逻辑值、基本表达式、左值表达式几种类型。
基本表达式:
this
用于被指代当前对象,通常情况下是方法中正在被调用的对象:
this["propertyName"];
this.propertyName;
分组操作符:
也就是(),在表达式中起到控制执行优先级的作用
左值表达式:
左值可以被作为赋值的目标
new
通过使用new运算符,创建一个自定义类型或者预置类型的对象的实例:
var objectName = new objectType([param1, param2, ..., paramN]);
例如:
//假如有这样一个构造函数:
function Person(name, age) {
this.name = name;
this.age = age;
this.greet = function() {
console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);
};
}
//new 运算符会调用构造函数并初始化新对象,并将该对象的prototype指向构造函数的prototype
var person1 = new Person("Alice", 30);
person1.greet(); // 输出: Hello, my name is Alice and I am 30 years old.
而创建预置类型的实例为:
// 创建 Date 对象的实例
var today = new Date();
console.log(today); // 输出当前日期和时间
// 创建 Array 对象的实例
var array = new Array(1, 2, 3);
console.log(array); // 输出: [1, 2, 3]
// 创建 Object 对象的实例
var obj = new Object();
obj.name = "John";
obj.age = 25;
console.log(obj); // 输出: { name: 'John', age: 25 }
super
该关键字用来调用一个对象的父类函数,具体等之后章节讲解时再说