js基本了解
js是运行在浏览器的编程语言,是前端唯一的一门语言
主要功能
监听用户的行为,并让网页作出对应的反馈
网页特效(动画效果)
表单验证 (针对表单数据的合法性进行判断)
数据交互 (获取后台的数据, 渲染到前端)
服务端编程 (node.js)
js包括 ECMAScript和 web APIS 其中web APIS 包括DOM和 BOM
ECMAScript规定了js的语法的基础规范
DOM和BOM 则是对文档和浏览器进行操作
JS权威网站 MDN
JavaScript权威网站: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
JS的书写方式
js是从上到下运行的,书写方式没有先后之分
行内式
<p style="color:red" onclick='alert("333")'>我是p元素</p>
内部js --写在body结束标签前面
<script>
alert('123')
</script>
外部js --外部js中间不应该写其它代码,中间的代码不会解析
<script src="./js/test.js">
alert('123') // 不显示
</script>
js注释
单行注释 // 快捷键ctrl + /
// 这是单行注释,一般用于注释当前这一行代码的意义
// 再来一行注释
多行注释
/*
这是块注释,也叫多行注释
这里面可以写多行注释
再来一行也可以
再来一行也OK
*/
js输入和输出 -- 无论是输入还是输出非变量的值要加引号
输入 prompt() -- 会阻塞主线进程
会提示用户输入内容,并且可以返回用户输入的内容,我们可以定义一个变量用于接收返回的内容
返回的内容是字符串类型
let name = prompt('请输入你的姓名')
document.write(name)
输出
alert() --警告弹框,它只能传入一个想弹出显示的内容 会阻塞主线进程
会阻止浏览器的执行,只能输出一个值(弊端)
alert('123') // 123
alert('aa','bb') // aa // bb 不会显示
document.write() --它会将内容输出到body标签中
能够写入多个值,以逗号分开
可以解析网页结构(html标签)
document.write('123',456) // 123 456
console.log() -- 将内容打印到控制台 ,可以打印多个内容
console.log('123',456,'你好') // 123 456 你好
变量
变量不是数据本身,它们仅仅是一个用于存储数值的容器
声明变量的关键词:var(过时) let const (常量,不可修改,必须在初始化的时候就赋值)
声明变量
let num = 123
const name = '张三'
var age = 18 // 等于号左边为声明,右边为赋值
声明多个变量
let
name = '张三',
age = 18,
num = 123;
console.log(name,age,num) // 输出变量的时候不需要加引号
变量的修改
let name = '张三'
name = '法外狂徒'
let name = '李四' //错误的 不允许多次声明一个变量
交换变量的值
<script>
let num1 = 10,
num2 = 20
console.log(num1, num2) // 10 20
// 定义一个中间变量
let temp
// 1.先将其中一个变量 num1 的值赋值中间变量 说明num1已经存储在另外一个位置,num1就可以被覆盖
temp = num1
// 2.将另外一个变量 num2 的值赋值给num1
num1 = num2
// 3.将中间变量的值赋值给num2
num2 = temp
console.log(num1, num2) // 20 10
</script>
字面量 --所见即所得的一个常量
变量的本质
内存:计算机中存储数据的地方,相当于一个大空间
变量:是程序在内存中申请的一块用来存放数据的小空间【内存中的一个地址空间】
变量的命名规则与规范
规则 -- 必须遵守,否则会报错
1.不能用关键字和有特殊含义的字符,例: let if const for ...
2.变量名只能用下划线 _ 字母 数组 和 $符号组成,且数字不能开头
3.字母严格区分大小写,如Age 和 age 不是一个变量
规范 -- 建议 不遵守不会报错,但是行业内常识
1.起名要有意义,最好是英语单词
2.遵守驼峰命名法 第一个单词首字母小写,第二个单词首字母大写 例 : userName
数据类型
基础数据类型
<script>
let age = 10 // 数值
let name = 'jack' // 带引号的就是字符串
let isBoy = true // boolean: true / false
let address // 一个变量如果没有赋值,那么默认值就是undefined
let hobby = null // 主动赋值才可能为null
console.log(age, name, isBoy,address,hobby)
</script>
number 数字类型
JavaScript 中的正数、负数、小数等 统一称为 数字类型
string 字符串类型
带引号的都是字符串
字符串拼接 ${数据}
反引号
模板字符串
let name = prompt('请输入你的姓名')
let age = prompt('请输入你的年龄')
let gender = prompt('请输入你的性别')
console.log(name,age,gender);
// 变量如果包含在引号之内,它就是一个普通的字符串
// + :如果+的两边有一边是字符串,那么+就是字符串连接符,它可以将多个字符串连接为一个字符串
console.log('我的姓名是' + name + ',我的年龄是' + age + ',我的性别是' + gender);
// 模板字符串
console.log(`我的姓名是${name},我的年龄是${age},我的性别是${gender}`);
Boolean 布尔值类型 true / false 两种
undefined 未定义类型
null 空类型 -- 尚未创建的对象
null 和 undefined 区别:
undefined 表示没有赋值
null 表示赋值了,但是内容为空
数据类型检测 typeof -- 简单数据
无法检测引用数据类型,检测引用数据类型会直接给出object,万物皆为对象
let name = 'jack'
let age = 20
let gender = true
let address
let computer = null
// typeof:检测当前数据的类型
console.log(typeof name) // string
console.log(typeof age) // number
console.log(typeof gender) // boolean
console.log(typeof address) // undefined
console.log(typeof computer) // object // 空对象
引用数据类型
Array
Object
function
传值
简单数据类型 :按值传递,相同的两个值中其中一个值改变不会影响另外一个值
引用数据类型: 按地址(引用) 传递,两个相同的值其中一个改变另外一个跟着改变
// 简单数据类型 也叫基础数据类型 值数据类型
let num1 = 10
let num2 = num1
num1 = 20
console.log(num2) // 10
//复杂数据类型,也叫引用数据类型
let obj1 = {
age = 18
}
let obj2 = obj1 // 两个是一个地址空间
obj1.age = 20
console.log(obj2)
//{age : 20}
如果要想使相同引用数据类型其中一个改变另外一个不变,可以使用剩余运算符 ...
数据类型转换
隐式转换
规则
+号两边只要有一个是字符串,都会把另外一个转成字符串
除了+以外的算术运算符 比如 - * / 等都会把数据转成数字类型
(+号作为正号解析可以转换成Number)
显式转换
转换成数字类型
Number(数据)
转成数字类型
如果字符串内容里有非数字,转换失败时结果为 NaN(Not a Number)即不是一个数字
NaN也是number类型的数据,代表非数字
parseInt(数据) -- 只保留整数
parseInt:会转换数据,直到碰到非数值为止,如果第一个就是非数值,那么就是NaN
parseFloat(数据) -- 浮点型,可以保留小数
parseFloat基本特性和parseInt一样,但是它会保留小数
转换为字符串类型
String(数据)
变量.to String()
运算符
算术运算符
+:求和
-:求差
*:求积
/:求商
%:取模(取余数)
优先级:有括号先算括号里面的,先乘除和取余,再加减 从左到右计算
赋值运算符
已经学过的赋值运算符:= 将等号右边的值赋予给左边, 要求左边必须是一个变量
其他赋值运算符:
+=
*=
/=
%=
age = age + 5 // age += 5
一元运算符
自增或自减
++num // 前置自增
num++ // 后置自增
--num // 前置自减
num-- // 后置自减
// 每次加一或减一
前置自增或自减,先自增或自减,然后再返回值参与计算
后置自增或自减,先返回值参与计算,然后再自增或自减
不参与计算,单独使用没有任何区别
<script>
let num = 10
num += 5 // num = num + 5 //15
let res = num++ // 15 + 1 = 16 后置自增先返回值,再自增 因此返回的值是15,然后自增为16
console.log(res) // 15
console.log(num); // 16
let x = 10, y = 20
let z = x > y ? ++x : y++ // 判断x > y 为false 则返回y++ 先返回值,再自增
console.log(x) // 10 不满足条件 x未改变
console.log(y) // 21 y++自增为21
console.log(z) // 20 y先返回值为20
let sum = 20
let set = sum > 0 || sum++ // 返回布尔值为true 当判断sum > 0时,逻辑或短路,后面不执行
console.log(set) // true
console.log(sum) //20 sum++不执行,sum为原值20
</script>
比较运算符
>: 左边是否大于右边
<: 左边是否小于右边
>=: 左边是否大于或等于右边
<=: 左边是否小于或等于右边
==: 左右两边是否相等,将两边的数据进行转换为数值,只看值不比较数据类型
===: 左右两边是否类型和值都相等
!==: 左右两边是否不全等
比较结果为boolean类型,即只会得到true或false
字符串比较,是比较的字符对应的ASCII码
从左往右依次比较
如果第一位一样再比较第二位,以此类推
比较的少,了解即可
NaN不等于任何值,包括它本身
尽量不要比较小数,因为小数有精度问题
不同类型之间比较会发生隐式转换
最终把数据隐式转换转成number类型再比较
所以开发中,如果进行准确的比较我们更喜欢 === 或者 !==
逻辑运算符
符号 | 名称 | 日常读法 | 特点 | 口诀 |
---|---|---|---|---|
&& | 逻辑与 | 并且 | 符号两边都为true结果才为true | 一假则假 |
|| | 逻辑或 | 或者 | 符号两边有一个true就为true | 一真则真 |
! | 逻辑非 | 取反 | true变false false变true | 真变假,假变真 |
逻辑运算符里的短路
符号 | 短路条件 |
---|---|
&& | 左边为false就短路 直接为false |
|| | 左边为true就短路 直接为true |
运算符优先级
从高到低
1.小括号
2.++ -- !
3.算术运算符 先乘除取余 后加减
4.比较运算符 > >= < <=
5.相等运算符 == != === !==
6.逻辑运算符 先&& 后 || 逻辑运算符中非的优先级最高,逻辑与比逻辑或的优先级高
7.赋值运算符 =
8.逗号
表达式和语句
表达式
表达式通常会在原地返回一个值,代码较短
num++
3+4
x=7 // 这些都是表达式
语句
js 整句或命令,用来描述一件事情,代码量比较长
程序三大流程控制语句
顺序结构
我们写的代码,写几句就从上往下执行几句,这种叫顺序结构
分支结构
有的时候要根据条件选择执行代码,这种就叫分支结构
常用的分支语句有
if分支语句
单分支
if(判断条件){当判断条件为true时执行的代码}
如果小括号内的数据不是布尔类型时会发生隐式转换为布尔类型true或者false
// 请输入你的分数,如果大于等于 60,则提示你 及格了
let num = +prompt('请输入分数')
// 添加判断结构
// 如果处理代码只有一句,那么也可以省略{},意味着如果没有添加{},那么if结构只会影响后面一句
if (num >= 60) {
alert('及格了')
console.log(123)
}
双分支
if(条件){
满足条件要执行的代码
} else {
不满足条件要执行的代码
}
let year = +prompt('请输入年份')
if ((year % 4 === 0 && year % 100 !== 0) || year % 400 === 0) {
alert('闰年')
} else {
alert('平年')
}
多分支
// 接收用户输入的时间: 0~24
let hour = +prompt('请输入小时值')
// 判断你输入的值是否满足需要,如果满足需要,就执行代码块逻辑
if (hour >= 0 && hour <= 24) {
// 凌晨好
if (hour >= 0 && hour < 6) {
alert('凌晨好')
}
// 上午好
else if (hour >= 6 && hour < 12) {
alert('上午好')
}
// 下午好
else if (hour >= 12 && hour < 18) {
alert('下午好')
}
// 晚上好
else {
alert('晚上好')
}
}
// 否则给出提示
else {
alert('不要乱搞')
}
三元运算符 (三元表达式)
条件 ? 满足执行的代码 : 不满足执行的代码
一般用来取值
数字补0 // 字符串拼接
let num = +prompt('请输入一个数字')
num = num < 10 ? '0' + num : num // 当输入的数字小于10就会自动在前面加一个0,大于10则返回输入值
console.log(num)
switch
语法规范:
switch(n) {
case 1:
执行代码块 1
break;
case 2:
执行代码块 2
break;
default:
与 case 1 和 case 2 不同时执行的代码
break;
}
使用场景:当case特别多的时候,使用会看上去比if更加简洁
let num = 6
switch (num)
{
case 0:
consol.log(1);
break;
case 1:
consol.log(2);
break;
case 2:
consol.log(3);
break;
case 3:
consol.log(4);
break;
case 4:
consol.log(5);
break;
case 5:
consol.log(6);
break;
case 6:
consol.log(7);
break;
} // 7
判断的优化:
=== true 可以省略不写
=== false 可以省略之后在前面加取反!即可
循环结构
某段代码被重复执行,就叫循环结构
循环结构必备三个条件 :初始化,循环条件,变化值
while循环
当没有具体次数时推荐使用
条件为布尔值,和if一样
while (条件) {
满足条件要重复执行的代码
}
执行完毕之后会继续进行条件判断,满足会再次执行,直到不满足条件为止
let sum=1
while(sum<=100){
console.log(sum)
sum++
}
do while 循环
do-while循环特点:先执行再判断,即使初始条件不成立,do-while循环至少执行一次;
let num = 10;
do{
document.write(num+"<br />");//10 9 8 7 6 5 4 3 2 1 0
num--;
}while(num>=0);
document.write(num);//-1
for循环
当有具体次数时推荐使用
for(初始值,循环条件,变化值){
循环体
}
for (let i = 1 ; i <= 10; i++) {
console.log(`在控制台打印第${i}个数`)
}
for循环和while循环有什么区别呢:
当如果明确了循环的次数的时候推荐使用for循环
当不明确循环的次数的时候推荐使用while循环
循环结束
continue:结束本次循环,继续下次循环
break:跳出所在的循环
循环嵌套
// 九九乘法表
<script>
// 行数
for (let i = 1; i <= 9; i++) {
// 每一行有几个表达式
for (let j = 1; j <= i; j++) {
document.write(`${j} * ${i} = ${j * i}`)
)
}
document.write('<br>')
}
</script>
数组 --Array
声明语法
let arr = ['张三',13,···]
//可以存储任意类型的数据
数组是按顺序保存,所以每个数据都有自己的编号
在数组中,数据的编号也叫索引或下标
取值语法
数组名[下标]
let arr = [123,456,'张三']
arr[0] // 123
arr[1] // 456
arr[2] // 张三
console.log(arr.length) // 3
元素:数组中保存的每个数据都叫数组元素
下标:数组中数据的编号,数组下标从0开始
长度:数组中数据的个数,通过数组的length属性获得
遍历数组
用循环把数组中每个元素都访问到,一般会用for循环遍历
let arr =['王星', '麦秋', '雷柯', '李乐', true, 20]
for(let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
数组求和
let arr = [10,20,30,40,50]
let num = 0
for (let i = 0; i < arr.length; i++) {
num += arr[i]
}
console.log(num) // 150
操作数组
增删改查
查:数组名.[下标]
修改: 数组名.[下标] = 新的值
在为数组的某个位置的元素重新赋值时
1.如果有这个索引,那么就是修改
2.如果没有这个索引,就是添加,同时会影响数组的长度
添加
数组名.push(添加的元素) 在数组的最后追加一个元素,并返回该数组的新长度
数组名.unshift(添加的元素) 在数组的最前面插入元素,并返回该数组的新长度
删除
数组名.pop() 删除数组的最后一个元素,并且返回当前删除的数据
数组名.shift() 删除数组的第一个元素,并且返回当前删除的数据
数组名.splice(起始索引位置 , 想删除的元素的数量(可选,不写代表从起始位置之后全部删完))
如果splice中超出两个元素,则是将从第三个元素起添加到起始索引之后
数组筛选
let arr = [11,25,34,64,78,95,21,1,0,56,7,6]
// 筛选出大于50的数
let arr2 = [] // 声明一个空数组存放筛选出来的数据
// 遍历数组
for (let i = 0 ; i < arr.length; i++) {
// 判断每一个元素是否大于50
if(arr[i] > 50) {
//当大于50时添加到空数组
arr2.push(arr[i])
}
}
console.log(arr2) // [64,78,95,56]
函数
function,是被设计为执行特定任务的代码块
函数的语法规范
function 函数名称() {函数体}
function getArr() {
console.log('111') // 函数封装 以便复用
}
getarr() // 调用函数getarr 输出 111
函数名称的命名规则和规范
规则:和变量命名规则一样:可以包含数字,字符,_ ,$,不能以数字开头
规范:小驼峰,一般以动词开头,代表这个函数的功能
函数调用: 函数名()
函数传参
声明语法
function getNum(num1,num2,num3){ // 形参
console.log(num1+num2-num3)
}
getNum(10,20,15) // 实参 15
形参:声明函数时写在函数名右边小括号里的叫形参(形式上的参数)
实参:调用函数时写在函数名右边小括号里的叫实参(实际上的参数)
形参可以理解为是在这个函数内声明的变量(let num;)实参可以理解为是给这个变量赋值(比如 num1 = 10)
开发中尽量保持形参和实参个数一致
我们曾经使用过的 alert('打印'), parseInt('11'), Number('11') 本质上都是函数调用的传参
如果形参没有被赋值,那么就是undefined
函数返回值
return
// 求任意数组中的最大值并返回这个最大值
// arr:类型是数组
function getMaxByArr(arr) {
let max = arr[0]
for (let i = 1; i < arr.length; i++) {
if (max < arr[i]) {
max = arr[i]
}
}
// 将最大值返回
return max
//如果之后还有代码则不会执行
}
let arr1 = getMaxByArr([1, 23, 243, 534, 5, 456, 57, 7])
console.log('数组中的最大值是' + arr1)
在函数体中使用 return 关键字能将内部的执行结果交给函数外部使用
函数内部只能运行到 1 次 return,并且 return 后面代码不会再被执行,所以 return 后面的数据不要换行
return会立即结束当前函数
函数可以没有 return,这种情况函数默认返回值为 undefined
返回多个值可以用数组
作用域
全局变量 全局变量在变量定义之后区域可以访问和修改 script中的变量
局部变量 局部变量只能在当前函数内部访问和修改 函数内部的变量
块级变量 let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问 {}中的变量
变量作用域特殊情况
如果函数内部或者块级作用域内部,变量没有声明,直接赋值,也当全局变量看,但是强烈不推荐
函数内部的形参可以看做是局部变量,所以形参相当于函数内部定义的局部变量,只有在函数内部可以使用
作用域链:采取就近原则的方式来查找变量最终的值
匿名函数
function () {}
将匿名函数赋值给一个变量,然后再调用
let fn = function (){
console.log('123')
}
//调用
fn() // 123
立即执行函数--防止变量污染
(function(){console.log('123')})() //123
多个立即执行函数要用 ; 隔开,要不然会报错
对象
对象(object):JavaScript里的一种数据类型
可以理解为是一种无序的数据集合
可以详细的描述某个事物
对象声明语法
//let 对象名 = {}
let obj = {}
对象有属性和方法组成
属性 --键值对
属性都是成 对出现的,包括属性名和值,它们之间使用英文 : 分隔
多个属性之间使用英文 , 分隔
属性就是依附在对象上的变量(外面是变量,对象内是属性)
属性重名的时候,后面定义的会将前面定义的覆盖
方法 -- 对象中的函数
方法是由方法名和函数两部分构成,它们之间使用 : 分隔
多个属性之间使用英文 , 分隔
方法是依附在对象中的函数
let stu = {
// 键和值使用:分隔
// 每组键值对使用,分隔
name: 'jack',
age: 20,
gender: '男',
height: 180,
// 下面是行为
code: function() {
console.log('我会写代码')
},
debug: function() {
console.log('我会调bug')
}
}
console.log(stu)
属性的获取有两种
1.点形式 对象.属性
2.[] 形式 对象[‘属性’]
点后面的属性名一定不要加引号
[] 里面的属性名加引号,除非它是一个变量
方法的获取
对象.方法() // 要加括号,和调用函数一样
let stu = {
// 键和值使用:分隔
// 每组键值对使用,分隔
name: 'jack',
age: 20,
gender: '男',
height: 180,
// 下面是行为
code: function() {
console.log('我会写代码')
},
debug: function() {
console.log('我会调bug')
}
}
//调用属性
console.log(stu.name) // jack
console.log(stu['age']) // 20
console.log(stu[age]) // 报错如果没有添加引号,会当成变量进行处理
// 调用方法
stu.code()
stu.debug()
// 访问一个对象不存在的属性,返回undefined
// console.log(stu.abc); // undefined
操作对象
增删改查
查找 -- 上面属性方法的调用
修改 所谓修改就是重新赋值:如果属性已经存在,就是修改,如果没有存在就是添加
对象.属性 = 值
对象.方法 = function() {}
添加
对象名.新属性名 = 新值
无论是属性或是方法,同一个对象中出现名称一样的,后面的会覆盖前面的
删除
delete 对象.你想删除的属性名称
let stu = {
// 键和值使用:分隔
// 每组键值对使用,分隔
name: 'jack',
age: 20,
gender: '男',
height: 180,
// 下面是行为
code: function() {
console.log('我会写代码')
},
debug: function() {
console.log('我会调bug')
}
}
//查找
stu.name
stu['age']
stu.code() // 调用方法
//修改
stu.name = '张三'
stu.code = function(){console.log('这是修改的')}
//添加
stu.num = 123 // 有相同的属性就是修改,没有就是添加
// 删除
delete stu.height
console.log(stu) //输出
遍历对象
for in
对象没有像数组一样的length属性,所以无法确定长度
对象里面是无序的键值对, 没有规律. 不像数组里面有规律的下标
for (let key in obj){console.log(key)} 可以用在数组身上,数组是个特殊的对象,但不推荐,输出的是字符串
let stu = {
// 键和值使用:分隔
// 每组键值对使用,分隔
name: 'jack',
age: 20,
gender: '男',
height: 180,
// 下面是行为
code: function() {
console.log('我会写代码')
}
}
// 语法:for(let key in 你想遍历的对象){通过key可以获取对象的属性值}
for (let key in stu) {
console.log(key, stu[key])
}
// key是属性
//stu[key]是属性值
内置对象
Math
random:生成0-1之间的随机数(包含0不包括1)
let num = Math.random()
console.log(num) // 生成0-1之间的随机数
ceil:向上取整
let num = Math.random() * 10
console.log(num) // 0-10之间随机数
num = Math.ceil(num)
console.log(num) // 1-10 向上取整,有小数就+1
floor:向下取整
let num = Math.random() * 10
console.log(num)
num = Math.floor(num)
console.log(num) // 0-9 向下取整,小数省略
// 0-10的随机整数(包含10)
let num = Math.random() * (10 + 1) // 随机0-11之间
console.log(Math.floor(num))// 向下取整 0-10的整数
// 5-10的随机整数(包含10)
Math.floor(Math.random() * (5 + 1)) + 5
// 生成N - M之间的随机整数(包括M)
Math.floor(Math.random() * (M - N + 1)) + N
max:找最大数
min:找最小数
pow:幂运算
abs:绝对值
随机数字函数
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}