当前位置: 首页 > news >正文

前端学习——JavaScript基础

        前面我们已经学习了前端代码的骨架——HTML和前端美化工具——CSS。但是作为界面与客户进行交互我们还需要一个语言工具——JavaScript。

        因此实际上HTML、CSS、JavaScript三者是这样的关系:

        HTML: 网页的结构(骨)

        CSS: 网页的表现(皮)

        JavaScript: 网页的行为(魂)

        接下来我们就来深入学习JavaScript。

        相关代码已经上传至博客中前端学习代码: 前端学习,喜欢请点个赞谢谢

目录

JavaScript的介绍

发展历史

特点

优势

应用领域

JavaScript的运行过程

JavaScript的组成

重要概念:ECMAScript        

前置知识

        JavaScript的书写形式

        行内式

        内嵌式

        外部式

        注释

        输入输出

        输入:prompt

        输出:alert

        输出:console.log

重要概念: 日志

重要概念: .

JavaScript语法学习

        变量

        创建变量

        使用变量

        动态类型

        基本数据类型

        number类型

        数字进制表示

        特殊的数字值

        string 字符串类型        

        转义字符

        求长度

        字符串拼接

        boolean 布尔类型

        undefined 未定义数据类型

        null 空值类型        

        运算符

        运算符优先级

条件语句

        if

        三元表达式

        switch 

        循环语句

        while循环

        for循环

        数组

        创建数组

        访问数组

        新增数组元素

        1. 通过修改 length 新增

        2. 通过下标新增

        3. 使用 push 进行追加元素

        删除数组中的元素

        函数

        关于参数个数

        函数表达式

        作用域

        作用域链

        对象

        基本概念

        使用 字面量 创建对象 [常用]

        使用 new Object 创建对象

        使用 构造函数 创建对象

        基本语法

        理解new关键字

JavaScript 的对象和 Java 的对象的区别

        1. JavaScript 没有 "类" 的概念

        2. JavaScript 对象不区分 "属性" 和 "方法"

        3. JavaScript 对象没有 private / public 等访问控制机制.

        4. JavaScript 对象没有 "继承"

        5. JavaScript 没有 "多态"


JavaScript的介绍

        JavaScript (简称 JS) 是一种高级的、解释型的编程语言。它最初被设计用于让网页“动起来”,如今已发展成为一门功能全面、无处不在的编程语言,是 Web 技术的三大核心之一(另外两个是 HTML 和 CSS)。

发展历史

时间事件意义
1995由 Brendan Eich 在网景公司(Netscape)用时10天创建,最初名为 Mocha,后改为 LiveScript,最终定名为 JavaScript诞生之初,旨在为浏览器增加动态交互能力。
1997ECMAScript 1 标准发布(由 ECMA 国际组织制定)。JavaScript 拥有了标准规范,确保了不同浏览器能够遵循同一标准实现。
2009ES5 发布,带来了严格的严格模式JSON支持等。同时,Node.js 诞生。JS 突破了浏览器的界限,可以用于开发服务器端程序,成为一门全栈语言。
2015ES6 (ECMAScript 2015) 发布,带来了let/const箭头函数Promise等革命性新特性。现代 JavaScript 的开端,语言能力得到巨大提升,满足了开发复杂应用的需求。
至今每年发布一个新版本(ES2016, ES2017...),以渐进的方式持续加入新特性。语言保持活力,不断进化,适应

特点

  1. 解释型语言:代码在运行时逐行被解释和执行,无需预先编译。

  2. 动态类型:变量在声明时不需要指定数据类型,类型在运行时才确定。

  3. 单线程与异步编程:核心执行模型是单线程的,但通过 事件循环(Event Loop) 和 回调函数(Callback) 机制(以及后来的 Promise 和 async/await)来处理异步操作,避免了阻塞。

  4. 基于原型(Prototype-based):不同于 Java、C++ 的基于类(Class-based)的继承,JS 使用原型链来实现对象继承(ES6 的 class 只是语法糖,其底层仍是基于原型)。

  5. 跨平台:只要有 JavaScript 引擎(如浏览器中的 V8、SpiderMonkey),JS 代码就可以在任何平台上运行(Windows, macOS, Linux, 移动设备等)。

优势

  1. 无处不在所有现代浏览器都内置了 JS 引擎,无需额外安装环境即可运行。这使得它成为了前端开发的唯一选择。

  2. 强大的生态系统:拥有全球最大的开源包管理系统 npm (Node Package Manager),海量的第三方库和框架可供使用,极大地提高了开发效率。

  3. 全栈开发:通过 Node.js,开发者可以使用同一种语言同时编写前端和后端代码,降低了上下文切换成本。

  4. 易学性:入门门槛相对较低,简单的语法和灵活的规则使其对初学者友好。

  5. 社区活跃:拥有极其庞大和活跃的开发者社区,遇到问题时很容易找到解决方案和学习资源。

  6. ** versatility (多用途性)**:除了Web开发,还可用于移动应用(React Native, Ionic)、桌面应用(Electron)、游戏开发、甚至物联网(IoT)等领域。

