1.初识JavaScript

1.1 JavaScript 是什么

JavaScript(简称JS)

  • 是世界上最流行的编程语言之一
  • 是一个脚本语言,通过解释器运行
  • 主要在客户端(浏览器)运行,现在也可以基于 node.js 在服务器端运行

JavaScript能做的事

  • 网页开发(更复杂的特效和用户交互)
  • 网页游戏开发
  • 服务器开发(node.js)
  • 桌面程序开发
  • 手机 app 开发

1.2 JavaScript 和 HTML 和 CSS 之间的关系

  • HTML:网页的结构
  • CSS:网页的表现
  • JavaScript:网页的行为

1.3 JavaScript 运行过程

JS通常是运行在浏览器上的

  • 编写的代码是保存在文件中的,也就是存储在硬盘(外存)上
  • 双击 .html 文件浏览器(应用程序)就会读取文件,把文件内容加载到内存中(数据流向:硬盘 => 内存)
  • 浏览器会解析用户编写的代码,把代码翻译成二进制的,能让计算机识别的指令(解释器的工作)
  • 得到的二进制指令会被 CPU 加载并执行(数据流向:内存 => CPU)
    在这里插入图片描述
    浏览器分成渲染引擎+JS引擎
  • 渲染引擎:解析 html + CSS,俗称“内核”
  • JS 引擎:也就是 JS 解释器

JS 引擎逐行读取 JS 代码内容,然后解析成二进制指令,再执行

1.4 JavaScript 的组成

  • ECMAScript(简称 ES): JavaScript 语法
  • DOM: 页面文档对象模型, 对页面中的元素进行操作
  • BOM: 浏览器对象模型, 对浏览器窗口进行操作
    光有 JS 语法,只能写一些基础的逻辑流程
    但是想要完成更复杂的任务,完成和浏览器以及界面的交互,就需要 DOM API 和 BOM API

这主要指在浏览器端运行的 JS. 如果是运行在服务端的 JS , 则需要使用 node.js 的 API,
就不太需要关注 DOM 和 BOM

重要概念: ECMAScript
这是一套“标准”,无论什么样的 JS 引擎都要遵守这个标准来实现

2.前置知识

2.1 第一个程序

<script>
    alert("你好!");
</script>
  • JavaScript代码可以嵌入到 HTML 的 script 标签中

2.2 JavaScript 的书写形式

2.2.1 行内式

直接嵌入到 html 元素内部

<input type="button" value="点击按钮" onclick="alert('哈哈')">

注意,JS 中的字符串常量可以使用单引号表示,也可以使用双引号表示
HTML 中推荐使用双引号,JS 中推荐使用单引号

2.2.2 内嵌式

写到 script 标签中

<script>
    alert("你好!");
</script>

2.2.3 外部式

写到单独的 js 文件中

<script src="js/test01.js"></script>
alert("你好!");

注意,这种情况下 script 标签中间不能写代码,必须空着(写了代码也不会执行)
适合代码多的情况

2.3 注释

单行注释 // (建议使用)
多行注释 /* */ (多行注释不能嵌套)

2.4 输入输出

输入:prompt

弹出一个输入框

// 弹出一个输入框
prompt("请输入您的姓名");

输出:alert

弹出一个警示对话框,输出结果

// 弹出一个输出框
alert("你好!");

输出:console.log

在控制台打印一个日志(供程序员查看)

// 向控制台输出日志
console.log("这是一条日志");

console 是 js 中的“对象”
. 表示取对象中的某个属性或者方法

3.语法概览

3.1 变量的使用

基本用法

创建变量(变量定义/变量声明/变量初始化)
var name = 'zhangsan';
var age = 20;

var 是 JS 中的关键字,表示这是一个变量
= 在 JS 中表示“赋值”,相当于把数据放到内存的盒子中, = 两侧建议有一个空格
每个语句最后带有一个 ; 结尾。JS 中可以省略但是建议加上
注意,此处的 ; 为英文分号。 JS 中的标点都是英文标点
初始化的值如果是字符串,那么就需要使用单引号或者双引号引起来
初始化的值如果是数字,直接赋值即可
在 JS 中的数字只有一种类型:数值类型(包括整数和小数)
JS 中定义一个变量时不需要对该变量指定类型

