初识JavaScript
1994年,网景公司发布了世界上第一款比较成熟的网络浏览器,但是这个浏览器只是一个静态的网页,无法与用户进行互动。为解决这一问题,提出了两种方案:第一个是嵌入原有的语言,但是比较麻烦所以被否决了;第二个是开发出一种新的语言。网景公司聘请了一个程序员布兰登·艾克(Brendan Eich),让他来做这个任务。他用了很短的时间就将JavaScript设计出来了,并在1995年9月首次发布,命名为LiveScript,在12月改名为JavaScript。
JavaScript包含了ECMAscript(js的语法和基本对象),DOM(文档对象模型),BOM(浏览器对象模型)。
主要功能:
1. 嵌入动态文本于HTML页面
2. 对浏览器事件做出响应
3. 读写HTML元素
4. 在数据被提交到服务器之前验证数据
5. 检测访客的浏览器信息
6. 基于Node.js技术进行服务器端编程
JavaScript编写位置
1. 直接写在网页内部的script标签中
<script>
alert('Hello!');
</script>
2. 创建一个外部js文件,链接到网页中
<script src="文件名.js"></script>
注意:如若在外部编写JavaScript,网页中的script标签中不要再编写代码,想在其中写需另起一个script标签。
3. 编写到指定的属性中
<button onclick="alert('hello~')">点我一下</button>
<a href="javascript:alert('hello!');">超链接</a> //点击执行js代码
<a href="javascript:;">超链接</a> //点击后什么都不发生
基本语法
注释中内容会被解释器忽略
可以对代码进行解释说明
可注释掉不想执行的代码
1.多行注释: /* */ (快捷键:shift+alt+a)
2.单行注释: //
3.js严格区分大小写
4.js中多个空格和换行会被忽略
可用这个特点对代码进行格式化
5.js中每条语句用分号结尾,不过js中用自动添加分号机制,但是建议写,以免出错
字面量 变量 常量
字面量实际上是一个值,代表的是字面的意思,如1,2,3,true等等,可直接使用,但是字面量没有含义,在代码中他或许是会有意义的,可能值会发生改变,所以我们直接使用字面量并不方便。
由此,我们可以使用变量,他可以储存字面量,同时可以改变其储存的值。
变量的使用
声明变量:let 变量名 变量赋值:a = xx
可以声明和赋值同时进行:let 变量名 = xx
变量的内存结构
在内存中,变量和赋的值存在了不同的区域,变量中存储的是所赋值的地址,当我们重新定义一个变量,并存储与上一变量相同的值时,内存中不会再开辟一个空间给它,而是直接将原有的存该变量值的地址给这个变量。如图所示:
常量
声明用const,其值不能修改,重复赋值会报错。常量会“锁住”上图的值那一列。
标识符
所以的可以由我们自主命名的内容都可以看作是一个标识符,如变量名,函数名等。
标识符命名规范有:只能含有字母,数字,下划线,$,且不能用数组、字开头;不能是js中的关键字;通常使用驼峰法命名,首字母小写,之后每个单词开头大写;类名用大驼峰命名法,首字母大写,之后每个单词开头小写;常量的字母全部大写。
数据类型
数值(Number): 所有整数和浮点数都是数值类型,有范围,当数值超过范围时会显示不精确的值,Infinity表示无穷,NaN是一个特殊的数值,表非法的数值。
大整数(BigInt):用来表示很大的数值,以n结尾,其可以表示的数字范围无限大。
布尔值(boole):用来进行逻辑判断,只有true和false两个值
空值(null):表示空对象,用typeof检查返回object
未定义(Undefined):声明变量未赋值就是undefined
符号(Symbol):用来创建一个唯一的标识
字符串:要用单引号或双引号引起来
注:以上七种是原始值,其一旦创建就不能修改
转义字符:\ " ----> " \' ----> ' \\ ----> \ \t ----> 制表符 \n ----> 换行
模板字符串:使用反单引号` `来表示模板字符串(可以换行),可以嵌入变量
let a="hello"
a='你好'
a="今天天气\"真\\\\好" //今天天气"真\\好
a="哈哈\t哈哈哈"//哈哈 哈哈哈
a="hhh\nhhh"
/*hhh
hhh*/
a=`今天
天气
真好`
/* 今天
天气
真好*/
let name="tom"
let s=`你好.${name}`
console.log(s) //你好,tom
类型检查
用typeof 运算符,它可以检查不同的值的类型,以此返回不同结果。
类型转换----字符串
1.调用toString()方法,对于空值和未定义类型没用
let a=10
console.log(typeof a) //Number
a=a.toString(a)
console.log(typeof a) //String
2.调用String()方法,对于空值和未定义类型有用
let a=10
console.log(typeof a) //Number
a=String(a)
console.log(typeof a) //String
类型转换----数值
用Number()方法
let a="10"
console.log(typeof a) //String
a=Number(a)
console.log(typeof a) //Number
字符串转换成数值类型:如果字符串是一个合法的数字,则自动转为对应的数字;如果字符串不是一个合法的数字,则转换为NaN;如果字符串是空串或纯空格的字符串,则转换为0
布尔值:true转为1,false转为0
null转为0;undefined转为NaN
专门用来将字符串转换为数值的两个方法:
parseInt():将字符串转为整数;解析时,从左到右读取,直到读取到字符串中所有有效整数
parseFloat() :将字符串转为浮点数;解析时,从左到右读取,直到读取到字符串中所有有效小数
类型转换----布尔值
使用Boolean()函数,null和undefined 都转为false
let a=1
console.log(typeof a) //Number
a=Boolean(a)
console.log(typeof a) //boolean
a=0 //false
a=NaN //false
a=Infinity //true
运算符
算数运算符
+ 加法运算符
- 减法运算符
* 乘法运算符
/ 除法运算符
** 幂运算
% 取余
js是弱类型语言,进行运算时会自动进行类型转换来完成运算。如a = 4 - '3',会自动转换为a = 4 - 3,得出结果a = 1。
但当任意一个值与字符串做加法时,会将其他值类型转换为字符串,做一个拼串操作。如a = 9 + '2',结果是a = 92。我们可以用这一特点来进行类型转换。如a = hello + ' ',输出结果是字符串类型的hello。
赋值运算符
赋值运算符是 “=”,赋值运算符用来将一个值赋给另一个值,将右边的值赋给左边,也就是说一个变量在=左边时才是变量,在右边是值。
+= : a += n 等价于 a = a + n
-= : a -= n 等价于 a = a - n
*= : a *= n 等价于 a = a * n
/= : a /= n 等价于 a = a / n
%= : a %= n 等价于 a = a % n
**= : a **= n 等价于 a = a ** n
??=:空赋值,只有当变量的值为null或undefined时才会对变量进行赋值
一元运算符
一元的+ - :
+:正号,不改变数值的符号。可以用其进行类型转换,将其他类型转为数值类型
-:负号,对数值进行符号取反
自增和自减
++ 自增运算符,使用后使原来变量值加一
自增分为前自增(++a)和后自增(a++),他们都会使原来变量立刻加一,但返回值不同
前自增就是先赋值后加一,而后自增是先加一后赋值,所以前者返回原值,后者返回加一后的值。
let a = 2;
let b = a++;
console.log(b); //b是原来a的值,也就是2
let c = ++a;
console.log(c); //c是自增后的值,也就是3
-- 自减运算符,使用后使原来变量值减一
自减分为前自减(--a)和后自减(a--),他们都会使原来变量立刻减一,但返回值不同
前自减就是先赋值后减一,而后自减是先减一后赋值,所以前者返回原值,后者返回减一后的值。
let a = 2;
let b = a--;
console.log(b); //b是原来a的值,也就是2
let c = --a;
console.log(c); //c是自减后的值,也就是1
逻辑运算符
! 逻辑非,相当于对布尔值进行取反操作,若对其他类型取反,先将其转换为布尔值再取反。可用 !! 来把非布尔值转换为布尔类型。
&& 逻辑与,其左右两边都是true则返回true,否则返回false。当&&左边为false时,不看右边的值,直接返回false。对非布尔值进行与运算,会转换为布尔值再运算,但最终返回原值,也就是说,如果第一个值为false,则返回第一个值;如果第一个值是true,则返回第二个值。
|| 逻辑或,其左右有true时,返回true,否则返回false。第一个值为true则不看第二个值。对非布尔值进行或运算,会转换为布尔值再运算,但最终返回原值,也就是说,如果第一个值为true,则返回第一个值;如果第一个值是false,则返回第二个值。
关系运算符
它用来检查两个值之间的关系是否成立,成立返回true,不成立返回false。
> 用来检查左值是否大于右值
>= 用来检查左值是否大于或等于右值
< 用来检查左值是否小于右值
<= 用来检查左值是否小于或等于右值
注意:当对非数值进行关系运算时,它会先将其转换为数值再比较,当关系运算符的两端是两个字符串,它不会将字符串转换为数值,而是逐位的比较字符的Unicode编码。比较两个字符串类型的数字的时一定要进行类型转换!
相等运算符
==:
相等运算符,用来比较两个值是否相等。使用相等运算符比较两个不同类型的值时,它会将其转换为相同的类型(通常转换为数值)然后再比较,类型转换后值相同也会返回true
null和undefined进行相等比较时会返回true,NaN不和任何值相等,包括它自身
===:
全等运算符,用来比较两个值是否全等,它不会进行自动的类型转换,如果两个值的类型不同直接返回false,null和undefined进行全等比较时会返回false
!=:
不等,用来检查两个值是否不相等,会自动的进行类型转换
!== :
不全等,比较两个值是否不全等,不和自动的类型转换
条件运算符
条件表达式 ?表达式1 :表达式2
执行顺序:先对条件表达式进行求值判断,如果结果为true,则执行表达式1,反之执行表达式2
let a = 100
let b = 30
let max = a>b ? a : b
console.log(max) // 100
if-else语句
语法:
if(条件表达式){
语句...
}else{
语句...
}
执行流程:先执行条件表达式来求值判断,结果为true执行if后的内容,反之执行else中的语句
if-else if-else语句:
if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else if(条件表达式){
语句...
}else{
语句...
}
执行流程:先执行条件表达式来求值判断,如果条件表达式结果为true,则执行当前if后的语句,执行完毕语句结束,如果条件表达式结果为false,则继续向下判断,直到找到true为止,如果所有的条件表达式都是false,则执行else后的语句
一旦有执行的代码块,下面的条件都不会执行了,所以要注意条件编写顺序
switch语句
语法:
switch(表达式){
case 表达式:
语句...
break;
case 表达式:
语句...
break;
case 表达式:
语句...
break;
default:
语句...
}
执行顺序:依次将switch后的表达式与case后的表达式进行全等比较,结果为true,则返回当前case处开始执行代码,结果为false,则继续比较,直到结果为true
while循环、do-while循环和for循环
循环语句可以使指定代码反复执行
循环通常有三个条件:初始化表达式、条件表达式、更新表达式
循环可以嵌套
while语句
while(条件表达式){
语句...
}
当一个循环语句的表达式恒为true时,这个循环就是一个死循环,会一直执行
do-while语句
do{
语句...
}while(条件表达式)
与while语句的区别:do-while循环不管是否满足条件表达式都会执行一次,然后再判断;但while循环会先判断是否满足条件表达式,满足再执行。
实质区别:do-while循环至少执行一次
for语句
for(初始化表达式;条件表达式;更新表达式){
语句...
}
初始化表达式在循环整个周期中之执行一次,for循环中的三个表达式可以都省略
使用let在for语句中声明的变量是局部变量,只能在for循环中访问
break和continue
break
break用来终止switch和循环语句,break执行后,当前的switch或循环会立刻停止break会终止离他最近的循环
continue
continue用来跳过当次循环,执行下一循环
对象
对象是js中的一种复合数据类型,相当于一个容器,可以存储各种不同类型的数据,我们称为属性
创建对象:
let obj = Object( )
添加属性:
对象.属性名 = 属性值
读取属性:
对象.属性名
删除属性:
delete 对象.属性名
let obj = Object()
obj.name = "tom"
obj.age = 18
属性名要求:通常就是一个字符串,可以是任意值,没有什么特殊要求,但是如果太特殊,不能直接使用,需要使用[ ]来设置,如"2889##42@"这种比较复杂的就需要用中括号括起来。(不建议使用)
属性值可以是任意的数据类型,也可以是一个对象(如obj.f = Object( ))
可以使用 in 运算符来检查对象中是否有某种属性,语法 :属性名 in obj,有符号true,没有返回false。
对象字面量
直接使用{ }来创建对象,可直接向对象中添加属性
语法:let 对象名 = {属性名:属性值,...}
枚举属性
指将对象中的所有的属性全部获取
for-in语句- 语法:
for(let 变量名 in 对象){
语句...
}
for-in的循环体会执行多次,有几个属性就会执行几次,每次执行时,都会将一个属性名赋值给我们所定义的变量
注意:并不是所有的属性都可以枚举,比如使用符号添加的属性
for(let 变量名 in 对象){
console.log(变量名,对象[变量名])
}
函数
函数的定义方式:
1.函数声明
functin 函数名(参数){
语句...
}
2.函数表达式
const 变量 = function(参数 ){
语句...
}
3.箭头函数
(参数 ) => {
语句...
}
调用函数:就是执行函数中的代码块,语法:函数名( )
定义函数时,在函数名后面括号中定义的参数是形参,调用时,可在括号中传值,这个值叫做实参
如果实参多于形参,则多余的实参不会使用;如果形参多于实参,则多余的形参为undefined
函数的返回值
通过return来指定函数返回值,返回值就是函数的执行结果,函数调用完毕返回值会作为结果返回
任何值都可以作为返回值!如果return后没有返回值,相当于返回undefined
箭头函数的返回值:直接写在箭头后面
const sum = (a,b) => a+b
如果返回值是对象字面量,需用()括起来
const fn = () => ({name:"孙悟空"})
this
函数在执行时,js解析器每次都会传递进一个隐含的参数,这个参数叫做 this。this会指向一个对象,其指定的对象会根据函数调用方式的不同而不同。
以函数形式调用时,this指向的是window。以方法形式调用时,this指向的是调用方法的对象。
通过this可以在方法中引用调用方法对象
const obj = {
name:"张三"
sayHello(){
console.log(this.name) // 张三
}
上述例子中,如果name属性要发生改变,可直接改name后的值,打印出的内容会随之改变。
箭头函数的this:
箭头函数:
([参数]) => 返回值
例子:
无参箭头函数 ( )=>返回值
一个参数的 a => 返回值
多个参数的 (a,b)=> 返回值
只有一个语句的函数 () => 返回值
只返回一个对象的函数 ( )=> ({...})
有多行语句的函数 () => {
...
return 返回值
}
箭头函数没有自己的this,他的this由外层作用域决定,他的this和他的调用方式无关
function fn(){
console.log("fn-->" , this);
}
const fn2 = ()=>{
console.log("fn2-->" , this);
}
fn() //window
fn2() //window
用箭头函数:
const obj = {
name:"Tom",
fn,
fn2,
sayHello(){
console.log(this.name) //Tom
const t2 =() => {
console.log(this) //obj
}
t2()
}
}
用普通函数:
const obj = {
name:"Tom",
fn,
fn2,
sayHello(){
console.log(this.name) //Tom
function t(){
console.log(this) //window
}
t()
}
}