应用领域

领域说明常用技术
Web 前端开发实现网页的动态交互、动画、数据验证、与后端API通信等。React, Angular, Vue.js, jQuery
服务器端开发构建高性能的服务器、Web API、后端服务。Node.js, Express.js, Koa, NestJS
移动应用开发使用JS编写跨平台的移动应用程序(iOS & Android)。React Native, Ionic, NativeScript
桌面应用开发使用Web技术(HTML, CSS, JS)构建跨平台的桌面应用程序。Electron (如VSCode, Slack, Discord), NW.js
游戏开发开发浏览器游戏或通过引擎开发更复杂的游戏。Phaser, Three.js, Babylon.js
数据库操作某些NoSQL数据库直接使用JS进行查询和操作。MongoDB

JavaScript的运行过程

        编写的代码是保存在文件中的, 也就是存储在硬盘(外存上).

        双击 .html 文件浏览器(应用程序)就会读取文件, 把文件内容加载到内存中(数据流向: 硬盘 => 内存)浏览器会解析用户编写的代码, 把代码翻译成二进制的, 能让计算机识别的指令(解释器的工作)

        得到的二进制指令会被 CPU 加载并执行(数据流向: 内存 => CPU)

        浏览器分成渲染引擎 + JS 引擎.

        渲染引擎: 解析 html + CSS, 俗称 "内核"

        JS 引擎: 也就是 JS 解释器. 典型的就是 Chrome 中内置的 V8 JS 引擎逐行读取 JS 代码内容, 然后解析成二进制指令, 再执行

JavaScript的组成

组成部分全称描述类比
ECMAScript-语言核心,定义了语言的语法和基本对象。C++标准库。提供了std::vectorstd::string等基础组件。
DOM文档对象模型将HTML文档抽象成一个树形结构,并提供了一套允许JS与页面内容进行交互的API(如增删改查HTML元素、修改样式、处理事件)。一个UI框架(如Qt、MFC)。C++代码通过调用Qt的API来创建按钮、处理点击事件。JS通过调用DOM API来操作网页。
BOM浏览器对象模型提供与浏览器窗口本身交互的API。由于缺乏标准,不同浏览器实现略有不同。包括:
• navigator:浏览器信息
• location:当前URL信息
• history:浏览器历史记录
• screen:屏幕信息
• window:全局对象,代表浏览器窗口
操作系统API。就像C++程序调用Windows API来操作窗口大小、获取系统信息一样

简单来说:

  • ECMAScript 是 语言本身

  • DOM 是 操作网页 的接口。

  • BOM 是 操作浏览器 的接口。

重要概念:ECMAScript        

  • ECMAScript (ES): 是由 ECMA国际 组织标准化的脚本语言规范。它定义了语言的语法、类型、语句、关键字、保留字、操作符、对象等核心内容。它是一本“规则书”,告诉你这种语言应该怎么写,有哪些功能。

  • JavaScript (JS): 是 对 ECMAScript 规范的实现和扩展。除了实现ES规范,JavaScript 在浏览器中还包含了其他功能(如DOM、BOM,下面会讲)。

前置知识

        JavaScript的书写形式

        行内式

        直接嵌入到 html 元素内部

<input type="button" value="点我一下" onclick="alert('haha')">

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

        HTML 中推荐使用双引号, JS 中推荐使用单引号.

        内嵌式

        写到 script 标签中

<script>alert("haha");
</script>

        外部式

        写到单独的 .js 文件中

<script src="hello.js"></script>
alert("hehe");


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

        适合代码多的情况.

        注释

        单行注释 //

        多行注释 /* */

        使用 ctrl + / 切换注释.

        多行注释不能嵌套.

        输入输出

        输入:prompt

        弹出一个输入框

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

        输出:alert

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

// 弹出一个输出框
alert("hello");

        输出:console.log

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

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

        注意: 在 VSCode 中直接输入 "log" 再按 tab 键, 就可以快速输入 console.log

        需要打开浏览器的开发者工具(F12) => Console 标签页 才能看到结果.
        

        这是给程序员看的,不是给用户看的

重要概念: 日志

        日志是程序员调试程序的重要手段

        去医院看病, 医生会让患者做各种检查, 血常规, 尿常规, B超, CT等... 此时得到一堆检测结果. 这些结果普通人看不懂, 但是医生能看懂, 并且医生要通过这些信息来诊断病情.

        这些检测结果就是医生的 "日志"

        PS: 相比于医生来说, 程序猿多一个终极大招, "重启下试试"