创建变量也可以使用 let。
let 出现时间比 var 出现的晚,意味着避免了一些 var 定义变量时的缺陷。
如果使用 let 定义变量,此变量的生命周期、作用域基本和Java类似(推荐使用 let)

使用变量
console.log(age); // 读取变量内容
age = 30; // 修改变量内容

变量需要先声明才能使用

代码示例: 弹框提示用户输入信息, 再弹框显示.

let name = prompt("请输入姓名");
let age = prompt("请输入年龄");
let score = prompt("请输入分数");

alert("您的姓名是" + name);
alert("您的年龄是" + age);
alert("您的分数是" + score);

也可以把三个输出内容合并成一次弹框

let name = prompt("请输入姓名");
let age = prompt("请输入年龄");
let score = prompt("请输入分数");

alert("您的姓名是" + name + "\n" + "您的年龄是" + age + "\n" + "您的分数是" + score);
  • + 表示字符串拼接,也就是把两个字符串首尾相接变成一个字符串
  • \n 表示换行

理解 动态类型

(1)JS 的变量类型是程序运行过程中才确定的(运行到 = 语句时才会确定类型)(弱类型)

let a = 10; // 数字
let b = "hehe"; // 字符串

(2)随着程序运行,变量的类型可能会发生改变(动态类型)

let a = 10; // 数字
a = "hehe"; // 字符串
  • 强类型变量/弱类型变量
    强类型变量意味着不同类型变量进行赋值时需要进行一定的手段(如强制类型转换)
    弱类型变量在不同类型的变量之间进行赋值的时候可以直接赋值
  • 动态类型变量/静态类型变量
    动态类型意味着代码在执行过程中,变量类型可以随时发生变化
    静态类型变量意味着变量定义的时候是什么类型,程序运行是该变量就是什么类型

3.2 基本数据类型

JS 中内置的几种类型

  • number:数字,不区分整数和小数
  • boolean:true 真, false 假
  • string:字符串类型
  • undefined:只有唯一的值 undefined,表示未定义的值
  • null:只有唯一的值 null,表示空值

number 数字类型

JS 中不区分整数和小数,统一都使用“数字类型”表示

数字进制表示

计算机中使用二进制表示数据,人用十进制
因为二进制在使用过程中不太方便
所以在日常使用二进制数字时会用 八进制 和 十六进制 来表示二进制数字

let a = 0b10; // 二进制,以 0b 开头
let b = 0o7; // 八进制,以 0o 开头
let c = 0x10; // 十六进制,以 0x 开头

注意:

  • 一个八进制数字对应三个二进制数字
  • 一个十六进制数字对应四个二进制数字(两个十六进制数字就是一个字节)
特殊的数字值
  • Infinity:无穷大,大于任何数字,表示数字已经超过了JS能表示的范围
  • -Infinity:负无穷大,小于任何数字,表示数字已经超过了JS能表示的范围
  • NaN:表示当前的结果不是一个数字
let max = Number.MAX_VALUE;
// 得到 Infinity
console.log(max * 2);
// 得到 -Infinity
console.log(-max * 2);
// 得到 NaN
console.log("haha" - 10);

注意:

  1. 负无穷大 和 无穷小 不一样。无穷小指的是无限趋近于0,值为 1 / Infinity
  2. 'haha' + 10 得到的结果不是 NaN,而是 ‘haha10’,计算时会把数字隐式转换成字符串,再进行字符串拼接
  3. 可以使用 isNaN 函数判定是不是一个非数字
console.log(isNaN(10)); // false
console.log(isNaN('haha' - 10)); // true

string 字符串类型

基本规则

字符串字面值需要使用引号引起来,单引号双引号均可

let a = "haha";
let b = "hehe";
// let c = hehe // 运行出错

如果字符串中本来已经包含引号:

// let msg = "My name is "zhangsan""; // 报错
let msg = "My name is \"zhangsan\""; // 正确,使用转义字符 \" 来表示字符串内部的引号

let msg = "My name is 'zhangsan'"; // 正确,搭配使用单双引号
let msg = 'My name is "zhangsan"'; // 正确,搭配使用单双引号
转义字符

有些字符不方便直接输入,于是要通过一些特殊方式来表示

  • \n
  • \\
  • \'
  • \"
  • \t
求长度

使用 String 的 length 属性即可

let a = "haha";
console.log(a.length);

let b = "哈哈";
console.log(b.length);

结果

4
2

