本节笔记结合黑马程序员相关视频整理了javascript的基础语法以及对象的创建和使用,并附有相关案例。
视频参考链接:黑马程序员JavaScript全套教程,Web前端必学的JS入门教程,零基础JavaScript入门
目录
javascript 是运行在客户端的脚本语言 ,可以实现业务逻辑和页面控制(决定功能),相当于人的各种行为。
js的书写方式和位置
-
行内式:直接写在元素的内部(在body中)
<input type="button" value="唐伯虎" onclick="alert('秋香姐')">
效果为:点击按钮,出现“秋香姐”
-
内嵌式:(在head中)
<script> alert('秋香'); </script>
-
外部式(在js文件中书写)
注意:
单双引号的使用:js中推荐使用单引号
js的输入输出语句
方法 | 说明 | 归属 |
---|---|---|
alert(msg) | 浏览器弹出警示框 | 浏览器 |
console.log(msg) | 浏览器控制台打印输出信息 | 浏览器 |
prompt(info) | 浏览器弹出输入框,用户可以输入 | 浏览器 |
代码示例:
<script>
// 输入框
prompt('请输入你的编号:');
// 警示框
alert('计算结果为:')
//在控制台中打印输出信息
console.log('msg')
</script>
变量
-
声明变量:var age; 其中var是js的关键字,age为变量名
-
案例:弹出提示用户输入姓名的对话框,然后弹出姓名结果
<script>
var name=prompt('请输入姓名:');
alert(name);
</script>
- 同时生成多个变量:
// 一次声明多个变量,用逗号隔开
var age=19,
sex='男',
height=1.75;
js的简单数据类型有:数字型、布尔值型、字符串型、undefined型(声明了变量,但是没有赋值)、null(声明的变量,赋值为null)
数字型
-
八进制表示:在数字前加0(如:var num=010);浏览器默认输出十进制.
-
十六进制表示:在数字前面加0x
-
js中的最大最小值:
Number.MAX_VALUE // 1.7976931348623157e+308
Number.MIN_VALUE // 5e-324
-
数字型三个特殊值
alert(Infinity); 表示无穷大,大于任何数值
alert(-Infinity); 变送无穷小,小于任何数值
alert(NaN); 代表一个非数值;isNaN():该方法用来判断非数字,若是非数字,返回true
字符串型
-
js中推荐使用单引号:如果字符串内容里面有引号,里面的引号最好使用双引号
-
字符串转义符:
转义符 说明 \n 换行符 \\ 斜杠 \’ 单引号 \‘’ 双引号 \t tab缩进 \b 空格 -
字符串长度:str. length
-
字符串拼接:多个字符串之间使用 + 进行拼接,方式为:字符串 + 任何类型 = 拼接后的新字符串(只要有字符串类型和其他类型拼接,其结果就为字符串型)
var name='xiaohu'; var age=19; console.log('我叫:'+name+'今年:'+age);
-
显示案例:弹出输入框,提示用户输入年龄,然后弹出一个警示框显示“您今年xx岁啦”
var age=prompt('请输入您的年龄:'); alert('您今年'+age+'岁啦');
-
字符串的不可变性
字符串的所有方法,都不会修改字符串本身,操作完成后会返回一个新的字符串
因为字符串不可变,所以不要大量拼接字符串(因为会不断开辟新的空间)。
-
根据位置返回字符
-
案例:统计给定字符串中出现最多的字符,并统计其出现的次数(类似hash表)
var st='oplkjoodskaapllaaaaiii'; var obj={};//先设置一个空对象,相当于hash表 for(var i=0;i<st.length;i++){ //如果该对象不存在st[i]元素,则加入,并令其等于1 if(!obj[st[i]])obj[st[i]]=1; else obj[st[i]]++;//存在,则次数+1 } //遍历对象 //存放元素和对应次数 var s,cnt=0; for(var k in obj){ if(obj[k]>cnt)s=k,cnt=obj[k]; } console.log('出现最多的元素为:'+s+',出现次数为:'+cnt);//出现最多的元素为:a,出现次数为:6
-
字符串的其他操作方法
-
替换字符:replace(‘被替换的字符’,‘替换为的字符’);默认只会替换第一个字符(可以结合indexOf替换所有的某个字符)
-
字符串转换为数组,split(‘分隔符’);
-
获取变量数据类型(typeof 关键字)
- 其中:null为object类型;undefined为undefined类型
var num=10; console.log(typeof num);
注意:prompt取过来的值为字符串型的
数据类型转换
- 转换为字符串型
方式 | 说明 | 案例 |
---|---|---|
toString() | 转成字符串 | var num =1;alert(num. toString()); |
String() 强制转换 | 转成字符串 | var num =1;alert(String(num)); |
加号拼接字符串 | 和字符串拼接的结果都是字符串 | var num =1;alert(num+‘字符串’); |
-
转换为数字型(前两个常用)
方式 说明 案例 parseInt(string)函数 将string转换成整数数值型;还可以将单位去掉 parseInt(‘78’) parseFloat(string)函数 将string转换成浮点型 parseFloat(‘23.56’) Number()强制类型转换函数 将string转换成数值型 Number(‘12’) js隐式转换(- * /) 利用算术运算隐式转换为数值型 ‘12’-0 -
转换为布尔型
方式 说明 案例 Boolean()函数 其他类型转换成布尔值 Boolean(‘true’) 注意:代表空、否定的值会被转换成false,如:‘’、0、NaN、null、undefined;其余会转换成true
运算符
-
算术运算符(+ - * / %)
-
对于浮点数精度的问题:让其直接相加或者相比较,会因为精度问题而不准确
-
-
递增(++)和递减(–)运算符
- 可放在变量前面,也可放在后面,前者为前置递增(递减)运算符,后者为后置递增(递减)运算符
- 前置和后置的区别:前置先自增,再计算结果。后置先返回原值计算,再自增
- 案例1: var age=10;console.log(age++ +10);返回结果为20,因为是先返回原值10计算出结果,然后+10,结果为20;计算之后,age变为11(先利用原值计算,再自增)
- 案例2: var age=10;console.log(++age +10);返回结果为21,因为是先自增1,然后+10,结果为21;计算之后,age变为11(先自增,再计算)
-
比较运算符(关系运算符):返回布尔值
- <、 >、 >=、<=、==(判等号)、!=(不等号)
- 全等号:=== 要求值和类型都一致
- 不全等号:!==
- 注意:对于==:会默认转换数据类型,将字符串型的数据转换成数字型数据(如:
18=='18'
//返回true)
-
逻辑运算符
- &&(逻辑与:两个都是true,结果才为true)、 ||(逻辑或:不少于一个为true,结果为true)、 !(逻辑非)
- 短路运算(逻辑中断):当有多个表达式(值)时,左边的表达式可以确定结果时,就不再继续运算右边的表达式的值
- &&:语法:表达式1&&表达式2;若表达式1值为真,则返回表达式2;若表达式1为假,则返回表达式1
- 案例:0&&1+2&&456*98;返回0,因为表达式1为假,直接返表达式1
- ||:语法:表达式1||表达式2;若表达式1结果为真,则返回表达式1;若表达式1结果为假,则返回表达式2
- 案例1: 0||456||123;返回456;因为表达式1为假,则返回表达式2,2为真
- 案例2(易错): var num=0; console.log(123||num++);console.log(num);最后num的值还是0,因为console.log(123||num++);该式只到第一个表达式就可以得到结果了,没有计算第二个表达式
- &&:语法:表达式1&&表达式2;若表达式1值为真,则返回表达式2;若表达式1为假,则返回表达式1
-
赋值运算符
- =、+=、-=、*=、/=、%=
-
运算符优先级
优先级 运算符 1 小括号() 2 一元运算符:即只有一个操作数(++ – !) 3 算数运算符(先*/% 后±) 4 关系运算符(>、 >=、 <、 <=) 5 相等运算符( ==、 !=、 ===、 !==
)6 逻辑运算符(先&& 后||) 7 赋值运算符(=) 8 逗号运算符(,)
下面讲的语法规则类似C/C++里面的语法
流程控制
-
案例:接收用户输入的年份,如果是闰年就弹出闰年,反之,弹出平年(能被400整除 或者 能被4整除但不能被100整除的年份为闰年)
var year=prompt('请输入年份:'); if(year%400==0||year%100 && year%4==0) { alert('是闰年'); } else alert('是平年');
三元表达式
-
语法结构: 条件表达式? 表达式1:表达式2
- 若条件表达式结果为真,则返回表达式1的结果,反之,返回表达式2的结果
-
案例1
var n=10; var res=n>5?'对':'错'; console.log(res);//结果为:对
-
案例2:用户输入数字,小于10,则在前面补0,如:01,02…;大于10,则不需要补,如:17
var num=prompt('请输入数字:'); var res=num>10?num:'0'+num;//字符串拼接 console.log(res);
switch分支语句
-
语法结构:
switch(表达式){ case val1: 执行语句1; break; case val2: 执行语句2; break; default: 若上面语句都不满足,则执行的语句; }
-
案例:用户在弹出框中输入一个水果,若有就弹出该水果的价格,若没有该水果就弹出”没有此水果“
var food=prompt('请输入水果的名称:'); switch(food){ case '苹果': alert('苹果的价格是10元'); break; case '香蕉': alert('香蕉的价格是5元'); break; default: alert('没有此水果'); break; }
-
注意:
- 表达式和val匹配的值必须是全等(即值和数据类型都相等)
- 需要加上break语句,因为若当前case里面没有break,则不会退出switch,而是继续执行下一个case
- switch语句进行条件判断后直接执行到程序的条件语句,不用一句一句的判断
循环语句
- 案例1:用户输入行数和列数,在控制台上打印对应行数和列数的星星
var r=prompt('输入行数:');
var c=prompt('输入列数:');
var str='';
for(var i=0;i<r;i++)
{
for(var j=0;j<c;j++)
{
str+='⭐';
}
str+='\n';
}
console.log(str);
- 案例2:打印九九乘法表
var str='';
for(var i=1;i<=9;i++)
{
for(var j=1;j<=i;j++)
{
str+=j+'*'+i+'='+i*j+'\t';
}
str+='\n';
}
console.log(str);
综合案例:简易ATM
需求:
- 里面现有100块
- 若存钱,就输入钱数加上先前存的钱数,之后弹出余额提示框
- 若取钱,就减去取的钱数,之后弹出显示余额提示框
- 如果显示余额,就输出余额
- 如果退出,弹出退出信息框
代码
var cur=100;
var x=true;
while(x)
{
var choice=prompt('请输入您的操作:\n1.存钱\n2.取钱\n3.显示余额\n4.退出');
switch(choice)
{
case '1':
var cun=prompt('输入存入的金额:');
cur+=parseFloat(cun);
alert('您的余额为:'+cur);
break;
case '2':
var qu=prompt('输入取出的金额:');
cur-=parseFloat(qu);
alert('您的余额为:'+cur);
break;
case '3':
alert('您的余额为:'+cur);
break;
case '4':
alert('谢谢使用');
x=false;
break;
default:
alert('输入有误');
break;
}
}
断点调试步骤
打开浏览器源代码——>sources——>找到要调试的文件,在程序的某一行设置断点;f11:程序的单步执行
数组
里面可以放任何类型的数据类型,用逗号分割
-
两种创建方式
-
利用数组字面量创建(常见)
var 数组名 = [元素1, 元素2];
-
利用new关键字创建
var 数组名 = new Array();
var arr=new Array(2,3);//等价于[2,3]
-
-
检测是否为数组(两种方法)
-
instanceof 运算符: arr instanceof Array
-
Array.isArray(arr);
-
-
数组的长度:数组名.length
-
数组对象添加和删除数组元素的方法
-
案例1:数组转换为分割字符串
要求:将数组[‘red’,‘green’,‘blue’,‘pink’]转换为字符串,且用|或其他符号分割,输出’red|green|blue|pink’
var arr=['red','green','blue','pink']; var str=''; var sep='|' for(var i=0;i<arr.length;i++) { str+=arr[i]; if(i!=arr.length-1)str+=sep; } console.log(str);
-
数组中新增元素
-
通过修改length长度新增数组元素
其中,empty为undefined数据类型
-
修改索引号
var arr=['red','green','blue','pink']; arr[10]='asj'; console.log(arr);
-
-
案例2:筛选数组:将一个数组中满足条件数筛选出来放入新数组中
//法一:通过设置新的索引值来加入筛选的数据 var arr=[1,34,29,30,79,9]; var len=arr.length; var newArr=[]; var cnt=0; for(var i=0;i<len;i++) { if(arr[i]>20)newArr[cnt++]=arr[i]; } console.log(newArr);
//法二:通过newArr.length来加入筛选的数据 var arr=[1,34,29,30,79,9]; var len=arr.length; var newArr=[]; for(var i=0;i<len;i++){ if(arr[i]>20)newArr[newArr.length]=arr[i]; }
-
数组排序(注意会改变原数组)
-
对于sort函数,需要自己写匿名函数,因为默认是按照字典序排列
arr.sort(function(a,b){ return a-b;//升序排列 //return b-a;//降序排列 })
-
-
数组索引方法
-
对于indexOf函数,第一个参数:要查找的字符,第二个参数:起始的位置(可省略)
-
案例1:去重;给定数组,要求去除数组中的重复元素
设置一个新数组,检查原数组的每个元素在新数组中是否存在,不存在就加入,反之,跳过
var arr=['a','b','c','d','e','a','a','h','c']; var newArr=[]; for(var i=0;i<arr.length;i++){ if(newArr.indexOf(arr[i]) == -1)newArr.push(arr[i]); } console.log(newArr);
-
案例2:查找给定字符串中所有o出现的位置以及次数
var st='oplkjoodskoo'; var pos=st.indexOf('o'); var cnt=0; while(pos!=-1){ cnt++; console.log('第'+cnt+'次出现的位置:'+pos); //需要从当前找到的位置之后开始查找 pos=st.indexOf('o',pos+1); } console.log('共出现'+cnt+'次');
-
-
数组转换为字符串
代码展示
var arr=['red','pink','blue'];
console.log(arr.toString());//结果:red,pink,blue
console.log(arr.join('*'));//结果:red*pink*blue
函数
-
声明函数
- 方式1:命名函数
function 函数名(形参1,形参2…)
{
函数体;
return 返回的结果;
}
- 方式2:函数表达式(匿名函数)
var 变量名 = function(){};
- 注意:
- 函数有return,则返回其后面的值,没有return,则返回undefined
- 方式2中的是变量名,不是函数名;函数表达式声明方式和声明变量差不多,只不过变量里面存的是值,而函数表达式中存的是函数
-
函数调用
函数名(实参1,实参2…);
-
arguments的使用
-
当不确定有多少个参数传递的时候,可以用arguments来获取,在js中,arguments实际上是当前函数的一个内置对象,所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参
-
arguments展示形式是一个伪数组,所以可以进行遍历,伪数组的特点:有length属性;按索引方式存储数据;不具有数组的push、pop等方法
function fun(){ console.log(arguments); console.log(arguments.length); console.log(arguments[0]); } fun(1,2,3);
-
-
案例:利用arguments实现求最大值
function getMax(){ var max=arguments[0]; for(var i=1;i<arguments.length;i++){ if(arguments[i]>max)max=arguments[i]; } return max; } console.log(getMax(6,4,7,1,3));
js作用域
代码变量在某个范围内起作用和效果
-
全局作用域:整个script标签,或者是一个单独的js文件
-
局部作用域:在函数内部,该变量只在函数内部起效果和作用
-
全局变量:在全局作用域下的变量,在全局下都可以使用;注意:若在局部作用域下,没有声明而直接赋值的变量也属于全局变量
- 全局变量只有在浏览器关闭的时候才会销毁,比较占内存资源
-
局部变量:在局部作用域下的变量
- 当程序执行完毕的时候销毁
-
作用域链:内部函数访问外部函数(函数之间嵌套)的变量,采取的是链式查找的方式来决定取哪个值,就近原则
js预解析
-
预解析分为 变量预解析(变量提升)和函数预解析(函数提升);变量提升就是把所有的变量声明提升到当前作用域的最前面,不提升赋值操作。函数提升就是将所有的函数声明提升到当前作用域的最前面,不调用函数
-
案例1(变量提升):
console.log(num); var num = 10; //结果为undefined //预解析步骤如下: //先将变量声明提升到当前作用域的最前面,且不提升赋值操作 var num; //然后按照顺序执行代码 console.log(num);//此处num没有赋值,所以为undefined num=10;
-
案例2(变量提升):
fun(); var fun = function(){ console.log(22); } //结果报错 //预解析步骤如下: //先将变量声明提升到当前作用域的最前面,且不提升赋值操作 var fun; //然后按照顺序执行代码 fun();//此时函数没有定义,所以报错
-
案例3(函数提升)
fun(); function fun(){ console.log(22); } //先将函数声明提升到当前作用域的最前面,不调用函数 function fun(){ console.log(22); } //然后按照顺序执行代码 fun();//所以执行通过,输出22
-
注意:通过上面案例,函数表达式(匿名函数)的调用必须写在函数表达式的下面
-
综合案例(先看最外层的变量和函数声明提升,再看里面的函数和变量声明提升)
var num=10; fun(); function fun(){ console.log(num); var num=20; } //结果输出:undefined //预解析过程: 先将变量和函数声明提升到最前面 var num; function fun(){ //将变量声明提升到当前作用域的最前面 var num; console.log(num); num=20; } //然后按照顺序执行代码 num=10; fun();//根据前面的链式作用域的就近原则,num为undefined类型
-
注意:若var a=b=c=9;表示的是只声明了a,后面的bc是没有被声明的,只是赋值。若要声明abc三个变量,则用逗号隔开,如:var a=9,b=9,c=9;
-
js对象
是一组无序的相关属性和方法的集合
变量和属性的区别:变量需要单独声明并赋值,而属性在对象里面是不需要声明的
-
创建对象的三种方式
-
利用字面量创建对象:花括号{}里面包含了表达整个具体事物(对象)的属性和方法
//类似CSS语法,即键值对的形式,属性和属性以及属性和方法之间用逗号隔开;方法右匿名函数生成 var obj={ name:'张三丰', age:18, sex:'男', sayHi:function(){ console.log('hi~~'); } }
-
利用new Object创建对象
var obj=new Object(); obj.name='张三丰'; obj.age=19; obj.sayHi=function(){ console.log('hi~~'); }
-
利用构造函数创建对象(前面两种方法一次只能创建一个对象,在不同的对象中,会遇到大量的属性和方法是相同的,只能复制,所以可以利用函数的方法,重复这些相同的代码。该函数称为构造函数)好处:可以批量生成对象
声明构造函数(和普通函数不同在于:构造函数中存放的是当前对象的属性和方法):
function 构造函数名(){
this.属性=值;
this.方法=function(){}
}
调用构造函数:
new 构造函数名();
//构造函数的名称第一个字母大写 function Star(name,age,sex){ this.name=name; this.age=age; this.sex=sex; } var xh=new Star('xiaohu',18,'女'); var xz=new Star('xiaozhang',19,'女'); var xzh=new Star('xiaozhou',20,'男'); console.log(xh.name); console.log(xzh['sex']);
-
-
使用对象
-
调用对象的属性:
- 对象名.属性名(即obj. name)
- 对象名[‘属性名’] (即obj[‘age’])
-
调用对象的方法:
- 对象名.方法名(即 obj. sayHi()😉
-
遍历对象:for (变量 in 对象)
-
var obj={
name:'张三丰',
age:18,
sex:'男',
sayHi:function(){
console.log('hi~~');
}
}
for(var k in obj){
console.log(k);//输出的是属性名
console.log(obj[k]);//输出的是属性值
}
自定义对象
- 案例:封装自己的数学对象max
//通过构造函数
function Obj(){
this.max=function(){
var m=arguments[0];
for(var i=1;i<arguments.length;i++){
if(arguments[i]>m)m=arguments[i];
}
return m;
}
}
var x=new Obj();
console.log(x.max(1,5,3));
//通过字面量创建对象的方式
var obj={
max:function(){
var m=arguments[0];
for(var i=1;i<arguments.length;i++){
if(arguments[i]>m)m=arguments[i];
}
return m;
}
}
console.log(obj.max(-1,-9,-8));
内置对象
学会在MDN中查阅相关文档
-
Math对象
-
Math.max()
-
Math.min()
-
Math.round() //四舍五入,对于.5的数据,往大了取,如:1.5,在1和2中选择大的那个,即为2;-1.5在-1和-2中取较大的那个,即为-1
-
Math.floor() //向下取整
-
Math.ceil() //向上取整
-
Math.PI
-
Math.abs() //绝对值
-
Math.random() //随机数;返回一个随机的小数;大于等于0,小于1
-
若想要得到指定范围内的随机数,利用下面红框公式即可
-
案例:实现随机点名(将所有姓名放入一个数组中,然后按照所有范围内的下标中的随机数,来实现随机点名)
//获取在0-arr.length-1(包括端点)的随机下标 function getRandom(min,max){ return Math.floor(Math.random()*(max-min+1))+min; } var arr=['red','green','xiaohu','xiaozhang','xiaozhou','xiaozhu']; console.log(arr[getRandom(0,arr.length-1)]);
-
-
-
日期对象
//若没有参数,则返回系统当前时间 var d=new Date(); console.log(d); //若里面写参数,则参数常见写法:'2024-10-1 8:8:9' 即年月日用-隔开,时分秒用:隔开 var d1=new Date('2024-10-1 8:8:9'); console.log(d1);
-
日期格式化:
-
如:
var d=new Date(); console.log(d.getFullYear());
-
综合案例1:输出当前时间:按照2024年8月1日 星期六 22:09:08这样的格式输出
function date(){ var d=new Date(); var year=d.getFullYear(); var month=d.getMonth()+1; var date=d.getDate(); var h=d.getHours(); h=h<10?'0'+h:h; var m=d.getMinutes(); m=m<10?'0'+m:m; var s=d.getSeconds(); s=s<10?'0'+s:s; var week=d.getDay(); var arr=['星期日','星期一','星期二','星期三','星期四','星期五','星期六']; return year+'年'+month+'月'+date+'日'+arr[week]+h+':'+m+':'+s; } console.log(date());
-
获取日期总的毫秒形式:Date对象是基于1970年1月1日起的毫秒数(三种方法)
- var date=new Date(); date.valueOf() 或者date.getTime()
- var date = +new Date();
- Date.now()打印即可
-
综合案例2:倒计时效果
输入的时间减去现在的时间就是剩余的时间:利用时间戳,输入毫秒数-现在的毫秒数,得到剩余时间的毫秒数;然后将剩余时间总的毫秒数转换为天、时、分、秒
转换公式如下:
d=parseInt(总秒数/60/60/24) //计算天数
h=parseInt(总秒数/60/60%24) //计算小时
m=parseInt(总秒数/60%60) //计算分钟数
s=parseInt(总秒数%60) //计算秒数
function fun(time){ var nowTime=+new Date(); var inputTime=+new Date(time); var times=(inputTime-nowTime)/1000;//得到总秒数 var d=parseInt(times/60/60/24); d=d<10?'0'+d:d; var h=parseInt(times/60/60%24); h=h<10?'0'+h:h; var m=parseInt(times/60%60); m=m<10?'0'+m:m; var s=parseInt(times%60); s<10?'0'+s:s; return d+'天'+h+'时'+m+'分'+s+'秒'; } console.log(fun('2024-5-2 15:17:56'));
-
-
浏览器对象(JS API 学习)
简单类型和复杂类型
- 简单类型:基本数据类型或者值类型(string number boolean undefined null)
- 在存储时变量中存储的是值本身
- 复杂类型:引用类型(通过new关键字创建的对象,Object Array Date);栈空间里面存放的是地址,真正的对象实例存放在堆空间中
- 在存储是变量中存储的仅仅是地址(引用)
- 栈:由操作系统自动分配释放存放函数的参数值、局部变量的值等,简单数据类型存放在栈里面
- 堆:存储复杂类型(对象),一般由程序员释放,若程序员不释放,则由垃圾回收机制回收,复杂数据类型存放到堆里面