重要概念: .

        console 是一个 js 中的 "对象"

        . 表示取对象中的某个属性或者方法. 可以直观理解成 "的" console.log 就可以理解成: 使用 "控制台" 对象 "的" log 方法

JavaScript语法学习

        变量

        创建变量

var name = 'zhangsan';
var age = 20;

        JavaScript中定义变量不需要进行类型说明

        var 是 JS 中的关键字, 表示这是一个变量.

        = 在 JS 中表示 "赋值", 相当于把数据放到内存的盒子中. = 两侧建议有一个空格每个语句最后带有一个 ; 结尾. JS 中可以省略 ; 但是建议还是加上.

        注意, 此处的 ; 为英文分号. JS 中所有的标点都是英文标点.

        初始化的值如果是字符串, 那么就要使用单引号或者双引号引起来.

        初始化的值如果是数字, 那么直接赋值即可.

        除此之外还可以用let来定义变量

        二者之间区别如下

特性varlet (以及 const)解释与说明
作用域函数作用域块级作用域最核心的区别var 的作用域是整个函数,而 let 的作用域仅限于其所在的 {} 块内(如 ifforwhile 或单独的 {})。
变量提升提升且初始化值为 undefined提升但未被初始化两者都会被提升到其作用域的顶部。但 var 变量会被初始化为 undefined,而 let 变量在声明之前处于 “暂时性死区” ,访问会抛出 ReferenceError
重复声明允许不允许在相同作用域内,用 var 重复声明同一个变量不会报错(这通常是 bug 的来源)。而用 let 重复声明会立即导致 SyntaxError
全局对象属性在全局作用域下,用 var 声明的变量会成为全局对象(浏览器中是 window)的属性。let 声明的变量则不会。
循环中的表现有问题符合预期在 for 循环中,var 由于是函数作用域,会导致所有迭代共享同一个变量引用。let 则为每次迭代创建一个新的块级作用域绑定,表现正常。

  为什么强烈推荐使用 let

        基于以上区别,推荐使用 let 的主要原因如下

        1、块级作用域避免了意外的变量泄露和污染
var 的函数作用域反直觉,尤其是在 if 和 for 循环中,变量会泄露到外部作用域,极易引发难以追踪的 bug。let 的块级作用域与 C++、Java 等语言的行为一致,更符合直觉,能更好地控制变量的生命周期。

示例:循环中的变量泄露

// 使用 var - i 会泄露到循环外部
for (var i = 0; i < 10; i++) { /* ... */ }
console.log(i); // 10 (依然可以访问到 i)// 使用 let - i 被完美封装在循环内部
for (let j = 0; j < 10; j++) { /* ... */ }
console.log(j); // ReferenceError: j is not defined (符合预期)

        2、暂时性死区避免了在声明前使用变量
虽然 var 和 let 都存在提升,但 let 的暂时性死区机制强制要求你先声明再使用。这迫使开发者写出更规范、更可预测的代码,避免了因提升而导致的逻辑错误。

示例:声明前使用

console.log(a); // 输出 undefined (诡异的行为)
var a = 10;console.log(b); // ReferenceError: Cannot access 'b' before initialization
let b = 20;     // 直接报错,更容易发现错误
  1. 禁止重复声明消除了潜在的命名冲突
    在大型项目或协作开发中,禁止重复声明可以有效地避免因不小心重命名变量而导致的意外覆盖,使代码更加安全。

  2. 更现代的语法标准
    let 和 const 是 ES6 (2015) 引入的现代标准。使用它们意味着你在编写更现代、更规范的 JavaScript。几乎所有新的代码库和教程都默认使用 let/const

        因此在现代JavaScript开发中尽量避免使用var

        使用变量

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

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

var name = prompt("请输入姓名:");
var age = prompt("请输入年龄:");
var score = prompt("请输入分数");
alert("您的姓名是: " + name);
alert("您的年龄是: " + age);
alert("您的分数是: " + score);

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

var name = prompt("请输入姓名:");
var age = prompt("请输入年龄:");
var score = prompt("请输入分数");
alert("您的姓名是: " + name + "\n" + "您的年龄是: " + age + "\n" + "您的分数是: " +
score + "\n");

        + 表示字符串拼接, 也就是把两个字符串首尾相接变成一个字符串.

        \n 表示换行

        动态类型

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

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

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

var a = 10; // 数字
a = "hehe"; // 字符串

        这一点和 C Java 这种静态类型语言差异较大.

        C, C++, Java, Go 等语言是静态类型语言. 一个变量在创建的时候类型就确定了, 不能在运行时发生改变。如果尝试改变, 就会直接编译报错.

        基本数据类型

        JS 中内置的几种类型

        number: 数字. 不区分整数和小数.

        boolean: true 真, false 假.

        string: 字符串类型.

        undefined: 只有唯一的值

        undefined. 表示未定义的值.

        null: 只有唯一的值

        null. 表示空值

        number类型

        JS 中不区分整数和浮点数, 统一都使用 "数字类型" 来表示

        数字进制表示

        计算机中都是使用二进制来表示数据, 而人平时都是使用十进制.因为二进制在使用过程中不太方便(01太多会看花眼).

        所以在日常使用二进制数字时往往使用 八进制 和 十六进制 来表示二进制数字

