作用域
通常来说,一段程序代码中所用到的名字并不是总是有效和可用的,而限定这个名字的可用性范围就是这个名字的作用域。
作用域的使用提高了程序逻辑的局限性,增强了程序的可靠性,减少了名字冲突
JavaScript的作用域分为全局作用域和局部作用域
全局作用域
全局作用域是整个script标签,或者是一个js文件
局部作用域
局部作用域就是在函数内部,只在函数内部起效果
变量的作用域
根据作用域的不同,变量可以分为两种:全局变量、局部变量
全局变量就是指在全局作用域下的变量,全局下都可以使用
局部变量就是指在局部作用域下的变量,只能在函数内部使用
注意:如果在函数内部没有使用var声明,而是直接赋值,则也属于全局变量。
函数的形参也是局部变量
从执行效率来看,全局变量只有在浏览器关闭时才会销毁,比较占内存资源
局部变量在程序执行完毕之后就会销毁,比较节约内存资源。
作用域链
根据在内部函数可以访问外部函数变量这种机制,用链式查找决定哪些数据可以被内部函数访问,
这被称为作用域链,也就是就近原则,从内往外一层一层查找。
JavaScript预解析
js引擎运行js代码分为两步——预解析和代码执行
预解析时,js引擎会把js里面所有的var还有function提到当前作用域的最前面
代码执行时,按照代码书写的顺序从上往下执行
预解析分为变量预解析和函数预解析
变量预解析就是把所有变量声明提升到当前作用域的最前面,注意,只提升了声明,没有提升赋值
函数预解析则是把所有的函数声明提升到当前作用域的最前面,但不调用
对象
对象是一组无序的相关属性和方法的集合,所有的事物都是对象
对象是由属性和方法组成。
属性是事物的特征,在对象中用属性来表示(常用名词)
方法是事物的行为,在对象中用方法来表示(常用动词)
创建对象
创建对象有三种方式:利用字面量、利用new Object、利用构造函数
利用字面量创建对象
var 对象名={
属性:属性值,
方法名:function(){
};
}
属性和方法采取键值对的方式设置,多个属性或方法间使用逗号隔开,方法冒号后面是一个匿名函数
调用对象的属性时,使用 对象名.属性名,也可以使用对象名['属性名']
调用对象的方法时,使用 对象名.方法名()
利用new Object创建对象
var obj=new Object();
obj.属性名=属性值;
obj.方法名=function(){};
利用等号赋值的方法添加属性和方法,属性和方法之间使用分号隔开
利用构造函数创建对象
构造函数可以省略创建多个对象时重复的代码
构造函数就是把对象里面一些相同的属性和方法抽出来,封装到函数里面
function 构造函数名(){
this.属性名=值;
this.方法名=function(){
}
}
var 对象名=new 构造函数名();
注意:构造函数的函数名首字母必须大写
利用构造函数创建对象也被称为对象的实例化
new关键字执行过程:首先在内存中创建了一个空对象,this指向这个空对象,然后执行构造函数里面的代码,给这个空对象添加属性和方法
遍历对象属性
使用for...in
for(k in obj){
console.log(k); //输出的是属性名
console.log(obj[k); //输出的是属性值
}
注意,k不需要加引号
这样遍历时,也会遍历方法
内置对象
JavaScript中的对象分为自定义对象、内置对象、浏览器对象
内置对象时JavaScript自带的一些对象,这些对象供开发者使用,并且提供了一些常用的、基本的、必要的方法或属性
内置对象可以通过查阅MDN文档(https://developer.mozilla.org/zh-CN/)来了解
接下来介绍一些常用内置对象
Math对象
Math对象不是一个构造对象,所以不需要new来调用,可以直接使用里面的对象和方法
Math对象中存储了一些数学相关的属性和方法
Math对象中也有一个随机数方法random(),该函数返回一个随机的小数,其范围在[0,1)中。
返回一个在两数之间的随机整数(不包括大的那个数)的方法:
function getRandomInt(min,max){
min=Math.ceil(min);
max=Math.floor(max);
return Math.floor(Math.random()*(max-min))+min;
}
返回一个在两数之间的随机整数(包括大的那个数)的方法:
function getRandomInt(min,max){
min=Math.ceil(min);
max=Math.floor(max);
return Math.floor(Math.random()*(max-min+1))+min;
}
Date对象
日期对象,用来处理日期和时间,可以返回年月日,也可以返回时分秒
是一个构造函数,所以需要使用new,调用构造函数来实例化对象才能调用这个对象
构造对象时,如果没有输入任何参数,则会返回当前时间
参数常用写法:
数字型:2019,10,01
字符串型(最常用):‘2019-12-29 8:8:8’
获取年月日时分秒:
要注意,getMonth()返回的月份比实际月份小一个月,getDay()中,周日返回0
获取总的毫秒数
获取自1970年1月1日起到现在总的毫秒数,常用于时间戳
方法:valueof()和getTime()
可以用这个方法来进行倒计时的显示:
<script>
// 计算现在据2022年3月28日12:00的倒计时
var date1=new Date();
var date2=new Date('2022-3-28 12:0:0');
// 获取总的毫秒数
var t1=date1.getTime();
var t2=date2.getTime();
// 相减得还差多少时间,单位为秒
var t=(t2-t1)/1000;
// 转换单位
var day=parseInt(t/60/60/24);
var hour=parseInt(t/60/60%24);
var m=parseInt(t/60%60);
var s=parseInt(t%60);
console.log('现在距离2022年3月28日12:00还有'+day+'天'+hour+'小时'+m+'分钟'+s+'秒');
</script>
Array对象
创建数组
数组对象,可以用来创建数组。
<script>
// 创建了一个长度为3的空数组
var arr1=new Array(3);
// 创建了一个数组[1,2,3]
var arr2=new Array(1,2,3);
</script>
判断对象是否为数组
Array对象也可以用于判断对象是否为数组
//检测arr是否为数组
//方法一
//使用instanceof
//是则返回true,反之返回false
arr instanceof Array;
//方法二(IE9以上版本才支持)
//使用Array对象中的isArray()方法
//是则返回true,反之返回false
Array.isArray(arr);
添加数组元素
push()方法可以在数组后面追加一个或者多个元素,参数是想要追加的元素,返回值为新数组的长度
unshift()是在数组的开头添加一个或者多个元素,参数是想要追加的元素,返回值为新数组的长度
<script>
var a=[1,2,3,4];
// 数组末尾添加元素5、6
// 得到[1,2,3,4,5,6]
a.push(5,6);
// 数组开头添加元素0,z
// 得到[0,z,1,2,3,4,5,6]
a.unshift(0,'z');
console.log(a);
</script>
删除数组元素
pop()方法可以删除数组的最后一个元素,没有参数,返回值为删除的元素
shift()方法可以删除数组的第一个元素,没有参数,返回值为删除的元素
<script>
var a=[1,2,3,4];
// 删除数组末尾元素
// 得到[1,2,3]
// 返回4
b=a.pop();
console.log(a);
console.log(b);
// 删除数组第一个元素
// 得到[2,3]
// 返回1
c=a.shift();
console.log(a);
console.log(c);
</script>
翻转、排序数组
reverse()方法可以用来翻转数组
sort()方法可以用来排序数组。但如果直接使用sort()函数,当排序的数组中出现大于十的数字时,会出现问题。所以使用以下写法:
//arr是要排序的数组
arr.sort(function(a,b){
//return a-b; 升序
//return b-a; 降序
})
查找数组索引方法
实例:数组去重
<script>
var a=[1,'a',5,7,'z',3,1,'a',7,'z'];
var b=[];
var t=a.length;
for(var i=0;i<t;i++){
var c=a[i];
if(b.indexOf(c)==-1){
b.push(c);
}
}
console.log(b);
</script>
数组转化为字符串
join()函数没有参数时,默认分隔符为逗号,有参数之后,原数组元素之间的分隔符为设置的参数。
字符串对象
基本包装类型
基本包装类型就是把简单数据类型包装成复杂数据类型,这样简单数据类型就有了属性和方法
字符型、数字型、布尔型都是基本包装类型
字符串不可变
字符串不可变指的是字符串变量里面的值不可变,实际上改变字符串的值的时候,是改变了变量名指向的地址,在内存中开辟了新的内存空间
因为字符串不可变,所以编写程序时不要大量拼接字符串,不然有可能使电脑卡顿
也是因为字符串不可变,所以字符串的所有方法都不会修改字符串本身,而是返回一个新的字符串
返回字符串中字符位置
indexof()函数中,开始的位置这一参数指的是从这一位置往后开始查找
实例:输出一个字符串中所有o的位置
<script>
var a='poodddgidshaosxo';
var n=0;
while(1){
var t=a.indexOf('o',n);
if(t==-1){
break;
}else{
console.log(t);
n=t+1;
}
}
</script>
根据位置返回字符
实例:统计字符串中出现次数最多的字符
<script>
var a='poodddgidshaosxod';
// 存放去重之后的字符串元素
var s=[];
//存放字符串元素对应出现的个数
var n=[];
// 计算每个元素出现的次数
for(var i=0;i<a.length;i++){
var t=s.indexOf(a.charAt(i));
if(t==-1){
s.push(a.charAt(i));
n.push(1);
}else{
n[t]=n[t]+1;
}
}
// 找到出现最多的次数的元素
var m=0;
var ms;
for(var i=0;i<n.length;i++){
if(m<n[i]){
m=n[i];
ms=s[i];
}
}
console.log('出现最多次数的元素是'+ms+',出现的次数为'+m);
</script>
拼接和截取字符串
替换字符串
使用replace('被替换的字符a','替换的字符b'),注意,这个函数使用时只能替换一次。如果字符串中有多个字符a,只替换第一个字符a
字符串转换为数组
使用split('分隔符'),在字符串中查找分隔符,按照分隔符将字符串分隔为数组