JavaScript介绍
什么是JavaScript
- JavaScript是世界上最流行的语言之一,是一种运行在客户端的脚本语言( Script 是脚本的意思)
- 脚本语言∶不需要编译,运行过程中由js解释器(js 引擎)逐行来进行解释并执行
- 现在也可以基于Node.js技术进行服务器端编程
JavaScript的作用
- 表单动态校验(密码强度检测)(JS产生最初的目的)
- 网页特效
- 服务端开发(Node.js)桌面程序(Electron)App(Cordova)
- 控制硬件-物联网(Ruff)游戏开发(cocos2d-js)
关系
- html/css是标记语言
- js是脚本语言,实现业务逻辑和页面控制
浏览器执行js
- 渲染引擎:用来解析html和css,叫做浏览器内核
- js引擎:用来执行网页中的js代码,对其进行处理
js的组成
- JavaScript语法(ECMAScript):规定js语法,变量、分支语句、循环语句、对象等js基础语法
- Web APIs:
- DOM-文档对象模型:操作文档,比如对页面元素进行移动、大小、添加删除等操作
- BOM-浏览器对象模型:操作浏览器,比如页面弹窗,检测窗口宽度、存储数据到浏览器等等
JS布局方式
- 行内式
- 内嵌式
- 引入式
注释
- 单行注释: //
- 多行注释:/* */
输入输出语句
方法 | 作用 |
---|---|
prompt(); | 弹出输入框,用户输入 |
alert(); | 浏览器弹出提示框 |
console.log(); | 浏览器控制台打印输出信息 |
document.write(); | 往(页面)文档里面输出内容 |
- alert() 和 prompt()会跳过页面渲染先被执行
- 字面量:描述计算机中的事物
变量
-
变量是用来存储数据的容器,本质是在内存中申请一个区域来存放数据,通过变量名访问
-
申明变量:let 变量名,不允许多次申明
-
变量值会被覆盖
//申明变量 赋值(变量地初始化) let age = 18 console.log(age) //变量更新 age = 19 console.log(age)
-
命名规范
-
不能用关键字
关键字∶有特殊含义的字符,JavaScript内置的一些英语词汇。例如: let、var、if、for等只能用下划线、字母、数字、$组成, -
数字不能开头
-
字母严格区分大小写,如let Age和let age是不同的变量:
-
由数字字母下户线美元符号组成,且不能以数字开头
-
严格区分大小写
-
驼峰命名
-
尽量不使用name
-
-
let和var(ES6中已被淘汰)比较var的缺陷
-
var缺点:
- 可以先使用再声明
- var声明的变量可以重复使用
- 还有变量提升、全局变量、没有块级作用域等等
//先使用再声明 console.log(num) var num //var声明的变量可以重复使用 var num = 10 var num = 20
-
常量
- 使用const关键字声明
- 常量不允许重新赋值,且声明的时候必须初始化(赋值)
const PI = 3.14
console.log(PI);
// PI = 35 报错: Assignment to constant variable. 不允许再赋值
// const P 报错:Missing initializer in const declaration 没有初始化
数据类型
- js是弱类型动态语言,只有赋值之后才会知道变量的类型,变量的数据类型会根据值的变化而变化。
基本数据类型
类型 | 说明 | 默认值 |
---|---|---|
Number | 数字,包括整型和浮点型和NaN(非数字) | 0 |
Boolean | 布尔值 | false |
String | 字符串 | “” |
Undefined | 申明变量但没有赋值 | undefined |
Null | 空 | null |
数值型(Number)
- 一切数字都是数值型,如1,2,1.1等
- 数值之间的运算符
//数值型
let num1 = 2
let num2 = 1.1
let num3 = 4
//运算符
console.log(num1 + num2);
console.log(num1 - num2);
console.log(num1 * num3);
console.log(num3 / num1);
console.log(num3 % num1);
-
特殊类型:NaN代表一个计算错误,比如:
console.log('wjw' - 2)
代表着计算结果不是数字,not a number
-
NaN是粘性的,任何对NaN的操作返回只都是NaN
-
isNaN();方法判断变量是不是数字,不是的话返回true,是的话false
-
字符串(String)
-
通过**单引号(“)、双引号(”")或反引号(``)包裹的数据都叫字符串,**单引号和双引号没有本质上的区别,推荐使单引号。
-
注意事项:
- 1.无论单引号或是双引号必须成对使用
- ⒉.单引号/双引号可以互相嵌套,但是不以自已嵌套自已(口诀:外双内单,或者外单内双)
- 3.必要时可以使用转义符\,输出单引号或双引号
-
字符串转义符:
- 字符串长度:length属性
console.log(str.length)//显示字符串的长度
-
字符串拼接:+
-
模板字符串
- 反引号(``) 包裹${变量},实现字符串拼接变量
//字符串
let str1 = "123456789"
let str2 = '温家旺'
let str3 = `wjw`
let str4 = '' //空字符串
console.log(str1,str2,str3)
//引号嵌套
console.log('温家旺是"sb"')
//字符串拼接 +
let age = 18
console.log('我今年' + age + '岁了')
//模板字符串
console.log(`我今年${age}岁了`)
布尔型(Boolean)
- 表达判断时,用布尔类型,只有两个值true or false
未定义类型(undefined)
- 只声明变量,不赋值的情况下,变量的默认值为undefined
空类型(null)
- 是一个代表“无”、“空”或“值未知”的特殊值,官方定义null是一个尚未创建的对象(object)
- null 和undefined区别:
- undefined 表示没有赋值
- null表示赋值了,但是内容为空
//布尔型
let flag = true
let isFlag = false
let f = 7>4 //表达式 值为true
console.log(flag)
//未定义类型
let a;
console.log(a)
//null类型
let obj = null
//未定义类型 和 null类型 区别
console.log(a + 1); // NaN
console.log(obj + 1); // 1
typeof监测数据类型
- typeof运算符可以返回被检测的数据类型。它支持两种语法形式:
- 作为运算符:typeof x(常用的写法)
- 函数形式: typeof(x)
//检测数据类型
let num = 10
let str = 'wjw'
let boolean = true
let a
let obj = null
console.log(typeof num,typeof str,typeof boolean,typeof a,typeof obj)
类型转换
- 使用表单、prompt获取过来的数据默认是字符串类型的,此时就不能直接简单的进行加法运算。
隐式转换
-
+号两边只要有一个是字符串,都会把另外一个转成字符串
-
除了+以外的算术运算符比如– * /等都会把数据转成数字类型
-
+号作为正号解析可以转换成数字型
-
任何数据和字符串相加结果都是字符串
let num = prompt('请输入一个数')
let num1 = prompt('请输入一个数')
//隐式转换
console.log(num + num1) // '11'
console.log('2' + 100); //'2100'
console.log(2 + '300'); // '2300'
console.log('w' - 1); // NaN
console.log('7' - 2); // 5
console.log('2' * 2); // 4
console.log('2' / 2); // 1
let num2 = +prompt('请输入一个数')
console.log(num2); //number
console.log(+'100'); // 100
显式转换
1.转换为字符串
方法 | 说明 |
---|---|
toString() | 转成字符串 |
String()强制转换 | 强转成为字符串 |
+号拼接成为字符串 | 和字符串拼接成为字符串(隐式转换) |
2.转换为数字
方法 | 说明 |
---|---|
parselnt()函数 | 转为整型,只识别数字开头部分,不是数字会被自动忽略 |
parseFloat()函数 | 转为浮点型,只识别数字开头部分, |
Number()强转函数 | 强转为数字类型 |
js隐式转换 | 算术运算 ‘+’ 隐式转换为数值 |
3.转换为布尔型
方法 | 说明 |
---|---|
Boolean()函数 | 其他类型转换为布尔型,代表空否定的值会被转换为false(0,‘’,NaN,null,undefined),其他为true |
案例:打印用户信息表
<head>
<meta charset="utf-8">
<title>用户订单</title>
<style>
h2{
text-align: center;
}
table{
height: 80px;
border-collapse: collapse;
text-align: center;
margin: 0 auto;
}
th{
padding: 10px 30px;
}
table,
th,
td{
border: 1px solid black;
}
</style>
</head>
<body>
<!-- js -->
<script>
let price = +prompt("请输入价格")
let num = +prompt("请输入数量")
let address = prompt("请输入地址")
let total = price * num
document.write(`
<h2>用户订单</h2>
<table>
<tr>
<th>商品名称</th>
<th>商品价格</th>
<th>商品数量</th>
<th>总价</th>
<th>收货地址</th>
</tr>
<tr>
<td>小米手机</td>
<td>${price}</td>
<td>${num}</td>
<td>${total}</td>
<td>${address}</td>
</tr>
</table>
`)
</script>
</body>
标识符、关键字、保留字
1.标识符
- 变量、属性、函数、参数等命名
- 标识符不能是保留字或关键字
2.关键字
3.保留字
- 不是关键字但可以成为关键字
运算符
1.算术运算符
2.递增和递减运算符
-
i++、++i、i–、–i
-
前置自增自减:先赋值后运算
后置自增自减:先运算赋值
3.关系运算符
- ==会默认转换数据类型
- '‘判断值,’='判断值和类型
4.逻辑运算符
- 短路运算:如果判断成功,后半部分不会执行
<script>
/* 逻辑运算中的短路运算 */
console.log(1 && 2); //输出2
console.log(0 && 2); //输出0
console.log(0 || 3); //输出3
console.log(1 || 2); //输出1
</script>
5.赋值运算符
6.运算符优先级
- 一元运算符中!优先级最高
- 逻辑与>逻辑或
语句
- 程序三大语句:顺序语句、分支语句、循环语句
分支语句
if语句
-
单分支语句 if
-
括号内的内容不是布尔值的时候,会发生隐式转换为布尔类型
数值型除0以外结果都为true,字符串除控制符串’ '结果都为true
-
if(条件表达式){
执行体
}
if(100){
console.log('会输出结果')
}
if('100'){
console.log('会输出结果')
}
- 双分支语句 if…else…
if(条件表达式){
执行体1
}else{
执行体2
}
- 双分支语句 if…else if…else if…else
if(条件1){
执行体1
}else if(条件2){
执行体2
}else if(条件3){
执行体3
}else {
代码n
}
三元表达式
-
语法:表达式 ? 执行体1 : 执行体2
-
其本质是一条if…else…语句
switch语句
-
switch语句一般用于等值判断,不适合于区间判断
-
一般需要配合break关键字使用没有break会造成case穿透
swicth(数据){ case 值1: 执行体1 break case 值2: 执行体2 break ... default: 执行体n }
- 这里需要注意,传入的数据与匹配的值没有隐式转换,强类型匹配
循环语句
断点调试
- 浏览器中->开发者模式->sources 目录下,打断点对我们的js代码进行调试
退出循环
- break 退出整个循环,循环结束
- continue 结束本次循环,继续下一次循环
while循环
- 语法:while(条件判断){ 循环体 }
- 循环需要避免进入死循环,设置退出条件,满足条件退出循环
- 因为js不是解释型语言,不会将代码像java那样进行预编译,所以会直接执行死循环,造成栈溢出
for循环
- 语法:for (let i = 起始值; i < 终止条件; i++) {}
for(起始值;终止条件;变化量){
循环体
}
- for循环遍历数组
let arr = ['关羽','张飞','赵云','黄忠','马超']
for (let i = 0; i < arr.length; i++) {
console.log(arr[i])
}
-
死循环
- while(true)来构造“无限”循环,需要使用break退出循环。
- for(; ;)也可以来构造“无限”循环,同样需要使用break退出循环。
-
循环嵌套
for(外循环起始值;终止条件;外循环变化量){
外循环体
for(内循环起始值;终止条件;内循环变化量){
内循环体
}
}
数组
-
数组(Array)是一种数据类型,是object对象
-
声明数组
- 语法:let 数组名 = [数据1,数据2,数据3,数据n];
- let 数组名 = new Array([数据1,数据2,数据3,数据n)
-
数组中元素是有序的,每个元素都有自己的索引值(下标),从0开始
-
数组长度:通过数组中的length属性获取长度,arr.length
let arr = [1,2,3,4] //获取数组下标元素 console.log(arr[0]) //获取数组长度 console.log(arr.length)
-
操作数组
-
修改:将数组元素重新赋值
arr[下标] = 新元素
-
增加元素:
-
数组中的push(元素)方法,添加到元素末尾,并且返回添加后数组的长度
语法:arr.push(元素)
-
数组中的unshift(元素)方法,添加到元素开头,并且返回添加后数组的长度
语法:arr.unshift(元素)
-
-
删除元素
-
pop()方法删除数组最后一个元素,并且返回该元素的值
语法:arr.pop()
-
shift()方法删除数组第一个元素,并且返回该元素的值
语法:arr.shift()
-
splice(start,end)方法删除指定元素,第一个参数是删除的起始位置,第二个参数是删除的元素个数
如果第二个参数end没有写,则会从开始位置一直删除到数组结尾
-
let arr = [1,2,3,'你好'] //修改 arr[3] = 'hello' console.log(arr) // [1, 2, 3, 'hello'] //添加元素 arr.push('你好') let length = arr.push('哈哈',4,5,6) console.log(arr) // [1, 2, 3, 'hello', '你好', '哈哈', 4, 5, 6] console.log(length) // 9 length = arr.unshift(0) console.log(arr) // [0, 1, 2, 3, 'hello', '你好', '哈哈', 4, 5, 6] console.log(length); // 10 //删除 let arr2 = [1,2,3,4] // arr2.pop() // [1,2,3] // arr2.shift() // [2,3,4] // arr2.splice(1,2) // [1, 4] console.log(arr2);
-
-
数组排序:arr.sort()方法,默认为升序排列
- 升序排序:
arr.sort(function(a,b){ renturn a - b })
- 降序排列
arr.sort(function(a,b){ renturn b - a })
-
案例
- 求数组最大值最小值
let arr = [23,2,5,4,6,100,56] let max = arr[0] let min = arr[0] for (let i = 0; i < arr.length; i++) { if(max < arr[i]){ max = arr[i] } if(min > arr[i]){ min = arr[i] } } console.log(`最大值${max}最小值${min}`);
- 筛选数组元素
//筛选数组 let arr = [10,25,0,34,65,0,87,100,0,15,75] let newArr = [] for (let i = 0; i < arr.length; i++) { if(arr[i]> 50){ newArr.push(arr[i]) } } console.log(newArr);
函数
-
函数的声明
function 函数名(){ 函数体 }
-
作用:提高代复用率
- 函数的调用:函数名()
-
函数传参:如果将函数写死,name局限性也一样很大,所以需要传入用户所需参数
function 函数名(参数1,参数2,...参数n){ 函数体 }
-
无参函数与有参函数对比之下有参数的函数更灵活
//求1-100之和 function getSum(){ let sum = 0 for (var i = 1; i <=100; i++) { sum += i } console.log(sum) } getSum() //同样是求数之间的和,有参灵活性更好 function getSum2(start,end){ let sum = 0 for (var i = start; i <=end; i++) { sum += i } console.log(sum) } getSum2(100,200)
-
参数
-
参数默认值:给参数设置默认值,可以使程序更加完美 ,防止无参传入时程序报错
function 函数名(参数1 = 默认值,参数2 = 默认值,...参数n = 默认值){ 函数体 }
-
-
函数返回值:return
-
return关键字可以将内部的返回值结果返还给外部调用者
-
函数中return后面的代码不会被执行,会结束当前函数
-
return空的返回值为undefined
-
我们将上方求累加和的函数设置返回值
function getSum2(start,end){ let sum = 0 for (var i = start; i <=end; i++) { sum += i } return sum } let sum = getSum2(1,100)
-
-
补充:
- 如果函数名相同,后面会覆盖前面
- 在Javascript中实参的个数和形参的个数可以不一致
- 如果形参过多会自动填上undefined (了解即可),或者默认值
- 如果实参过多那么多余的实参会被忽略(函数内部有一个arguments,里面装着所有的实参)
- 函数碰到return会停止执行
-
思考:break 和 return 结束的区别
- break结束的是语句循环语句或者分支语句;而return结束的是函数
-
变量作用域
-
变量、函数等都有一定的作用域
-
全局变量:script标签里面或者.js文件里面变量
-
局部变量:在函数中或者块级作用域中的变量
-
特殊情况:如果在函数内部,变量没有申明直接赋值,那么在函数被调用的时候则被当做全局变量,但是不建议这种写法
function fun(){ num = 50 console.log(num) // 50 } console.log(num) //50
-
函数中的形参可以当做函数内部的局部变量
-
-
变量的访问原则:先局部,再全局,就近原则
-
-
匿名函数:function( ){ }
-
使用方法:
-
函数表达式:将匿名函数赋值给变量
let fun = function(){ 函数体 } fun() //调用函数
-
立即执行函数:无需调用立即执行,且结尾和立即函数声明之前的小括号必须要有分号‘;’结束
let fun = function(){} fun(); //如果下面有立即执行函数,必须要有分号;小括号之间才会被证明结束,否者会连接成为一个未被定义的新函数,报错 //写法1 (function(){ 匿名函数体 })(); //写法2 (function(){ 匿名函数体 }());
写法一:(function(){}) (),第一个括号的本质是将匿名函数分隔开来,第二个括号的本质是调用函数
写法二:(function(){}()),第一个外围括号的本质是将匿名函数分隔开来,第二个小括号的本质是调用函数
-
-
小例子
//函数表达式 let num1 = 1 let num2 = 1 let fun = function(num1,num2){ //传参 return num1 + num2 } console.log(fun(num1,num2)); //立即执行函数 (function (x,y) { //写法1 console.log(x + y) })(1,2); //传参 (function (x,y) { //写法2 console.log(x + y) }(1,2)); //传参
-
思考:使用函数表达式与具名函数(有名字申明的函数)的区别在哪里?
- 具名函数的调用可以写到任何位置,函数命名之前**(函数提升)**或者之后
函数表达式,必须先声明函数表达式,后调用,相当于变量需要先声明后使用
- 具名函数的调用可以写到任何位置,函数命名之前**(函数提升)**或者之后
-