var a = 07; // 八进制整数, 以 0 开头
var b = 0xa; // 十六进制整数, 以 0x 开头
var c = 0b10; // 二进制整数, 以 0b 开头

        注意:

        一个八进制数字对应三个二进制数字

        一个十六进制数字对应四个二进制数字. (两个十六进制数字就是一个字节)各种进制之间的转换, 不需要手工计算, 直接使用计算器即可.

        特殊的数字值

        Infinity: 无穷大, 大于任何数字. 表示数字已经超过了 JS 能表示的范围.

        -Infinity: 负无穷大, 小于任何数字. 表示数字已经超过了 JS 能表示的范围.

        NaN: 表示当前的结果不是一个数字.

        注意:

        1. 负无穷大 和 无穷小 不是一回事. 无穷小指无限趋近与 0, 值为 1 / Infinit

        2. 'hehe' + 10 得到的不是 NaN, 而是 'hehe10', 会把数字隐式转成字符串, 再进行字符串拼接.

        3. 可以使用 isNaN 函数判定是不是一个非数字.

console.log(isNaN(10)); // false
console.log(isNaN('hehe' - 10)); // true

        string 字符串类型

        

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

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

        如果文本中有引号,可以这么处理

var msg = "My name is "zhangsan""; // 出错
var msg = "My name is \"zhangsan\""; // 正确, 使用转义字符. \" 来表示字符串内部的引
号.
var msg = "My name is 'zhangsan'"; // 正确, 搭配使用单双引号
var msg = 'My name is "zhangsan"'; // 正确, 搭配使用单双引号
        转义字符

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

转义序列名称描述与示例
\0空字符表示 Unicode 值为 0 的字符(空字符)
示例:"Hello\0World" - 在字符串中间插入空字符
\'单引号在由单引号定义的字符串中表示单引号字符
示例:'It\'s a beautiful day' - 输出: It's a beautiful day
\"双引号在由双引号定义的字符串中表示双引号字符
示例:"He said, \"Hello!\"" - 输出: He said, "Hello!"
\\反斜杠表示字面意义上的反斜杠字符
示例:"C:\\Windows\\System32" - 输出: C:\Windows\System32
\n换行符插入一个新行(在Unix/Linux和macOS中常用)
示例:"Line 1\nLine 2" - 输出两行文本
\r回车符将光标移动到行首(在旧版Mac OS中用作行结束符)
示例:"Loading...\rDone" - 输出: Done...(覆盖效果)
\v垂直制表符插入一个垂直制表符(很少使用)
示例:"Column1\vColumn2" - 垂直对齐文本
\t水平制表符插入一个制表符(通常相当于4或8个空格)
示例:"Name:\tJohn" - 输出: Name: John
\b退格符将光标向后移动一个位置(在某些环境下会删除前一个字符)
示例:"Hello\b World" - 可能输出: Hell World
\f换页符表示换页(主要用于打印机控制)
示例:"Page 1\fPage 2" - 在打印时换页
\uXXXXUnicode转义使用4位十六进制数表示Unicode字符
示例:"\u00A9" - 输出: © (版权符号)
\u{X...}
\u{XXXXXX}
Unicode码点转义使用1-6位十六进制数表示Unicode字符(ES6新增)
示例:"\u{1F604}" - 输出: 😄 (笑脸表情)
\xXX拉丁字符转义使用2位十六进制数表示Latin-1字符
示例:"\xA9" - 输出: © (版权符号)
\<行末>行继续符在字符串中换行而不插入实际换行符(ES5+)
示例:"This is a very long \<br>string that spans two lines." - 单行字符串
        求长度

        使用 String 的 length 属性即可

var a = 'hehe';
console.log(a.length);
var b = '哈哈';
console.log(b.length);

        结果:

4 2

        单位为字符的数量


        字符串拼接

        
        使用 + 进行拼接

var a = "my name is ";
var b = "zhangsan";
console.log(a + b);

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

var c = "my score is ";
var 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);
//这样的操作其实是不科学的. 实际开发中不应该这么写

        undefined 未定义数据类型
 

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

var a;
console.log(a)

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

console.log(a + "10"); // undefined10

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

console.log(a + 10);

        null 空值类型
        

        null 表示当前的变量是一个 "空值".

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

        注意:

        null 和 undefined 都表示取值非法的情况, 但是侧重点不同

        null 表示当前的值为空. (相当于有一个空的盒子)

        undefined 表示当前的变量未定义. (相当于连盒子都没有)

        运算符