单位为字符的数量

字符串拼接

使用 + 进行拼接

let a = "My name is ";
let b = "zhangsan";
console.log(a + b);

数字和字符串也可以进行拼接

let c = "My score is ";
let d = 100;
console.log(c + d);

要认准进行拼接的变量是字符串还是数字

console.log(100 + 100); // 200
console.log('100' + 100); // 100100

boolean 布尔类型

表示“真”和“假”

boolean 原本是数学中的概念(布尔代数)
在计算机中 boolean 意义重大,往往要搭配条件/循环完成逻辑判断

boolean 参与运算时当做 1 和 0 看待

console.log(true + 1);
console.log(false + 1);

这样的操作实际上是不科学的,实际开发中不应该这样写
boolean 参与运算后类型变为 number

undefined 未定义数据类型

如果一个变量没有被初始化过,结果就是 undefined,是 undefined 类型

let a;
console.log(a);

undefined 和字符串进行相加,结果进行字符串拼接

console.log(a + "10");

undefined 和数字进行相加,结果为 NaN

console.log(a + 10);

null 空值类型

null 表示当前的变量是一个“空值”

let b = null;
console.log(b + 10); // 10
console.log(b + "10"); // null10

注意:
null 和 undefined 都表示取值非法的情况,但侧重点不同
null 表示当时的值为空(相当于有一个空盒子)
undefined 表示当前的变量未定义(相当于连盒子都没有)

3.3 运算符

算术运算符

  • +
  • -
  • *
  • /
  • %

赋值运算符 & 复合赋值运算符

  • =
  • +=
  • -=
  • *=
  • /=
  • %=

自增自减运算符

  • ++ :自增1
  • -- :自减1

比较运算符

  • <
  • >
  • <=
  • >=
  • == :比较相等(会进行隐式类型转换,只比较内容)
  • !=
  • === :比较相等(不会进行隐式类型转换,比较内容和类型)
  • !==

逻辑运算符

  • &&
  • ||
  • !

位运算

  • & 按位与
  • | 按位或
  • ~ 按位取反
  • ^ 按位异或

移位运算

  • << 左移
  • >> 有符号右移(算术右移)
  • >>> 无符号右移(逻辑右移)

3.4 条件语句

if 语句

基本语法格式
// 形式1
if (条件1) {
    语句;
}

// 形式2
if (条件1) {
    语句;
} else {
    语句2;
}

// 形式3
if (条件1) {
    语句;
} else if (条件2) {
    语句2;
} else if (...) {
    语句···;
} else {
    语句N;
}

例:判断输入的数字是奇数还是偶数

let num = prompt("请输入数字");
if(num % 2 == 0){
    alert("输入的数字" + num + "是偶数");
}else if(num % 2 == 1 || num % 2 == -1){
    alert("输入的数字" + num + "是奇数");
}else{
    alert("非法输入");
}

三元表达式

是 if else 的简化写法

条件 ? 表达式1 : 表达式2;

条件为真返回表达式1,条件为假返回表达式2

注意:三元表达式的优先级是比较低的

例:三元表达式判断奇偶

let num = prompt("请输入数字");
num % 2 == 0 ? alert("输入的数字" + num + "是偶数") : alert("输入的数字" + num + "是奇数");

switch

更适合多分支的场景

switch(表达式){
    case1:
        语句1;
        break;
    case2:
        语句2;
        break;
    default:
        语句N;
}

例:用户输入一个整数,提示今天星期几

let day = prompt("请输入今天星期几");
day = parseInt(day); // 用户输入的 day 为字符串形式,需要将字符串转换成数字
switch(day){
    case 1:
        alert("今天星期一");
        break;
    case 2:
        alert("今天星期二");
        break;
    case 3:
        alert("今天星期三");
        break;
    case 4:
        alert("今天星期四");
        break;
    case 5:
        alert("今天星期五");
        break;
    case 6:
        alert("今天星期六");
        break;
    case 7:
        alert("今天星期日");
        break;
    default:
        alert("输入有误");
}

3.5 循环语句

重复执行某些语句

while 循环

while(条件){
    循环体;
}

执行过程:

  • 先执行条件语句
  • 条件为 true,执行循环体
  • 条件为 false,直接结束循环

continue

结束本次循环

break

结束整个循环

for 循环

