博客列表 >JavaScript基础语法(二)(运算符、流程控制、函数)

JavaScript基础语法(二)(运算符、流程控制、函数)

幽幽小帆
幽幽小帆原创
2022年04月10日 16:09:12478浏览

1、运算符

(1)赋值运算符

一个 赋值运算符(assignment operator) 将它右边操作数的****赋给它左边的操作数。最简单的赋值运算符是等于(=),它将右边的操作数值赋给左边的操作数。那么 x = y 就是将 y 的值赋给 x。

  1. =
  2. +=
  3. -=
  4. *=
  5. /=

(2)算术运算符

算术运算符使用数值(字面量或者变量)作为操作数并返回一个数值。标准的算术运算符就是加减乘除(+ - * /)。

当操作数是浮点数时,这些运算符表现得跟它们在大多数编程语言中一样(特殊要注意的是,除零会产生Infinity)。

除了标准的算术运算符(+, - ,* /),JavaScript还提供了下表中的算术运算符。

  • %:求余,返回相除之后的余数。
  • ++:自增
  • --:自减
  • -:返回操作数的负值
  • +:如果操作数在之前不是number,试图将其转换为number
  • **:指数运算符
    • 2 ** 3 returns 8
    • 10 ** -1 returns 0.1

(2)逻辑运算符

逻辑运算符常用于布尔(逻辑)值之间; 当操作数都是布尔值时,返回值也是布尔值。 不过实际上&&和||返回的是一个特定的操作数的值,所以当它用于非布尔值的时候,返回值就可能是非布尔值。

  1. &&
  2. ||
  3. !

短路求值:

作为逻辑表达式进行求值是从左到右,它们是为可能的“短路”的出现而使用以下规则进行测试:

  • false && anything // 被短路求值为false
  • true || anything // 被短路求值为true

逻辑的规则,保证这些评估是总是正确的。请注意,上述表达式的anything部分不会被求值,所以这样做不会产生任何副作用。

(3)比较运算符

  1. = // 赋值运算符
  2. == // 等于(类型不一样,值一样,也会判断true
  3. === // 绝对等于(类型一样,值一样)
  • 这是js的一个缺陷,坚持不要使用 == 比较
  • NaN 和任何值都不相等,包括自身,只能通过 isNaN(NaN) 来判断这个数是否是NaN
  • 浮点数问题:

null 和 undefined

  • null 空
  • undefined 未定义

(4)字符串运算符

除了比较操作符,它可以在字符串值中使用,连接操作符(+)连接两个字符串值相连接,返回另一个字符串,它是两个操作数串的结合。

  1. var myString = "alpha";
  2. myString += "bet"; // 返回 "alphabet"

(5)逗号运算符

逗号操作符(,)对两个操作数进行求值并返回最终操作数的值。它常常用在 for 循环中,在每次循环时对多个变量进行更新。

例如

  • 假如 a 是一个二维数组,每个维度各有10个元素,以下代码利用逗号操作符来同时改变两个变量的值。
  • 这段代码的功能是打印出该二维数组的对角线元素的值:
  1. var x = [0,1,2,3,4,5,6,7,8,9]
  2. var a = [x, x, x, x, x];
  3. for (var i = 0, j = 9; i <= j; i++, j--)
  4. console.log('a[' + i + '][' + j + ']= ' + a[i][j]);
  5. 结果:
  6. a[0][9]= 9
  7. a[1][8]= 8
  8. a[2][7]= 7
  9. a[3][6]= 6
  10. a[4][5]= 5

(6)一元操作符

  • delete
    • delete操作符,删除一个对象的属性或者一个数组中某一个键值
    • 如果 delete 操作成功,属性或者元素会变成 undefined。
    • 删除数组中的元素时,数组的长度是不变的,例如删除a[3], a[4],a[4]和a[3] 仍然存在变成了undefined。
  • typeof
    • typeof 操作符返回一个表示 operand 类型的字符串值。operand 可为字符串、变量、关键词或对象,其类型将被返回。
  • void
    • void运算符表明一个运算没有返回值。
    • 如下创建了一个超链接文本,当用户单击该文本时,不会有任何效果。
  1. <a href="javascript:void(0)">Click here to do nothing</a>

(7)关系操作符

  • in
    • in操作符,如果所指定的属性确实存在于所指定的对象中,则会返回true
  1. // Arrays
  2. var trees = new Array("redwood", "bay", "cedar", "oak", "maple");
  3. 0 in trees; // returns true
  4. 3 in trees; // returns true
  5. 6 in trees; // returns false
  6. "bay" in trees; // returns false (you must specify the index number,
  7. // not the value at that index)
  8. "length" in trees; // returns true (length is an Array property)
  9. // Predefined objects
  10. "PI" in Math; // returns true
  11. var myString = new String("coral");
  12. "length" in myString; // returns true
  13. // Custom objects
  14. var mycar = {make: "Honda", model: "Accord", year: 1998};
  15. "make" in mycar; // returns true
  16. "model" in mycar; // returns true
  • instanceof
    • 如果所判别的对象确实是所指定的类型,则返回true
    • 当你需要确认一个对象在运行时的类型时,可使用instanceof

(7)运算符优先级

运算符的优先级,用于确定一个表达式的计算顺序。在你不能确定优先级时,可以通过使用括号显式声明运算符的优先级

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 ,

更为详细的版本:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_Precedence#table

2、流程控制

(1)if else

  1. let age = 3;
  2. if (age >= 18){
  3. console.log("成年人");
  4. }else if (age >= 12){
  5. console.log("青少年");
  6. }else{
  7. console.log("儿童");
  8. }

(2)switch

  1. <script>
  2. let err = 0;
  3. switch(err){
  4. case 0:
  5. console.log('请求错误');
  6. break;
  7. case 1:
  8. console.log("请求超时");
  9. break;
  10. case 2:
  11. console.log("请求成功");
  12. break;
  13. default:
  14. console.log("未知错误");
  15. break;
  16. }
  17. </script>
  1. <script>
  2. let age = 0;
  3. switch(true){
  4. case age >=18 && age < 65:
  5. console.log('青壮年');
  6. break;
  7. case age >= 12 && age < 18:
  8. console.log("青少年");
  9. break;
  10. case age >=3 && age < 12:
  11. console.log("儿童");
  12. break;
  13. case age < 3:
  14. console.log("婴幼儿");
  15. break;
  16. default:
  17. console.log("退休了");
  18. break;
  19. }
  20. </script>

(3)三元表达式

Boolean(条件)? A : B

  1. // 如果Boolean(gender)则输出女,否则输出男。
  2. Boolean(gender)? '女': '男';

(3)for循环

循环三条件:

  1. 初始条件:数组索引的引用(i= 0)
  2. 循环条件:为真则执行循环体(i < arr.length)
  3. 更新条件:必须要有,否则进入死循环(i++)

①、for循环

  1. for(let i=0; i< 100; i++){
  2. console.log(i)
  3. }
  4. let age = [12, 3, 45, 24, 53, 32, 56, 45, 67];

②、while循环

  1. var num = 0;
  2. while(num <= 100){
  3. console.log(num);
  4. num++;
  5. }
  6. do{
  7. console.log(num);
  8. num++;
  9. }while(num < 100)

③、for of 循环

ES6语法糖,类似python

  1. let age = [12, 3, 45, 24, 53, 32, 56, 45, 67];
  2. for (let num of age){
  3. console.log(num);
  4. }

④、for in 循环

对象遍历用 for…in

  1. let age = [12, 3, 45, 24, 53, 32, 56, 45, 67];
  2. for (let num in age){
  3. console.log(num); // num 是age的索引
  4. console.log(age[num]); // 输出值
  5. }
  1. let obj = {
  2. id:1,
  3. username: 'xiaoniu',
  4. 'max salary': 123456,
  5. };
  6. for (var key in obj){
  7. console.log(key); // key obj
  8. console.log(obj[key]); // 输出值
  9. }

3、函数

对于重复的计算过程,可以考虑函数进行封装,实现“代码复用”。

(1)函数的声明和调用

这部分基础语法(一)中已有。

(2)匿名函数

匿名函数有两种:

  • 第一种:函数是一次性的,称为立即调用函数, IIFE
    • 将声明与调用二合一
  1. (function(a,b){
  2. console.log(a+b);
  3. })(10,50);
  • 第二种:函数不是一次性的,可以使用函数表达式
    • 将匿名函数当成值赋给一个变量
    • 调用方式:通过变量
  1. let getUserName = function(username){
  2. return "Hello" + username;
  3. }
  4. console.log(getUserName('小牛同学'));
  • 第三种:箭头函数
    • 用于简化匿名函数
  1. // 命名函数
  2. function sum(a, b){
  3. return a + b
  4. }
  5. // 匿名函数
  6. let add1 = function(a, b){
  7. return a + b
  8. }
  9. // 箭头函数
  10. let add2 = (a, b)=>{
  11. console.log(a + b)
  12. }

转化方法:

  • 去掉function
  • 在参数列表与大括号之间使用 =>
  1. // 如果函数体只有一条语句,**大括号**可以不写
  2. <script>
  3. let sum = (a, b)=>a+b;
  4. let res = sum(23, 342);
  5. console.log(res); // 结果为:365
  6. </script>
  7. <script>
  8. let sum = (a, b)=>console.log(a+b);
  9. sum(23, 342); // 结果为:365
  10. </script>
  11. // 如果参数只有一个,那么**参数的括号**也可以不写
  12. add = a => a+5;
  13. console.log(add(34, 42));
  14. // 但是没有参数时,括号必须写
  15. add = ()=>15+3;
  16. console.log(add());

补充

  • 胖箭头:=>
  • 瘦箭头:→

(3)函数传参

①、参数不足时,可以设置默认参数

参数不足时,可以设置默认参数

  1. function sum1(num1, num2){
  2. let total = 0;
  3. total = num1 + num2;
  4. console.log("total =", total);
  5. }
  6. sum1(12, 34);
  7. sum1(23); // 输出: NaN,原因是由于参数不足。
  8. //对于参数不足可以设置一个默认参数
  9. function sum2(num1, num2=0){
  10. let total = 0;
  11. total = num1 + num2;
  12. console.log("total =", total);
  13. }
  14. sum2(23);
  • function: 函数声明的关键字
  • sum1:函数名称
  • (num1, num2): 参数列表
  • (12, 34):调用参数,实际参数(实参),与上面参数列表中的参数一一对应。

③、参数过多时,可以使用rest语法

对于传入函数参数过多的情况,可以使用 rest语法 来解决,这种方式叫做归内参数/剩余参数/不定参数,将多余参数压到一个数组参数中

  1. function sum3(...args){
  2. console.log(args); // 输出:[23, 34, 545, 7, 23]
  3. }
  4. sum3(23,34,545,7,23);

①、将 … 用在函数的形参中,就是rest,归并操作,把多余的参数压到一个数组中。

  1. <script>
  2. let f = (a,b,...c)=>console.log(a,b,c);
  3. f(1,2,3,4,5,6); // 输出: 1 2 [3, 4, 5, 6]
  4. </script>

②、将 … 用在函数的调用参数中,就是扩展/展开,spread。

  1. let f = (a,b,...c)=>console.log(a,b,c);
  2. f(1,2,3,4,5,6);
  3. const arr = [12,45,67,76,34]
  4. f(...arr)

(4)函数的返回值

函数只能有一个返回值,默认单值返回。

如果需要返回多个值呢?

  • 可以使用数组或者对象
  1. <script>
  2. let fn = () => [1,2,3]
  3. let res = fn();
  4. console.log(res);
  5. fn = () =>({
  6. id:2,
  7. name:'admin',
  8. age:'23',
  9. });
  10. console.log(fn());
  11. </script>

(5)作用域

作用域分为:全局作用域、函数作用域,还有块作用域(块作用域不常用)。

  1. // 块作用域
  2. {
  3. let a = 1;
  4. console.log(a);
  5. }
  6. console.log(a);

①、函数作用域

函数作用域,即为在函数里边的变量。

②、全局作用域

全局作用域,即在函数外边的变量。

注:

函数里可以调用函数外的变量,但是函数外不能调用函数内的变量。

如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量互相独立,互不影响:

这说明JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量

  1. function foo() {
  2. var x = 1;
  3. function bar() {
  4. var x = 'A';
  5. console.log('x in bar() = ' + x);
  6. }
  7. console.log('x in foo() = ' + x); // 1
  8. bar(); // 'A'
  9. console.log('x in foo() = ' + x); // 1
  10. }
  11. foo();
  12. // 输出:
  13. x in foo() = 1
  14. x in bar() = A
  15. x in foo() = 1

作用域链:作用域链用于查询变量。作用域链的内容是:查询变量的时候,先从函数内部查询,如果有就直接访问,如果没有则向上一个作用域查询,一级一级向上,直到全局作用域。

作用域链的特点:

  • 单向的。
  • 由外向内传递可以,但是由内向外禁止。

(6)闭包

闭包的两个条件:

  1. 父子函数
  2. 自由变量
  1. <body>
  2. <script>
  3. function parent() {
  4. let a = 5;
  5. function f(b) {
  6. let c = 7;
  7. return a + b + c;
  8. }
  9. return f;
  10. }
  11. console.log(parent());
  12. const f1 = parent();
  13. console.log(f1);
  14. console.log(f1(3));
  15. </script>
  16. </body>

以下代码中 a 是子函数f 的自由变量。

  1. <body>
  2. <script>
  3. function parent1(a) {
  4. function f(b) {
  5. let c = 7;
  6. return a + b + c;
  7. }
  8. return f;
  9. }
  10. // 这时候,在外部调用 parent1() 会返回一个函数,此时闭包就产生了。
  11. console.log(parent1(4));
  12. // parent1() 调用结束,应该将空间和参数都释放的,但是由于父函数中第一个变量a 被它的一个子函数引用着,所有就不能销毁,这就会产生闭包。
  13. const f1 = parent1(4);
  14. console.log(f1);
  15. console.log(f1(3));
  16. </script>
  17. </body>

  1. // 如果:
  2. const f1 = parent1();
  3. console.log(f1(3)); // 结果为NaN,因为a缺少参数。

闭包的示例:

  1. let counter = (function(n){return function(){return n++}})(1);
  2. console.log(counter());
  3. console.log(counter());
  4. console.log(counter());


(7)对象字面量的简化

①、属性简化

  1. <script>
  2. let username = 'jack';
  3. let name = 'marry';
  4. let user1 = {
  5. username: 'tom',
  6. };
  7. console.log(user1.username); // 输出:tom
  8. let user2 = {
  9. username: name,
  10. };
  11. console.log(user2.username); // 输出:marry
  12. let user3 = {
  13. username: username,
  14. };
  15. console.log(user3.username); // 输出:jack
  16. // 简化熟悉
  17. let user4 = {
  18. username,
  19. };
  20. console.log(user4.username); // 输出:jack
  21. </script>

当满足以下两个条件的时候,可以简化属性:

  1. 作用域相同:对象属性与变量处于同一作用域下面。
  2. 名称相同:对象属性与变量同名。

②、方法简化

  1. <script>
  2. let username = 'jack';
  3. let user = {
  4. username,
  5. };
  6. console.log(user.username); // 输出:jack
  7. let user1 = {
  8. username,
  9. getName: function(){
  10. return 'Hello ' + this.username;
  11. },
  12. };
  13. console.log(user1.getName()) // 输出:Hello jack
  14. // 简化方法
  15. // 语法:省略 ": function"
  16. let user2 = {
  17. username,
  18. getName(){
  19. return 'Hello ' + this.username;
  20. },
  21. };
  22. console.log(user2.getName()) // 输出:Hello jack
  23. </script>

(8)模板字面量和模板函数

模板字面量:也叫”模板字符串”,是同义词,我觉得用”模板字面量”更直观,准确
模板函数:有的书也翻译与”标签函数”,因为它使用”模板字面量”做参数,称为”模板函数”更准确。

①、模板字符串

  1. <script>
  2. // 传统的输出字符串,使用双引号或者单引号
  3. console.log("Hello World!");
  4. // 如果要输出多行字符串,那么传统方法:
  5. console.log("html \n" + "css\n" + "js");
  6. // 输出表达式计算结果:
  7. let a = 10, b=20;
  8. console.log(a + "+" + b + "=" + (a, b))
  9. // 使用模板字符串
  10. // 模板字符串语法: 对变量或表达式可以使用 ${x} 来引用。
  11. let res = `${a} + ${b} = ${a + b}`
  12. console.log(res);
  13. // 模板表达式可以嵌套
  14. let gender = 0;
  15. let res1 = `${gender? `男:${name}`: `女`}`;
  16. console.log(res1);
  17. </script>

注:使用插值占位符: **${}** ,可以将变量或表达式插入到字符串中。

②、模板函数

使用模板字符串为参数的函数

例如:

  1. alert`Hello World!`
  1. <script>
  2. function calc(strs, ...args){
  3. console.log(strs);
  4. console.log(args);
  5. console.log(args[0] * args[1])
  6. }
  7. calc`数量: ${10}, 单价: ${50}`
  8. </script>

注:

  • 模板函数就是在“模板字面量”之前加一个标签/标识符,而这个标签就是一个函数名。
  • 模板函数的参数是有约定的,不能乱写,第一个是字面量数组,从第二个开始才是内部的占位符参数
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议