分类运算符名称功能描述示例
算术运算符+加法对两个操作数进行加法运算,如果有一个操作数是字符串,则进行字符串拼接5 + 3 // 8 'Hello' + 'World' // 'HelloWorld'
-减法对两个操作数进行减法运算5 - 3 // 2
*乘法对两个操作数进行乘法运算5 * 3 // 15
/除法对两个操作数进行除法运算10 / 2 // 5
%取模返回两个操作数相除的余数10 % 3 // 1
**指数计算第一个操作数的第二个操作数次幂2 ** 3 // 8
++自增将操作数增加1(可以前置或后置)let x=5; x++ // x=6
--自减将操作数减少1(可以前置或后置)let x=5; x-- // x=4
赋值运算符=赋值将右侧的值赋给左侧的变量let x = 5
+=加法赋值将左侧变量与右侧值相加,结果赋给左侧变量x += 3 // x = x + 3
-=减法赋值将左侧变量减去右侧值,结果赋给左侧变量x -= 3 // x = x - 3
*=乘法赋值将左侧变量乘以右侧值,结果赋给左侧变量x *= 3 // x = x * 3
/=除法赋值将左侧变量除以右侧值,结果赋给左侧变量x /= 3 // x = x / 3
%=取模赋值将左侧变量与右侧值取模,结果赋给左侧变量x %= 3 // x = x % 3
**=指数赋值将左侧变量与右侧值进行指数运算,结果赋给左侧变量x **= 3 // x = x ** 3
比较运算符==相等比较两个操作数是否相等(会进行类型转换)5 == '5' // true
!=不等比较两个操作数是否不相等(会进行类型转换)5 != '6' // true
===严格相等比较两个操作数是否相等(不会进行类型转换)5 === '5' // false
!==严格不等比较两个操作数是否不相等(不会进行类型转换)5 !== '5' // true
>大于检查左操作数是否大于右操作数5 > 3 // true
<小于检查左操作数是否小于右操作数5 < 3 // false
>=大于等于检查左操作数是否大于或等于右操作数5 >= 5 // true
<=小于等于检查左操作数是否小于或等于右操作数5 <= 3 // false
逻辑运算符&&逻辑与如果两个操作数都为真,则返回真,否则返回假true && false // false
||逻辑或如果两个操作数中有一个为真,则返回真,否则返回假true || false // true
!逻辑非如果操作数为真,则返回假,反之返回真!true // false
位运算符&按位与对两个操作数的每一个二进制位进行与操作5 & 1 // 1
|按位或对两个操作数的每一个二进制位进行或操作5 | 1 // 5
^按位异或对两个操作数的每一个二进制位进行异或操作5 ^ 1 // 4
~按位非对操作数的每一个二进制位取反~5 // -6
<<左移将第一个操作数的二进制形式向左移动指定位数5 << 1 // 10
>>右移将第一个操作数的二进制形式向右移动指定位数(保留符号位)5 >> 1 // 2
>>>无符号右移将第一个操作数的二进制形式向右移动指定位数(不保留符号位)5 >>> 1 // 2
条件运算符? :三元条件根据条件选择两个值中的一个:condition ? expr1 : expr2age >= 18 ? '成人' : '未成年'
逗号运算符,逗号从左到右计算多个表达式,并返回最后一个表达式的值let x = (5, 10) // x=10
一元运算符delete删除删除对象的属性或数组的元素delete obj.property
typeof类型返回一个字符串,表示未经计算的操作数的类型typeof 5 // "number"
void无效执行表达式并返回undefinedvoid(0)
关系运算符in属性存在如果指定的属性在指定的对象中,则返回true'name' in obj
instanceof实例检查如果对象是指定构造函数的实例,则返回trueobj instanceof Array
其他运算符new创建实例创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例new Date()
yield暂停函数暂停和恢复生成器函数function* gen() { yield 1; }
...展开/剩余展开数组或对象,或用于收集剩余参数[...arr], {...obj}, function(...args)
??空值合并如果左侧操作数为null或undefined,则返回右侧操作数,否则返回左侧操作数null ?? 'default' // 'default'
?.可选链允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效
        运算符优先级

        以下是 JavaScript 中所有运算符的优先级列表,从最高优先级(20)到最低优先级(1)。同一行中的运算符具有相同的优先级。

20分组( ... )不适用表达式分组
19成员访问.从左到右对象属性访问
需计算的成员访问[ ... ]从左到右对象属性访问(使用变量或表达式)
new(带参数列表)new ... ( ... )不适用创建实例(带参数)
函数调用( ... )从左到右函数调用
可选链?.从左到右可选属性访问
18new(无参数列表)new ...从右到左创建实例(无参数)
17后置递增... ++不适用后置递增
后置递减... --不适用后置递减
16逻辑非! ...从右到左逻辑非
按位非~ ...从右到左按位非
一元加法+ ...从右到左一元正号
一元减法- ...从右到左一元负号
前置递增++ ...从右到左前置递增
前置递减-- ...从右到左前置递减
typeoftypeof ...从右到左类型检查
voidvoid ...从右到左返回 undefined
deletedelete ...从右到左删除属性
awaitawait ...从右到左等待 Promise
15... ** ...从右到左指数运算
14乘法... * ...从左到右乘法
除法... / ...从左到右除法
取模... % ...从左到右取模(求余)
13加法... + ...从左到右加法或字符串连接
减法... - ...从左到右减法
12按位左移... << ...从左到右按位左移
按位右移... >> ...从左到右按位右移(保留符号)
无符号右移... >>> ...从左到右无符号右移
11小于... < ...从左到右小于比较
小于等于... <= ...从左到右小于等于比较
大于... > ...从左到右大于比较
大于等于... >= ...从左到右大于等于比较
in... in ...从左到右属性存在检查
instanceof... instanceof ...从左到右实例检查
10相等... == ...从左到右相等比较(允许类型转换)
不相等... != ...从左到右不相等比较(允许类型转换)
严格相等... === ...从左到右严格相等比较(不允许类型转换)
严格不相等... !== ...从左到右严格不相等比较(不允许类型转换)
9按位与... & ...从左到右按位与操作
8按位异或... ^ ...从左到右按位异或操作
7按位或... | ...从左到右按位或操作
6逻辑与... && ...从左到右逻辑与操作
5逻辑或... || ...从左到右逻辑或操作
空值合并... ?? ...从左到右空值合并操作
4条件运算符... ? ... : ...从右到左三元条件操作
3赋值=从右到左赋值
+= -= *= /= %=从右到左运算赋值
**= <<= >>= >>>=从右到左运算赋值
&= ^= |= &&= ||= ??=从右到左运算赋值
2yieldyield ...从右到左生成器产出值
yield*yield* ...从右到左委托给另一个生成器
1逗号... , ...从左到右逗号操作符

条件语句

        if

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

        三元表达式

        

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

        为真执行表达式1,为假执行表达式2.

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

        switch 

        

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

        循环语句

        while循环

while (条件) 
{循环体;
}

        执行过程:

        先执行条件语句

        条件为 true, 执行循环体代码.条件为 false, 直接结束循环        

        for循环

for (表达式1; 表达式2; 表达式3) 
{循环体
}

        表达式1: 用于初始化循环变量.

        表达式2: 循环条件

        表达式3: 更新循环变量.执行过程:

        执行流程:

        先执行表达式1, 初始化循环变量再执行表达式2, 判定循环条件如果条件为 false, 结束循环

        如果条件为 true, 则执行循环体代码.执行表达式3 更新循环变量

        数组

        创建数组

        使用 new 关键字创建

// Array 的 A 要大写
var arr = new Array();

        使用字面量方式创建 [常用]

var arr = [];
var arr2 = [1, 2, 'haha', false]; // 数组中保存的内容称为 "元素"

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

这一点和 C, C++, Java 等静态类型的语言差别很大. 但是 Python, PHP 等动态类型语言也是如此

        访问数组

        使用下标的方式访问数组元素(从 0 开始)

var arr = ['小猪佩奇', '小猪乔治', '小羊苏西'];
console.log(arr);
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
arr[2] = '小猫凯迪';
console.log(arr);

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

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

        注意: 不要给数组名直接赋值, 此时数组中的所有元素都没

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

var arr = ['小猪佩奇', '小猪乔治', '小羊苏西'];
arr = '小猫凯迪';

        新增数组元素

        1. 通过修改 length 新增

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

var arr = [9, 5, 2, 7];
arr.length = 6;
console.log(arr);
console.log(arr[4], arr[5]);

        结果为:

        2. 通过下标新增

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

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

        结果为:

        

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


        3. 使用 push 进行追加元素

        代码示例: 给定一个数组, 把数组中的奇数放到一个 newArr 中.

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

        删除数组中的元素

        使用 splice 方法删除元素

var arr = [9, 5, 2, 7];
// 第一个参数表示从下表为 2 的位置开始删除. 第二个参数表示要删除的元素个数是 1 个
arr.splice(2, 1);
console.log(arr);
// 结果
[9, 5, 7]

        目前咱们已经用到了数组中的一些属性和方法.

arr.length, length 使用的时候不带括号, 此时 length 就是一个普通的变量(称为成员变量, 也叫属性)

arr.push(), arr.splice() 使用的时候带括号, 并且可以传参数, 此时是一个函数 (也叫做方法)

        函数

// 创建函数/函数声明/函数定义
function 函数名(形参列表) {
函数体
return 返回值;
}
// 函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值

        函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次.

