一个 赋值运算符(assignment operator) 将它右边操作数的**值**赋给它左边的操作数。最简单的赋值运算符是等于(=),它将右边的操作数值赋给左边的操作数。那么 x = y 就是将 y 的值赋给 x。
=
+=
-=
*=
/=
算术运算符使用数值(字面量或者变量)作为操作数并返回一个数值。标准的算术运算符就是加减乘除(+ - * /)。
当操作数是浮点数时,这些运算符表现得跟它们在大多数编程语言中一样(特殊要注意的是,除零会产生Infinity)。
除了标准的算术运算符(+, - ,* /),JavaScript还提供了下表中的算术运算符。
%
:求余,返回相除之后的余数。++
:自增--
:自减2 ** 3
returns 8
10 ** -1
returns 0.1
逻辑运算符常用于布尔(逻辑)值之间; 当操作数都是布尔值时,返回值也是布尔值。 不过实际上&&和||返回的是一个特定的操作数的值,所以当它用于非布尔值的时候,返回值就可能是非布尔值。
&&
||
!
短路求值:
作为逻辑表达式进行求值是从左到右,它们是为可能的“短路”的出现而使用以下规则进行测试:
false
&& anything // 被短路求值为falsetrue
|| anything // 被短路求值为true逻辑的规则,保证这些评估是总是正确的。请注意,上述表达式的anything
部分不会被求值,所以这样做不会产生任何副作用。
= // 赋值运算符
== // 等于(类型不一样,值一样,也会判断true
=== // 绝对等于(类型一样,值一样)
null 和 undefined
除了比较操作符,它可以在字符串值中使用,连接操作符(+)连接两个字符串值相连接,返回另一个字符串,它是两个操作数串的结合。
var myString = "alpha";
myString += "bet"; // 返回 "alphabet"
逗号操作符(,)对两个操作数进行求值并返回最终操作数的值。它常常用在 for 循环中,在每次循环时对多个变量进行更新。
例如
var x = [0,1,2,3,4,5,6,7,8,9]
var a = [x, x, x, x, x];
for (var i = 0, j = 9; i <= j; i++, j--)
console.log('a[' + i + '][' + j + ']= ' + a[i][j]);
结果:
a[0][9]= 9
a[1][8]= 8
a[2][7]= 7
a[3][6]= 6
a[4][5]= 5
delete
typeof
void
<a href="javascript:void(0)">Click here to do nothing</a>
in
// 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
"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
true
。instanceof
运算符的优先级,用于确定一个表达式的计算顺序。在你不能确定优先级时,可以通过使用括号显式声明运算符的优先级。
Operator type | Individual operators | |
---|---|---|
member | . [] |
|
call / create instance | () new |
|
negation/increment | ! ~ - + ++ -- typeof void delete |
|
multiply/divide | * / % |
|
addition/subtraction | + - |
|
bitwise shift | << >> >>> |
|
relational | < <= > >= in instanceof |
|
equality | == != === !== |
|
bitwise-and | & |
|
bitwise-xor | ^ |
|
bitwise-or | ` | ` |
logical-and | && |
|
logical-or | ` | ` |
conditional | ?: |
|
assignment | `= += -= *= /= %= <<= >>= >>>= &= ^= | =` |
comma | , |
let age = 3;
if (age >= 18){
console.log("成年人");
}else if (age >= 12){
console.log("青少年");
}else{
console.log("儿童");
}
<script>
let err = 0;
switch(err){
case 0:
console.log('请求错误');
break;
case 1:
console.log("请求超时");
break;
case 2:
console.log("请求成功");
break;
default:
console.log("未知错误");
break;
}
</script>
<script>
let age = 0;
switch(true){
case age >=18 && age < 65:
console.log('青壮年');
break;
case age >= 12 && age < 18:
console.log("青少年");
break;
case age >=3 && age < 12:
console.log("儿童");
break;
case age < 3:
console.log("婴幼儿");
break;
default:
console.log("退休了");
break;
}
</script>
Boolean(条件)? A : B
// 如果Boolean(gender)则输出女,否则输出男。
Boolean(gender)? '女': '男';
循环三条件:
for(let i=0; i< 100; i++){
console.log(i)
}
let age = [12, 3, 45, 24, 53, 32, 56, 45, 67];
var num = 0;
while(num <= 100){
console.log(num);
num++;
}
do{
console.log(num);
num++;
}while(num < 100)
ES6语法糖,类似python
let age = [12, 3, 45, 24, 53, 32, 56, 45, 67];
for (let num of age){
console.log(num);
}
对象遍历用 for…in
let age = [12, 3, 45, 24, 53, 32, 56, 45, 67];
for (let num in age){
console.log(num); // num 是age的索引
console.log(age[num]); // 输出值
}
let obj = {
id:1,
username: 'xiaoniu',
'max salary': 123456,
};
for (var key in obj){
console.log(key); // key obj
console.log(obj[key]); // 输出值
}
对于重复的计算过程,可以考虑函数进行封装,实现“代码复用”。
这部分基础语法(一)中已有。
匿名函数有两种:
(function(a,b){
console.log(a+b);
})(10,50);
let getUserName = function(username){
return "Hello" + username;
}
console.log(getUserName('小牛同学'));
// 命名函数
function sum(a, b){
return a + b
}
// 匿名函数
let add1 = function(a, b){
return a + b
}
// 箭头函数
let add2 = (a, b)=>{
console.log(a + b)
}
转化方法:
// 如果函数体只有一条语句,**大括号**可以不写
<script>
let sum = (a, b)=>a+b;
let res = sum(23, 342);
console.log(res); // 结果为:365
</script>
<script>
let sum = (a, b)=>console.log(a+b);
sum(23, 342); // 结果为:365
</script>
// 如果参数只有一个,那么**参数的括号**也可以不写
add = a => a+5;
console.log(add(34, 42));
// 但是没有参数时,括号必须写
add = ()=>15+3;
console.log(add());
补充
参数不足时,可以设置默认参数
function sum1(num1, num2){
let total = 0;
total = num1 + num2;
console.log("total =", total);
}
sum1(12, 34);
sum1(23); // 输出: NaN,原因是由于参数不足。
//对于参数不足可以设置一个默认参数
function sum2(num1, num2=0){
let total = 0;
total = num1 + num2;
console.log("total =", total);
}
sum2(23);
对于传入函数参数过多的情况,可以使用 rest语法 来解决,这种方式叫做归内参数/剩余参数/不定参数,将多余参数压到一个数组参数中。
function sum3(...args){
console.log(args); // 输出:[23, 34, 545, 7, 23]
}
sum3(23,34,545,7,23);
①、将 … 用在函数的形参中,就是rest,归并操作,把多余的参数压到一个数组中。
<script>
let f = (a,b,...c)=>console.log(a,b,c);
f(1,2,3,4,5,6); // 输出: 1 2 [3, 4, 5, 6]
</script>
②、将 … 用在函数的调用参数中,就是扩展/展开,spread。
let f = (a,b,...c)=>console.log(a,b,c);
f(1,2,3,4,5,6);
const arr = [12,45,67,76,34]
f(...arr)
函数只能有一个返回值,默认单值返回。
如果需要返回多个值呢?
<script>
let fn = () => [1,2,3]
let res = fn();
console.log(res);
fn = () =>({
id:2,
name:'admin',
age:'23',
});
console.log(fn());
</script>
作用域分为:全局作用域、函数作用域,还有块作用域(块作用域不常用)。
// 块作用域
{
let a = 1;
console.log(a);
}
console.log(a);
①、函数作用域
函数作用域,即为在函数里边的变量。
②、全局作用域
全局作用域,即在函数外边的变量。
注:
函数里可以调用函数外的变量,但是函数外不能调用函数内的变量。
如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量互相独立,互不影响:
这说明JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。
function foo() {
var x = 1;
function bar() {
var x = 'A';
console.log('x in bar() = ' + x);
}
console.log('x in foo() = ' + x); // 1
bar(); // 'A'
console.log('x in foo() = ' + x); // 1
}
foo();
// 输出:
x in foo() = 1
x in bar() = A
x in foo() = 1
作用域链:作用域链用于查询变量。作用域链的内容是:查询变量的时候,先从函数内部查询,如果有就直接访问,如果没有则向上一个作用域查询,一级一级向上,直到全局作用域。
作用域链的特点:
闭包的两个条件:
<body>
<script>
function parent() {
let a = 5;
function f(b) {
let c = 7;
return a + b + c;
}
return f;
}
console.log(parent());
const f1 = parent();
console.log(f1);
console.log(f1(3));
</script>
</body>
以下代码中 a 是子函数f 的自由变量。
<body>
<script>
function parent1(a) {
function f(b) {
let c = 7;
return a + b + c;
}
return f;
}
// 这时候,在外部调用 parent1() 会返回一个函数,此时闭包就产生了。
console.log(parent1(4));
// parent1() 调用结束,应该将空间和参数都释放的,但是由于父函数中第一个变量a 被它的一个子函数引用着,所有就不能销毁,这就会产生闭包。
const f1 = parent1(4);
console.log(f1);
console.log(f1(3));
</script>
</body>
// 如果:
const f1 = parent1();
console.log(f1(3)); // 结果为NaN,因为a缺少参数。
闭包的示例:
let counter = (function(n){return function(){return n++}})(1);
console.log(counter());
console.log(counter());
console.log(counter());
<script>
let username = 'jack';
let name = 'marry';
let user1 = {
username: 'tom',
};
console.log(user1.username); // 输出:tom
let user2 = {
username: name,
};
console.log(user2.username); // 输出:marry
let user3 = {
username: username,
};
console.log(user3.username); // 输出:jack
// 简化熟悉
let user4 = {
username,
};
console.log(user4.username); // 输出:jack
</script>
当满足以下两个条件的时候,可以简化属性:
<script>
let username = 'jack';
let user = {
username,
};
console.log(user.username); // 输出:jack
let user1 = {
username,
getName: function(){
return 'Hello ' + this.username;
},
};
console.log(user1.getName()) // 输出:Hello jack
// 简化方法
// 语法:省略 ": function"
let user2 = {
username,
getName(){
return 'Hello ' + this.username;
},
};
console.log(user2.getName()) // 输出:Hello jack
</script>
模板字面量:也叫”模板字符串”,是同义词,我觉得用”模板字面量”更直观,准确
模板函数:有的书也翻译与”标签函数”,因为它使用”模板字面量”做参数,称为”模板函数”更准确。
<script>
// 传统的输出字符串,使用双引号或者单引号
console.log("Hello World!");
// 如果要输出多行字符串,那么传统方法:
console.log("html \n" + "css\n" + "js");
// 输出表达式计算结果:
let a = 10, b=20;
console.log(a + "+" + b + "=" + (a, b))
// 使用模板字符串
// 模板字符串语法: 对变量或表达式可以使用 ${x} 来引用。
let res = `${a} + ${b} = ${a + b}`
console.log(res);
// 模板表达式可以嵌套
let gender = 0;
let res1 = `${gender? `男:${name}`: `女`}`;
console.log(res1);
</script>
注:使用插值占位符: **${}
** ,可以将变量或表达式插入到字符串中。
使用模板字符串为参数的函数
例如:
alert`Hello World!`
<script>
function calc(strs, ...args){
console.log(strs);
console.log(args);
console.log(args[0] * args[1])
}
calc`数量: ${10}, 单价: ${50}`
</script>
注: