• 【第2章 Node.js基础】2.1 JavaScript基本语法


    学习目标

    (1)了解JavaScript的基本语法;
    (2)能读懂JavaScript代码。

    JavaScript版本与JavaScript运行环境

    JavaScript版本

    • ECMA组织制定了JavaScript语言的标准——ECMAScript(简称ES) 。
    • 大多数场合使用JavaScript名称,可将JavaScript看作是ES标准的实现语言。
    • 主要版本:
      • 2009年——ES5;
      • 2015年——ES6(ES2015);
      • ES7( ES2016 )、ES8( ES2017 )、ES9( ES2018 )和ES10( ES2019 )。
    • ES6是目前的主流版本,Node.js自6.0版本开始全面支持ES6。
    • Node.js自7.6版本开始就默认支持async/await异步编程。

    JavaScript运行环境

    • Node.js REPL交互式运行环境
      在这里插入图片描述

    • 浏览器控制台
      在这里插入图片描述

    JavaScript语句与注释

    语句

    • JavaScript每条语句都以分号;结束。
    • 一行代码可包含多条语句。
    • 一行语句太长,则可以使用续行符\进行换行。

    语句块

    • 语句块是一组语句的集合,作为一个整体使用大括号“{}”封装。
    • 语句块可以嵌套,形成层级结构。

    注释

    行注释

    // 我是单独一行注释
    alert('Hello World'); // 我是句尾的行注释
    
    • 1
    • 2

    块注释

    /* 我要开始注释啦
    我要结束注释啦*/
    
    • 1
    • 2

    变量

    变量的命名

    • JavaScript的变量可以是任意数据类型。
    • 变量名可以是大小写英文字母、数字、符号“$”或“_”的任意组合,但不能以数字开头。

    变量的声明与赋值

    • 弱类型的编程语言,所有数据类型都可以用var关键字声明。在定义变量时无须指定变量类型。
    var hello; // 声明一个名为hello的变量,此时该变量的值为undefined,表示未定义
    
    • 1
    • 使用等号对变量进行赋值,可以将任意数据类型赋值给变量。
      hello='我是个字符串'; //此时变量的值为“我是个字符串”
    
    • 1
    • 可以在声明变量的同时对变量进行赋值。
    var name = "法外狂徒-张三";
    
    • 1
    • 可以反复赋值同一个变量。

    变量提升

    • 变量可以在声明之前使用,值为undefined。
    console.log(temp);// 返回undefined
     var temp = '你好';
    
    • 1
    • 2
    • ES6用let关键字改变这种行为,变量一定要在声明之后使用。否则报错;
      在这里插入图片描述

    变量泄露

    • 用来计数的循环变量使用var关键字声明后会泄露为全局变量。
        var temp = 'Hello!';
        for (var i = 0; i < temp.length; i++) {
            console.log(temp[i]);
        }
       console.log(i); // 返回数字6,泄露为全局变量了。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 改用let关键字来声明循环变量避免变量泄露。
     var temp = 'Hello!';
        for (let i = 0; i < temp.length; i++) {
            console.log(temp[i]);
        }
       console.log(i); // 报错未定义,没有泄露
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述

    全局作用域和函数作用域

    ES5中只有全局作用域(顶层作用域)和函数作用域。

    var temp = '你好!';//全局作用域
    function testScope() {
        var temp = '早上好!'; //函数作用域
        console.log(temp);
    }
    testScope(); //返回函数作用域中的“早上好”!
    console.log(temp); //返回全局变量的“你好”!
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    块级作用域与let关键字

    ES6引入块级作用域,使用let关键字声明的变量只能在当前块级作用域中使用。

    function testBlockScope() {
        let name = '小明';
        if (true) {
            let name = '小红';
            console.log(name); // 返回“小红”
        }
        console.log(name); // 返回“小明”
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    使用const关键字声明只读常量

    ES6引入const关键字声明只读的常量。

    const PI = 3.14159;
    console.log(PI); // 输出: 3.14159
    
    PI = 3.14; // 报错: TypeError: Assignment to constant variable.
    
    • 1
    • 2
    • 3
    • 4
    注意

    需要注意的是,const关键字确实可以用于声明只读的常量,但对于对象来说,const并不表示对象本身是不可变的,而是表示对象的引用是不可变的。

    当使用const声明一个对象时,你不能再将该常量指向其他对象,但你仍然可以修改对象本身的属性值。

    const person = {
      name: "John",
      age: 30
    };
    
    person.age = 31; // 可以修改对象的属性值
    console.log(person); // 输出: { name: "John", age: 31 }
    
    person = {}; // 报错: TypeError: Assignment to constant variable.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    数据类型

    数值(Number)、字符串(String)、布尔值(Boolean)、null和undefined、数组(Array)、对象(Object)、符号(Symbol)、映射(Map)、集合(Set)

    数值(Number)

    • 不区分整数和浮点数,统一用数值表示。
    • 十六进制数使用0x作为前缀。二进制和八进制数值分别使用前缀0b(或0B)和0o(或0O)。
    • 无法计算结果时就可用NaN表示;Infinity表示无限大。

    字符串(String)

    • 字符串是用单引号“'”或双引号“"”括起来的任意文本。
    • ES6提供模板字符串,可使用反引号包括整个模板字符串,使用${}将变量括起来。
    var msg = `服务器侦听监听地址和端口:${srvip}:${port},请注意!`;
    
    • 1
    • 模板字符串中也可以不嵌入任何变量,通常用于按实际格式输出(如换行)。

    布尔值(Boolean)

    • 布尔值只有true、false两种,经常用于条件判断中。
    • 在比较是否相等时,建议使用=== 而不要使用 ==

    null和undefined

    • null表示一个空值,即什么也没有。
    • undefined表示“未定义”,仅用于判断函数参数是否正常传递。

    数组(Array)

    • JavaScript的数组可以包括任意数据类型。
    • 数组用[]表示,元素之间用逗号分隔。
    • 数组的元素可以通过索引来访问,注意索引的起始值为0。

    对象(Object)

    • 对象是一组由键值对组成的无序集合,用{}表示,键值对之间用逗号分隔。
    var myObj = {
      isobj: true,
      num: [1,2,3],
      desp: '对象好像可以无所不包'
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 键均为字符串类型,而值可以是任意数据类型。
    • 获取一个对象的属性可用“对象名.属性(键)名”的方式。
    • ES6允许将表达式作为对象的属性名,即把表达式放在方括号内。
    let numproperty = 'num';
    var myObj = {
        [numproperty]: [1,2,3],
      ['des'+'cription']: '我是个对象'
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5

    符号(Symbol)

    • ES6引入数据类型Symbol,用于表示独一无二的值,其值通过Symbol()函数自动生成。
    • Symbol值用于对象的属性名,可以有3种表示方法。
    let welcome = Symbol();//自动产生一个值
    // 第1种表示方法
    let myObj = {};
    myObj[welcome] = '欢迎光临';
    // 第2种表示方法
    let myObj = { [welcome]: '欢迎光临' };
    // 第3种表示方法
    let myObj = {};
    Object.defineProperty(myObj, welcome, { value: '欢迎光临' });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    映射(Map)

    • ES6引入Map数据结构,与对象类似,但各种类型的数据(甚至对象)都可以作为键。
    • Map本身是一个构造函数,用于生成Map数据结构。
     const myMap = new Map();
    
    • 1
    • 可以使用Map结构的set方法添加成员
    const myObj = {welcome: '欢迎光临'};
    myMap.set(myObj,'我是一个对象');
    
    • 1
    • 2
    • 使用Map结构的get方法读取键(成员)
    myMap.get(myObj);  //结果为'我是一个对象
    
    • 1
    • Map结构的实例支持遍历方法。
      • keys():返回键名的遍历器。
      • values():返回键值的遍历器。
      • entries():返回键值对的遍历器。
      • forEach():使用回调函数遍历每个成员。

    集合(Set)

    • 集合是无重复的、无序的数据结构,类似于数组,即没有重复的值。
    • 集合是一个构造函数,用于生成Set数据结构。
    const mySet = new Set();
    
    • 1
    • 可以通过add()方法向Set结构加入成员。
    • Set()函数可将Iterable类型的数据结构(数组、集合或映射)作为参数,用于初始化集合。
    const mySet = new Set([1, 2, 3, 4, 4]);//会自动过滤掉其中一个数字4
    
    • 1
    • Set结构中的元素可以看作是键,与Map结构不同的是,它只有键名没有键值。
    • Set结构使用与Map结构相同的4种遍历方法来遍历成员。

    遍历数组可以采用下标循环,而遍历映射和集合就无法使用下标。为了统一集合类型,ES6引入了新的Iterable类型,数组、映射和集合都属于Iterable类型。这种类型的集合可以通过新的for … of循环来遍历。更好的遍历方式是使用Iterable类型内置的forEach方法。

    流程控制

    分支结构

    • if () { … } else { … }
    • if () { … } else if () { … } else { … }
    • switch … case
     switch(变量)
    {
        case1:
               代码1;
               break;
        case2:
               代码2;
               break;
        default:
               如果以上条件都不满足,则执行该代码;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    循环结构

    • for
    • for … in
     for (var key in obj) {
        console.log(key); 
    }
    
    • 1
    • 2
    • 3
    • while
    • do … While
    • break
    • continue

    循环结构中的条件需使用括号括起。

    JavaScript的函数

    函数声明

    • 声明函数需要使用function关键字。
     function sumAge(x,y) {
        return  x + y;
    }
    
    • 1
    • 2
    • 3
    • ES6直接支持默认参数
    sumAge(x=19,y=20)
    
    • 1
    • 在ES5中设置默认参数需要采用变通的方法
    function sumAge (x,y) {
        x = arguments[0]===undefined ? 21 : arguments[0]; //设置参数x的默认值为21
        y = arguments[1]===undefined ? 20 : arguments[1]; //设置参数y的默认值为20
        return  x + y;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    函数调用

    • 声明函数之后使用“函数名(参数)”的形式,按顺序传入参数进行调用。
    sumAge(22,20)//两人加起来42岁
    
    • 1

    arguments对象

    • JavaScript的函数默认带有arguments对象,利用该对象可以获得调用者传入的所有参数。
    function sumAge (){
        var sum = 0;
        var numcount= arguments.length
        for (var i=0;i<numcount;i++){
          sum += arguments[i];
        }
        return sum;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    rest参数

    • ES6引入rest参数(形式为“…变量名”),用于获取函数的多余参数,以代替arguments对象。
    function sumAge(...values){
        var  sum = 0;
        for (var val of values){
            sum += val;
        }
        return sum;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    匿名函数

    声明函数时省略函数名。

    var sumAge = function (x,y) {
        return  x + y;
    };
    
    • 1
    • 2
    • 3

    箭头函数

    使用箭头符号(=>)定义函数。

    示例箭头函数普通函数
    一个参数var f = x => x;var f = function (x) { return x; };
    多个参数var sumAge = (x, y) => x + y;var sumAge = function (x, y) { return x + y; };
    无参数var f = () => 20;var f = function () { return 20; };
    代码块包含多条语句var diffAge = (x, y) => { var diff = x - y; return Math.abs(diff); }var diffAge = function (x, y) { var diff = x - y; return Math.abs(diff); };

    以上是箭头函数和普通函数在不同情况下的对比示例。箭头函数是ES6中引入的一种更简洁的函数语法,可以更方便地定义函数。与普通函数相比,箭头函数具有更短的语法和更简洁的写法。

    高阶函数

    以一个或多个函数作为参数的函数。

    function diffAge(m, n, abs) {
        return abs(m-n);
    }
    diffAge(19, 22, Math.abs);
    
    • 1
    • 2
    • 3
    • 4

    闭包

    • 当函数作为返回值,或者作为参数传递时,该函数就被称为闭包。
    • 闭包是能够读取其他函数内部变量的函数,可以使用函数之外定义的变量。
    var basePrice = 10.00;//起步价
    var baseMiles = 3.00;        //起步里程
    function taxiPrice(unitPrice, Mileage) {
      function totalPrice() {   //计算总费用 ;这是定义在一个函数内部的函数
        if ( Mileage > baseMiles) {   //超过起步里程
          return  unitPrice*Mileage;  //单价与里程相乘
        }
        else{                    //在起步里程内
          return basePrice;
        }
      }
      return totalPrice ();
    }
    taxiPrice(2.00,6.00);//打车费用12.00
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    JavaScript的类

    ES5通过构造函数生成实例对象

    function Visitor(name, sex) {   //来宾信息
        this.name = name;
        this.sex = sex;
    }
    VisitorPoint.prototype.getInfo = function () {
        return this.name + ', ' + this.sex;
    };
    var visitor = new Visitor('张勇', '先生');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    ES6引入类作为对象的模板,通过class关键字定义类

    class Visitor{
      constructor(name, sex) {
        this.name = name;
        this.sex = sex;
      }
      getInfo() {
        return this.name + ', ' + this.sex;
      }
    }
    var visitor = new Visitor('张勇', '先生');
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    严格模式

    • 变量必须声明后使用。
    • 不能出现两个命名参数同名的情况,否则报错。
    • 不能使用with语句。
    • 不能对只读属性赋值,否则报错。
    • 不能使用前缀0表示八进制数,否则报错。
    • 不能删除不可删除的属性,否则报错。
    • 不能删除变量,只能删除属性。
    • eval关键字不会在它的外层作用域引入变量。
    • eval和arguments不能被重新赋值。
    • 不能使用arguments.callee和arguments.caller属性。
    • 禁止this关键字指向全局对象。
    • 不能使用fn.caller和fn.arguments属性获取函数调用的堆栈。
    • 增加了保留字(如protected、static和interface)。

    JavaScript编程规范

    代码格式

    • 每条JavaScript语句应该以分号结束。
    • 缩进使用2个半角空格或4个半角空格,而不使用Tab键。
    • 每行仅声明一个变量,而不要声明多个变量。
    • 字符串尽量使用单引号。
    • 符号“{”应在行末,表示代码块的开始,符号“}”应在行首,表示代码块的结束。

    命名规范

    • 变量推荐使用小驼峰命名法。
    • 常量名建议全部大写。
    • 函数也采用小驼峰命名法,建议前缀部分为动词。
    • 类和构造函数采用大驼峰命名法,同时建议前缀部分为名词。
    • 文件命名尽量采用下划线分割单词。

    函数

    • 函数的实现代码尽可能短小精悍,便于阅读。
    • 避免多余的else语句,尽早执行return语句。
    • 尽可能为闭包命名,便于调试跟踪。
    • 不要嵌套闭包。
    • 使用方法链时,每行仅调用一个方法,并使用缩进表明方法的并列关系。

    注释

    • 注释要尽量简单,清晰明了,同时注重注释的意义。
    • 尽可能从更高层次说明代码的功能。
    • 尽可能使用英文注释。
  • 相关阅读:
    计算机网络(第8版)-第5章 运输层
    通过热透镜聚焦不同类型的高斯模式
    Java 断言 Assert 使用教程与最佳实践
    【数字IC基础】时序分析之关键路径(Critical Path)、优化方法
    【408数据结构与算法】—树和二叉树(二十七)
    OpenCV4.8 GPU版本CMake编译详细步骤 与CUDA代码演示
    Java基础——String类详解,实用解释
    NoSQL之 Redis配置与优化
    Tensorflow Bug :got shape [1, 7], but wanted [1].
    在C# WinForms应用程序中安装,配置和使用MetroFramework
  • 原文地址:https://blog.csdn.net/No_Name_Cao_Ni_Mei/article/details/134291373