function hello() {
console.log("hello");
}
// 如果不调用函数, 则没有执行打印语句
hello();

        调用函数的时候进入函数内部执行, 函数结束时回到调用位置继续执行. 可以借助调试器来观察.函数的定义和调用的先后顺序没有要求. (这一点和变量不同, 变量必须先定义再使用)

// 调用函数
hello();
// 定义函数
function hello() 
{console.log("hello");
}
        关于参数个数

        实参和形参之间的个数可以不匹配. 但是实际开发一般要求形参和实参个数要匹配

        (1)如果实参个数比形参个数多, 则多出的参数不参与函数运算

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

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

sum(10); // NaN, 相当于 num2 为 undefined.

        JavaScript传递参数相较于C/C++/Java这样的语言来说很灵活,不过实际上这种灵活并不是好事

        函数表达式
var add = function() 
{var sum = 0;for (var i = 0; i < arguments.length; 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 中函数是一等公民, 可以用变量保存, 也可以作为其他函数的参数或者返回值.

        作用域

        某个标识符名字在代码中的有效范围.在 ES6 标准之前, 作用域主要分成两个

        全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.局部作用域/函数作用域: 在函数内部生效.

// 全局变量
var num = 10;
console.log(num);
function test() 
{// 局部变量var num = 20;console.log(num);
}
function test2() 
{// 局部变量var num = 30;console.log(num);
}
test();
test2();
console.log(num);
// 执行结果
10
20
30
10

创建变量时如果不写 var, 则得到一个全局变量

function test() 
{num = 100;
}
test();
console.log(num);
// 执行结果
100

另外, 很多语言的局部变量作用域是按照代码块(大括号)来划分的, JS 在 ES6 之前不是这样的.

if (1 < 2) 
{var a = 10;
}
console.log(a);

        作用域链

        背景:

        函数可以定义在函数内部

        内层函数可以访问外层函数的局部变量.

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

        

var num = 1;
function test1() 
{var num = 10;function test2() {var num = 20;console.log(num);}test2();
}
test1();
// 执行结果
2

        执行 console.log(num) 的时候, 会现在 test2 的局部作用域中查找 num. 如果没找到, 则继续去 test1 中查找. 如果还没找到, 就去全局作用域查找.

        就像下面这张图:

        对象

        基本概念

        对象是指一个具体的事物.

        "电脑" 不是对象, 而是一个泛指的类别. 而 "我的联想笔记本" 就是一个对象.

        在 JS 中, 字符串, 数值, 数组, 函数都是对象.每个对象中包含若干的属性和方法.

        属性: 事物的特征.

        方法: 事物的行为.

        对象需要保存的属性有多个, 虽然数组也能用于保存多个数据, 但是不够好.

        例如表示一个学生信息. (姓名蔡徐坤, 身高 175cm, 体重 170斤) var student = ['蔡徐坤', 175, 170];但是这种情况下到底 175 和 170 谁表示身高, 谁表示体重, 就容易分不清

        JavaScript 的对象 和 Java 的对象概念上基本一致. 只是具体的语法表项形式差别较大.

        使用 字面量 创建对象 [常用]

        使用 { } 创建对象
 

var a = {}; // 创建了一个空的对象
var student = 
{name: '蔡徐坤',height: 175,weight: 170,sayHello: function() {console.log("hello");}
}

        使用 { } 创建对象

        属性和方法使用键值对的形式来组织.

        键值对之间使用 , 分割. 最后一个属性后面的 , 可有可无键和值之间使用 : 分割.

        方法的值是一个匿名函数.

        使用对象的属性和方法

// 1. 使用 . 成员访问运算符来访问属性 `.` 可以理解成 "的"
console.log(student.name);
// 2. 使用 [ ] 访问属性, 此时属性需要加上引号
console.log(student['height']);
// 3. 调用方法, 别忘记加上 ()
student.sayHello();

        使用 new Object 创建对象

var student = new Object(); // 和创建数组类似
student.name = "蔡徐坤";
student.height = 175;
student['weight'] = 170;
student.sayHello = function () 
{console.log("hello");
}
console.log(student.name);
console.log(student['weight']);
student.sayHello();

注意, 使用 { } 创建的对象也可以随时使用 student.name = "蔡徐坤"; 这样的方式来新增属性.



        使用 构造函数 创建对象

        

        前面的创建对象方式只能创建一个对象. 而使用构造函数可以很方便 的创建 多个对象.例如: 创建几个猫咪对象

var mimi = 
{name: "咪咪",type: "中华田园喵",miao: function () {console.log("喵");}
};
var xiaohei = 
{name: "小黑",type: "波斯喵",miao: function () {console.log("猫呜");}
}
var ciqiu = 
{name: "刺球",type: "金渐层",miao: function () {console.log("咕噜噜");}
}

此时写起来就比较麻烦. 使用构造函数可以把相同的属性和方法的创建提取出来, 简化开发过程.

        基本语法
function 构造函数名(形参) 
{this.属性 = 值;this.方法 = function...
}
var obj = new 构造函数名(实参);

        注意:

        在构造函数内部使用 this 关键字来表示当前正在构建的对象.构造函数的函数名首字母一般是大写的.

        构造函数的函数名可以是名词.

        构造函数不需要 return

        创建对象的时候必须使用 new 关键字. this 相当于 "我"

        示例:

function Cat(name, type, sound) 
{this.name = name;this.type = type;this.miao = function () {console.log(sound); // 别忘了作用域的链式访问规则}
}
var mimi = new Cat('咪咪', '中华田园喵', '喵');
var xiaohei = new Cat('小黑', '波斯喵', '猫呜');
var ciqiu = new Cat('刺球', '金渐层', '咕噜噜');
console.log(mimi);
mimi.miao();

        理解new关键字

        new 的执行过程:

        1. 先在内存中创建一个空的对象 { }

        2. this 指向刚才的空对象(将上一步的对象作为 this 的上下文)

        3. 执行构造函数的代码, 给对象创建属性和方法

        4. 返回这个对象 (构造函数本身不需要 return, 由 new 代劳了)

        参考以下资料:newhttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new

JavaScript 的对象和 Java 的对象的区别

        1. JavaScript 没有 "类" 的概念

        对象其实就是 "属性" + "方法" .

        类相当于把一些具有共性的对象的属性和方法单独提取了出来, 相当于一个 "月饼模子"在 JavaScript 中的 "构造函数" 也能起到类似的效果.

        而且即使不是用构造函数, 也可以随时的通过 { } 的方式指定出一些对象

        在 ES6 中也引入了 class 关键字, 就能按照类似于 Java 的方式创建类和对象了

        2. JavaScript 对象不区分 "属性" 和 "方法"

        JavaScript 中的函数是 "一等公民", 和普通的变量一样. 存储了函数的变量能够通过 ( ) 来进行调用执行.

        3. JavaScript 对象没有 private / public 等访问控制机制.

对象中的属性都可以被外界随意访问.

        4. JavaScript 对象没有 "继承"

        继承本质就是 "让两个对象建立关联". 或者说是让一个对象能够重用另一个对象的属性/方法. JavaScript 中使用 "原型" 机制实现类似的效果.

        5. JavaScript 没有 "多态"

        多态的本质在于 "程序猿不必关注具体的类型, 就能使用其中的某个方法".

        C++ / Java 等静态类型的语言对于类型的约束和校验比较严格. 因此通过 子类继承父类, 并重写父类的方法的方式 来实现多态的效果.

        但是在 JavaScript 中本身就支持动态类型, 程序猿在使用对象的某个方法的时候本身也不需要对对象的类型做出明确区分. 因此并不需要在语法层面上支持多态

        本期关于JavaScript的语法部分学习介绍到这里就结束了,喜欢请点个赞谢谢

封面图自取:

http://www.dtcms.com/a/359842.html

相关文章:

  • Vue2 与 Vue3 路由钩子的区别及用法详解
  • 电科金仓KingbaseES V9数据库:国产数据库的自主创新与行业实践深度解析
  • Nginx四层负载均衡实战指南
  • Redis 7.0 高性能缓存架构设计与优化
  • Spring Data JPA 派生查询方法命名速查表
  • 【51单片机】【protues仿真】基于51单片机智能晾衣架系统
  • git中使用SSH的配置
  • 从零开始搭建使用 TDengine:新用户快速上手指南
  • STAR法则
  • Encoder编码器
  • kafka服务端架构总览
  • sublime MAC系统快捷键及常见问题
  • 深入理解Nginx反向代理及其应用
  • 【机器学习学习笔记】numpy基础
  • Library cache lock常见案例分析(一)
  • TensorFlow 面试题及详细答案 120道(81-90)-- 其他框架/工具
  • 【重学MySQL】九十三、MySQL字符集与比较规则完全解析
  • 标定分享3--lidar与rtk/ins标定外参工程实现分享
  • SciPy
  • 【MLLM】具有长期记忆的多模态智能体框架M3-Agent
  • Uniapp 项目创建与目录结构解析
  • LangChain实战(七):Text Embedding Models与Vector Stores
  • 嵌入式ARM程序高级调试技能:19.qumu arm elf无法生成coredump
  • 829作业
  • DAY17-新世纪DL(DeepLearning/深度学习)战士:Q(机器学习策略)2
  • Claude Code干翻Cursor后,轮到AI浏览器了
  • 组件通信终极指南:从Props Drilling到Context API
  • MPI-NCCL-TEST 训练自检,基础通信和可用的机器
  • NM:微生物组数据分析的规划与描述
  • GDPU操作系统实验:生产者消费者问题