Javascript学习(一)
说起来网站都搭好了,现在才开始系统地学一遍Javascript,确实抽象。只不过也无所谓了,毕竟HTML和CSS学得也是依托()。放一个学习链接。对于这个网站也插播一句,开源精神yyds。
简介
JavaScript 是一种轻量级的脚本语言。所谓“脚本语言”(script language),指的是它不具备开发操作系统的能力,而是只用来编写控制其他大型应用程序(比如浏览器)的“脚本”。JavaScript 也是一种嵌入式语言,只能用来做一些数学和逻辑运算。JavaScript 本身不提供任何与 I/O(输入/输出)相关的 API,都要靠宿主环境(host)提供,所以 JavaScript 只合适嵌入更大型的应用程序环境,去调用宿主环境提供的底层 API。目前,已经嵌入 JavaScript 的宿主环境有多种,最常见的环境就是浏览器,另外还有服务器环境,也就是 Node 项目。
JS基础知识
- HTML 定义了网页的内容
- CSS 描述了网页的布局
- JavaScript 网页的行为
对应人的骨架、外貌和动作,写一篇博客来专门学Javascript。
hello world
经典hello world,代码如下:
1 |
|
JavaScript 可以通过不同的方式来输出数据:
- 使用 window.alert() 弹出警告框。
- 使用 document.write() 方法将内容写到 HTML 文档中。
- 使用 innerHTML 写入到 HTML 元素。
- 使用 console.log() 写入到浏览器的控制台。
注释
类似于C++:
- 单行://
- 多行:/* ………… */
变量
使用关键字 var 来定义变量,用于存储数据,使用等号来为变量赋值。 eg: var a,length;
JavaScript有以下几种数据类型:
- 值类型(基本类型):字符串(String)、数字(Number)、布尔(Boolean)、空(Null)、未定义(Undefined)、Symbol。
- 引用数据类型(对象类型):对象(Object)、数组(Array)、函数(Function),还有两个特殊的对象:正则(RegExp)和日期(Date)。
注意:JavaScript 对大小写敏感,所以不管是操纵DOM元素还是JS变量命名都需要注意大小写。可以用typeof 操作符来获取变量的类型。JavaScript 拥有动态类型。即相同的一个变量名可以在程序中有不同的类型(取决于对变量的赋值),如下例:
1 | var x; // x 为 undefined |
Boolean 用法与C++一样,这里给一下数组的用法:
1 | var cars=new Array(); |
或者:
1 | var cars=new Array("Saab","Volvo","BMW"); |
或者:
1 | var cars=["Saab","Volvo","BMW"]; |
这里不需要指定数组的长度和大小,直接赋值即可。JS变量声明如果没有赋初值,则默认为Undefined类型,也可以声明时指定类型:
1 | var carname=new String; /* 指定为string */ |
JS对象
JS对象由花括号分隔。在括号内部,对象的属性以名称和值对的形式 (name : value) 来定义。键值对在 JavaScript 对象通常称为对象属性,属性之间由逗号分隔。对象的方法定义了一个函数,并作为对象的属性存储,对象方法通过添加 () 调用 (作为一个函数)。对象方法的语法格式如下:
1 | methodName : function() { |
下面是一个对象的示例:
1 | var person = { |
对象的寻址方式:
1 | name=person.lastname; |
简单说,JavaScript对象是属性和方法的容器,是一个键值对集合,类似于Pytho中的字典。对象是可变的,它们是通过引用来传递的。以下实例的person对象不会创建副本:
1 | var person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"} |
字面量
一个字面量是一个常量,eg: 3.14、”helloworld”
- 数字字面量:可以是整数或者是小数,或者是科学计数(e)。eg:3.14、2002、1023e5
- 字符串字面量:可以是单引号,也可以是双引号。eg:”Tom”、’Jack’
- 数组字面量:[100,200,300]
- 表达式字面量:5*6 4/2+3
- 对象字面量:{firstName:”John”, lastName:”Doe”, age:50, eyeColor:”blue”}
- 函数字面量:function myFunction(a, b) { return a * b;}
操作符和运算符同C++,语句也是以 ; 结尾。JavaScript 标识符必须以字母、下划线(_)或美元符($)开始。这一点也与C++类似,只不过多了一个可以以$开始的特性。
函数
函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块。语法定义:
1 | function FunctionName(var1, var2,……) { |
同时,函数也可以作为变量进行赋值,函数存储在变量中,不需要函数名称,通过变量名来调用。当然,JS函数也支持递归,支持缺省参数。
1 | var x = function(a,b){return a* b}; |
ES6新增了箭头函数。用法如下:
1 | // ES5 |
关于函数参数,还有一种特殊用法,主要用于支持可变参数,用arguments[i]来表示传入函数的参数数组,如下例:
1 | var findmax=function(){ |
而函数体对于传入参数的改变,如果是普通的值,则函数体不会影响该值;如果是传入的对象,则函数会产生影响,具体说就像C++里的普通传值和引用传值。示例如下:
1 | function test(a,b){ |
在JS中, 函数也是对象。JS函数有它的属性和方法。call() 和 apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身。
1 | function myFunction(a,b){return a+b;} |
关键字(不全)
跟C++大差不差
语句 | 描述 |
---|---|
break | 用于跳出循环。 |
catch | 语句块,在 try 语句块执行出错时执行 catch 语句块。 |
continue 跳过循环中的一个迭代。 | |
do … while | 执行一个语句块,在条件语句为 true 时继续执行该语句块。 |
for | 在条件语句为 true 时,可以将代码块执行指定的次数。 |
for … in | 用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。 |
function | 定义一个函数 |
if … else | 用于基于不同的条件来执行不同的动作。 |
return | 退出函数 |
switch | 用于基于不同的条件来执行不同的动作。 |
throw | 抛出(生成)错误 。 |
try | 实现错误处理,与 catch 一同使用。 |
var | 声明一个变量。 |
while | 当条件语句为 true 时,执行语句块。 |
运算符
&、|、>>、&&、||、!、<、>之类的都与C++类似。但有两个不同的,还是因为Javascript变量的动态类型导致的。
- == 数值相等,变量类型可以不相同
- === 数值类型均相同
!== 和 !===与此类似。如下面的例子
1 | console.log(5=="5");// return true |
分支控制
if等用法与C++类似,注意switch进行匹配的时候是===的严格匹配。下面是for……in 的用法,跟Python有一点像:
1 | var person={fname:"John",lname:"Doe",age:25}; |
标签用法,直接看例子:
1 | cars=["BMW","Volvo","Saab","Ford"]; |
break即可跳出标签所在的代码块,单独的break则用于跳出循环。
JSON(JavaScript Object Notation)
JSON 是用于存储和传输数据的格式,通常用于服务端向网页传递数据。比如发送端可以把一个JS对象转为JSON,之后传输给接收端,接收端再把JSON转为JS对象。JSON示例如下:
1 | var person={"employees":[ |
JSON就是键值对的集合,上面的键即为 employees,值又是一个数组,数组中包含三个JS对象。JSON数据的具体规则:
- 数据为键值对。
- 数据由逗号分隔。
- 大括号保存对象。
- 方括号保存数组。
一些特殊关键字
const
const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改,跟C++一样的。
1 | const test=2; |
但对于声明的常量对象,又可以对每个属性进行赋值,但不能整体重新赋值,例子:
1 | const car = {type:"Fiat", model:"500", color:"white"}; |
null
在 JavaScript 中 null 表示 “什么都没有”。null是一个只有一个值的特殊类型。表示一个空对象引用。
1 | var num1=1,num2=2; |
this
JavaScript this 关键字用法:
- 在方法中,this 表示该方法所属的对象。
- 如果单独使用,this 表示全局对象。
- 在函数中,this 表示全局对象。
- 在函数中,在严格模式下,this 是未定义的(undefined)。
- 在事件中,this 表示接收事件的元素。
let vs var
简单说,var关键字支持函数作用域和全局作用域,但没有块作用域这个概念在里边。比如下面的代码:
1 | let i=9; |
可以看到,在循环外仍然能够访问循环中的初值。var 关键字声明的变量要么是全局作用域的,要么是函数作用域的,这意味着变量要么在整个程序中可见,要么在整个函数体内可见,即使它们是在诸如 if 语句或 for 循环这样的块中声明的。而let则支持函数作用域、块作用域和全局作用域,比如下面的代码:
1 | for(let i=0;i<5;i++){} |
这种方式就跟C比较类似了,循环结束后无法再访问循环中的变量。
正则表达式
跟编译原理里的正则表达式差不多一个意思,使用单个字符串来描述、匹配一系列符合某个句法规则的字符串搜索模式,搜索模式可用于文本搜索和文本替换。基本思想即是用有限的字符串(一个)去表示无限的若干个字符串。例子:
1 | var patt = /runoob/i; |
在 JavaScript 中,正则表达式通常用于两个字符串方法
- search() 方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串,并返回子串的起始位置.
- replace() 方法用于在字符串中用一些字符串替换另一些字符串,或替换一个与正则表达式匹配的子串。
用法举例:
1 | var pattern = /nankai/i; |
JS异步编程
之前一直没太明白什么是同步I/O,什么是异步I/O。借此机会学习了一下。在同步I/O模型中,一个I/O请求发出后,发起请求的程序要等I/O操作完成才能继续执行后续代码。这意味着在I/O操作进行时,程序将被阻塞,无法执行其他任务。同步I/O的特点是编程简单,逻辑容易理解和实现,但它可能导致程序效率低下;而异步I/O模型允许程序在发起I/O请求后立即继续执行后续代码,不需要等待I/O操作完成。在I/O操作完成后,会通过某种机制(如回调函数、事件、Promise等)通知程序。这意味着程序可以在等待I/O操作完成的同时执行其他任务,从而提高了程序的效率和响应性。如果用过Socket编程就知道,一般情况下的Receive函数就是一种同步I/O,当然也可以设置成非阻塞的,Receive立即返回,但程序就需要不断地轮询Socket,检查是否有数据可读。之前写计网实验的时候,用这种方式近似实现了“定时器”的效果,即轮询while(true)
给定的定时时间。而异步I/O则是完成后再“通知”正在运行的程序。事件驱动机制:代码的执行由事件(如用户交互、I/O操作完成等)触发的,而不是顺序执行。在Web服务中,这种模型非常适合处理网络请求,因为服务器可以立即响应各种事件。
JavaScript的执行环境是单线程的,这意味着同一时刻只能执行一个任务。为了不阻塞这个单线程,I/O操作(如数据读写、网络请求)被设计成异步的。当这些操作被发起时,JavaScript代码可以继续执行,而I/O操作在后台进行。当异步I/O操作完成时,相应的回调函数被放入事件队列,等待JavaScript引擎执行。当所有当前的同步任务执行完毕后,再来检查异步任务是否完成,若完成则调用回调函数。如下面的例子:
1 | function print() { |
异步编程的例子:
1 | setTimeout(function () { |
JS类
类定义语法,基本思想和C++差不太多。注意JS中采用垃圾回收机制来自动管理内存,所以类中只有构造函数,没有析构函数。
1 | //class ClassName { |
类相关的关键字:
- extends:继承一个类;
- static:在类中定义一个静态方法;
- super:调用父类的构造方法
具体示例如下:
1 | class Animal { |
静态方法即为属于整个类而非某个具体对象的方法,通过className.staticMethod()的方式调用。