for (表达式1: 表达式2: 表达式3){
    循环体;
}
  • 表达式1:用来初始化循环变量
  • 表达式2:循环条件
  • 表达式3:更新循环变量

执行过程

  • 先执行表达式1,初始化循环变量
  • 再执行表达式2,判断循环条件
  • 如果条件为 false,结束循环
  • 如果条件为 true,则执行循环体代码
  • 执行表达式3,更新循环变量

3.6 数组

创建数组

使用 new 关键字创建
// Array 的 A 要大写
let arr = new Array();
使用字面量方式创建[常用]
let arr = [];
let arr2 = [1, 2, 3, '4']; // 数组中保存的内容称为“元素”

注意: JS 中的数组不要求元素是相同类型

获取数组元素

通过下标的方式获取数组元素(数组下标从 0 开始)

let arr = [1, 2, 3, '4'];
console.log(arr);
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
console.log(arr[3]);
arr[2] = "123";
console.log(arr);

在这里插入图片描述

如果下标超出范围读取元素,则结果为 undefined

console.log(arr[5]); // undefined
console.log(arr[-1]); // undefined

在这里插入图片描述

**注意:**不要给数组名直接赋值

let arr = [1, 2, 3, '4'];
console.log(arr);
arr = "12345";
console.log(arr);

在这里插入图片描述

相当于本来 arr 是一个数组,重新赋值之后变成了字符串

新增数组元素

通过修改 length 新增

相当于在末尾新增元素,新增的元素默认值为 undefined

let arr = [1, 2, 3, 4];
console.log(arr);
arr.length = 10;
console.log(arr);
console.log(arr[6]);

在这里插入图片描述

通过下标新增

如果下标超出范围赋值元素,则会给指定位置插入新元素

let arr = [];
arr[2] = 10;
console.log(arr);

在这里插入图片描述

此时这个数组的 [0] 和 [1] 都是 undefined

使用 push 进行追加元素

代码示例:将 arr 中的奇数放到 newArr 中

let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let newArr = [];
for(let i = 0; i < arr.length; i++){
if(arr[i] % 2 != 0){
    newArr.push(arr[i]);
}
}
console.log(arr);
console.log(newArr);

在这里插入图片描述

删除数组中的元素

使用 splice 方法删除元素

let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(arr);
arr.splice(1, 1);
console.log(arr);

第一个参数表示从下标为 1 的位置开始删除,第二个参数表示要删除的元素个数是 1 个

属性和方法
arr.length:length 使用的时候不带括号,此时 length 就是一个普通的变量(称为成员变量,也叫属性)
arr.push()、arr.splice():使用的时候带括号,并且可以传一个参数,此时是一个函数(也叫方法)

3.7 函数

语法格式

function 函数名(形参列表){
    函数体;
    return 返回值;
}

// 函数调用
函数名(实参列表); // 不考虑返回值
返回值 = 函数名(实参列表); // 考虑返回值
  • 函数定义不会执行函数体中的内容,必须调用才会执行,调用几次就执行几次
function hello(){
    console.log("hello");
}

function hello2(name){
    console.log(name + ",hello");
    return 1;
}

// 将没有返回值的函数赋值给一个变量,该变量是 undefined
let a = hello();
// 将有返回值的函数赋值给一个变量,该变量的类型就是函数返回值的类型
let b = hello2("123");
  • 调用函数的时候进入函数内部执行,函数结束时回到调用位置继续执行
  • 函数的定义和调用的先后顺序没有要求
// 调用函数
hello();
// 定义函数
function hello(){
    console.log("hello");
}

关于参数个数

实参和形参之间的个数可以不匹配,但实际开发中一般要求形参和实参个数要匹配
(1)如果实参个数比形参多,则多出的参数不参与函数运算

function sum(num1, num2){
    return num1 + num2;
}

sum(10, 20, 30); // 30

(2)如果实参个数比形参个数少,则此时多出的形参值为 undefined

function sum(num1, num2){
    return num1 + num2;
}

sum(10); // undefined

函数表达式

另一种函数的定义方式

let add = function(){
    let sum = 0;
    // arguments 参数列表
    for(let i = 0; i < arguments; i++){
        sum += arguments[i];
    }
    return sum;
}

console.log(add(10, 20)); // 30
console.log(add(1, 2, 3, 4)); // 10

console.log(typeof add); // function

此时形如 function(){} 这样的写法定义了一个匿名函数,然后这个匿名函数用一个变量来表示,后面就可以通过这个 add 变量来调用函数了

JS 中函数是一等公民,可以用变量保存,也可以作为其他函数的参数或者返回值

作用域

某个表示符名字在代码中的有效范围
在 SE6 标准之前,作用域主要分为两个:

  • 全局作用域:在整个 script 标签中或单独的 js 文件中生效
  • 局部作用域/函数作用域:在函数内部生效
let num = 10; // 全局变量
function test01(){
    let num = 100; // 局部变量
    console.log(num);
}
function test02(){
    let num = 200; // 局部变量
    console.log(num);
}
console.log(num);
test01();
test02();

创建变量时如果不写 var 也不写 let,就会得到一个全局变量

function test() {
    num = 100;
}
test();
console.log(num);

很多语言的局部变量作用域是按照代码块(大括号)来划分的, 在 ES6 之前的JS,var 没有块级作用域,只有函数作用域

作用域链

  • 函数可以定义在函数内部
  • 内部函数可以访问外层函数的局部变量

内部函数可以访问外部函数的变量,采取的是链式查找的方式,从内到外依次查找

3.8 对象

基本概念

对象指一个具体的事物
在 JS 中,字符串、数值、数组、函数都是对象
每个对象中包含若干属性和方法

  • 属性:事物的特征
  • 方法:事物的行为
使用 字面量 创建对象[常用]

使用 {} 创建对象

let a = {}; // 创建了一个空对象

let student = {
    name : "小明",
    height : 175,
    weight : 70,
    sayHello : function(){
        console.log("hello");
    }
};
  • 使用 {} 创建对象
  • 属性和方法使用 键值对 的形式来组织
  • 键值对之间使用 ‘,’ 分隔,最后一个属性后面可以不加 ‘,’
  • 键和值之间使用 ‘:’ 分隔
  • 方法的值是一个匿名函数

使用对象的属性和方法

// 1.使用 . 成员访问运算符来访问属性
console.log(student.name);
// 2.使用 [] 访问属性,此时属性需要加上引号
console.log(student['height']);
// 3.调用方法,不要忘记()
console.log(student.sayHello());
使用 new Object 创建对象
let student = new Object(); // 和创建数组类似

student.name = "小明";
student.height = 175;
student.weight = 70;
student.sayHello = function(){
    console.log("hello");
}

console.log(student.name);
console.log(student["height"]);
student.sayHello();

注意:使用 {} 创建的对象也可以随时使用 student.name = "小明"; 这样的方式新增属性

使用 构造函数 创建对象

前面两个创建方式只能创建一个对象,而使用构造函数可以很方便的创建多个对象

function 构造函数名(形参){
    this.属性 =;
    this.方法 = function ...
}

let obj = new 构造函数名(实参);

注意:

  • 在构造函数内部使用 this 关键字来表示当前正在构建的对象
  • 构造函数的函数名首字母一般大写
  • 构造函数的函数名可以是名词
  • 构造函数不需要 return
  • 创建对象的时候必须使用 new 关键字

使用构造函数创建两个 Person 对象

function Person(name, height, weight){
    this.name = name;
    this.height = height;
    this.weight = weight;
    this.say = function(){
        console.log(name + "正在说");
    }
}

let xiaoming = new Person("小明", 175, 70);
let zhangsan = new Person("张三", 175, 70);

console.log(xiaoming);
console.log(zhangsan);
class

ES6中引入了 class,可以使用 class 构造对象

class Person{
    constructor(name, height, weight){
        this.name = name;
        this.height = height;
        this.weight = weight;
    }
    say(){
        console.log(this.name + "正在说");
    }

    static other = "other";
}

let xiaoming = new Person("小明", 175, 70);
xiaoming.say();
console.log(Person.other);
  • constructor:构造函数
  • class 中定义方法直接写 方法名(){}
  • class 中可以定义 static 属性或方法,这个属性或方法不属于对象,属于整个类
class Student extends Person{
    constructor(name, height, weight, number){
        super(name, height, weight);
        this.number = number;
    }
    // 重写 say 方法
    say(){
        console.log("学生" + this.name + "正在说话")
    }
}

let student = new Student("张三", 175, 70, 1);
console.log(student);
  • 使用 extends 实现类继承, super() 用于调用父类构造方法
  • 子类可重写父类方法
Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