JavaScript作用域
何为作用域呢?简单而言,就是标识符在某个范围起作用与效果,提高程序可靠性,减少命名冲突。
javascript作用域
- 全局作用域
- 局部作用域
全局作用域
标识符处于整个script脚本或单独的js文件中,便叫做全局作用域
<script>
var num = 10;
console.log(num) //标识符num的作用域便属于全局作用域
</script>
局部作用域
标识符处于函数内部,便叫做局部作用域
<script>
function fn() {
var num = 20;
console.log(num) //20
}
fn() //调用函数
</script>
变量的作用域
根据作用域的不同,变量可分为全局变量及局部变量
全局变量
在全局作用域下声明的变量便叫做全局变量
<script>
var num = 20;
console.log(num);
function fn() {
console.log(num);
}
fn()
</script>
全局变量之未使用var声明的变量
<script>
function fn() {
num = 5;
}
fn();
console.log(num);
</script>
局部变量
在函数内部声明的变量属于局部变量
<script type="text/javascript">
function fn() {
var num = 20;
console.log(num);
}
fn()
</script>
局部变量之函数的形参
函数的形参也可以看做局部变量
<script type="text/javascript">
function fn(num){
console.log(num)
}
fn(20)
console.log(num);
</script>
全局变量 局部变量的区别
-
全局变量在全局任何位置都能被调用到,只有当浏览器关闭才能被销毁。比较占内存。
-
局部变量在函数结束时便会被销毁,比较节省内存
Javascript块级作用域
ES6之后,引进块级作用域,何为块级作用域呢?{}便是一个最简单的块级作用域
<script>
if(5>3) {
var num = 20;
}
console.log(num) //20
</script>
javascript作用域链
内部函数访问外部函数变量的机制,采用链式的方式一级一级往上查找,被称为作用域链(就近原则)
<script type="text/javascript">
var num =20;
function fn(){
var num =25;
function fn2(){
console.log(num)
}
fn2()
}
fn()
</script>
javascript作用链之习题
习题一
<script>
function f1() {
var num = 123;
function f2() {
console.log(num)
}
f2() //123
}
var num = 456;
f1()
</script>
习题二
<script>
var a = 1;
function fn1() {
var a = 2;
var b = '22';
fn2()
function fn2(){
var a = 3;
fn3();
function fn3() {
var a = 4;
console.log(a); //a = 4
console.log(b); //b = '22'
}
}
}
fn1()
</script>
javascript预解析
js引擎执行js代码分为两步:预解析 代码执行
- 预解析:js引擎会把js里面的所有使用var 声明的变量和function声明的函数提升到当前作用域的最顶部
- 代码执行 :按照代码执行的顺序从上往下执行
预解析分为变量预解析及函数预解析
- 变量预解析会把变量提升到当前作用域的最顶部,不提升赋值操作
- 函数预解析会把函数声明提升到当前作用域的最顶部,不调用函数。
变量预解析
<script type="text/javascript">
console.log(num);
var num = 10;
// 上述步骤相当于下列代码
// var num;
// console.log(num);
// num = 10;
</script>
函数预解析
函数预解析第一种情况
<script type="text/javascript">
fn();
function fn(){
console.log('hello')
}
/*上述代码相当于下列代码
function fn() {
console.log('hello')
}
fn()*/
</script>
函数预解析的第二种方法
<script type="text/javascript">
fn();
var fn = function(){
console.log('hello')
}
/* 上述代码相当于下列情况
var fn;
fn();
fn=function () {
console.log('hello') 代码会报错
}
*/
</script>
预解析之习题一
<script>
var num = 10;
fun();
function fun(){
console.log(num);
var num =20;
}
/* 上述代码相当于下列代码
var num;
function fun() {
var num;
console.log(num);
num = 20;
}
num = 20;
fun()
*/
</script>
预解析之习题二
<script type="text/javascript">
var num = 10;
function fn() {
console.log(num)//undefined;
var num = 20;
console.log(num)//20
};
fn()
/* 上述代码相当于下列代码
var num;
function fn(){
var num;
console.log(num);//undefined
num = 20;
console.log(num)//20
}
num = 10;
fn()
*/
</script>
预解析之习题三
<script>
var a = 18;
f1();
function f1(){
var b = 9;
console.log(a);//undefined
console.log(b);//9
var a = '22'
}
/* 上述代码相当于
var a;
function f1(){
var b;
var a;
b = 9;
console.log(a);
console.log(b);
a = '22'
}
a = 18;
f1()
*/
</script>
预解析之习题四
<script>
f1();
console.log(c);//9
console.log(b);//9
console.log(a);//报错
function f1(){
var a = b = c =9;
console.log(a);//9
console.log(b);//9
console.log(c);//9
}
/*上述代码相当于
function f1(){
var a;
a = 9;
b = 9;
c = 9;
console.log(a);
console.log(b);
console.log(c);
}
f1();
console.log(c);
console.log(b);
console.log(a);
*/
</script>
javascript对象
对象是一组无序的相关属性和方法的集合、所有的事物都可以是对象,例如字符串,数组,函数等等
对象是由属性与方法组成
- 属性:对象的特性,在对象中用属性表示
- 方法:对象的行为,在对象中用方法表示。
为什么需要对象
保存一个值,可以用到变量,保存多个值时,可以用到数组,对象可以表示一个事物的具体信息,让结构更清晰。
创建对象的方法
- 利用字面量的方式创建对象
- 利用 new Object创建对象
- 利用构造函数创建对象
字面量的方式创建对象
<script>
var obj = {
name:'尧子陌',
sex:'男',
age:18,
say:function(){
console.log('hello word')
}
};
console.log(obj.name);
console.log(obj['name']);
obj.say()
</script>
注意事项
- 属性与属性值之间采用键对值的形式,中间用英文状态下的冒号相隔
- 多组属性之间用英文状态下的逗号相隔
- 调用方法时,不要忘记加小括号。
调用对象的属性与方法
调用对象的属性
- 对象.属性
- 对象['属性‘]
调用对象的方法
- 对象.方法();
变量与属性 方法与函数之间的区别
-
变量是单独声明赋值,单独存在
-
属性是对象里面的变量,不需要声明,用来描述事物的特征。
-
函数是单独存在,通过函数名()调用函数
-
方法是对象里面的函数,通过对象名.方法()来调用方法,用来描述事物的特性与行为
new Object的方式创建对象
注意事项
- 使用new Object的方式创建对象并采用等号的方式添加对象的属性与方法
- 多组属性之间用英文状态下的分号相隔,
- 调用对象的属性与方法与字面量调用对象的属性与方法一致。
<script>
var object = new Object();
object.name='尧子陌';
object.sex='男';
object.age='24';
object.say =function(){
console.log('hello word')
};
console.log(object);
console.log(object.name);
console.log(object.sex);
object.say();
</script>
构造函数创建对象
构造函数是一种特殊的函数,主要是用来初始化对象,即为对象成员变量赋初始值,它与new一起使用,把对象的公共属性与方法抽取出来,封装到函数里面。
注意事项
- 构造函数名首字母必须要大写
- 构造函数不需要return 便可以返回结果
- 构造函数必须跟new关键字一起使用
- 构造函数的属性与方法前面必须要使用this
<script>
function Star(name,sex,age,say) {
this.name = name;
this.sex = sex;
this.age = age;
this.say =function(){
console.log('hello word')
}
};
var people = new Star('尧子陌','男','24');
console.log(people);
console.log(people.name);
people.say();
</script>
构造函数的案例
使用构造函数创建猪八戒及成吉思汗两个对象
<script>
function Star(name,sex,age,say) {
this.name = name;
this.sex = sex;
this.age = age;
this.say =function(sayHi){
console.log(sayHi)
}
};
var people1 = new Star('猪八戒','男','1200岁');
people1.say('俺老猪很能吃呢');
console.log(people1);
var people2= new Star('成吉思汗','男','54');
people2.say('只识弯弓射大雕');
console.log(people2)
</script>
构造函数与对象
- 构造函数抽取对象中公共属性与方法,泛指某一大类
- 使用new关键字创建对象的过程被称为对象的实例化。
new关键字
new关键字的执行过程
1.在内存中创建一个空对象
2.this指向这个新对象
3.执行构造函数的代码,为对象添加属性与方法
4.返回新对象(不需要return)
遍历对象
for( 变量 in 对象) {
}
变量用key表示,但简写为key
<script>
var obj = {
name:'尧子陌',
sex:'男',
age:18,
say:function(){
console.log('hello word')
}
};
for(var k in obj) {
console.log(k);
console.log(obj[k])
}
</script>
对象的总结
- 对象可以让结构更加清晰
- 对象是复杂类型Object
- 对象是一组无序的属性与方法的集合
- 构造函数泛指某一大类
- 使用 for in可以遍历对象
javascript内置对象
javascript对象分为3类:自定义对象 内置对象 浏览器对象。前两者属于ECMAScript标准,后者属于js独有
注意事项
- 内置对象属于ECMAScript对象,供开发者使用,可以提高开发效率。
- js内置对象:Math对象 Data对象 Array对象 String对象等等
查文档的途径
如何学习对象中的方法
- 查看该方法的功能
- 查看里面参数的意义与类型
- 查看返回值的意义与类型
- 用demo进行测试
Math对象
Math对象属于ECMAScript中的内置对象,它拥有许多数学函数方法。它并不是一个函数对象。
- Math.max:返回多个数值中的最大值
- Math.min:返回多个数值中的最小值
<script>
console.log(Math.PI);//打印圆周率
console.log(Math.max(50,100,150,850,300)); //返回多个数值中的最大值
console.log(Math.min(50,20,10,5,800,2,200));//返回多个数值中的最小值
</script>
Math对象之封装属于数学对象
封装属于自己的数学对象,里面有圆周率,最大值及最小值等
<script>
var myMath = {
PI:function () {
return Math.PI;
}
Max:function(){
var max = arguments[0];
for(var i =0;i<arguments.length;i++){
if(max<arguments[i]){
max = arguments[i]
}
}
return max;
},
Min:function(){
var min = arguments[0];
for(var i =0;i<arguments.length;i++){
if(min>arguments[i]) {
min = arguments[i]
}
}
return min
}
}
console.log(myMath.PI);
console.log(myMath.Max(20,12,50,63,11));
console.log(myMath.Min(20,12,50,63,11));
</script>
Math对象常用的方法
绝对值方法Math.abs()
<script>
console.log(Math.abs(-2));//2
console.log(Math.abs('-2'));//2 会把字符串转换成数值
console.log(Math.abs('尧子陌'));//NaN;
</script>
Math对象之三个取整方法
- Math.floor() 向下取整
- Math.ceil() 向上取整
- Math.round() 四舍五入取整
<script>
// Math.floor() 向下取整
console.log(Math.floor(-2.5)) // -3
console.log(Math.floor(1.8)) // 1
console.log(Math.floor(2.5)) // 2
console.log(Math.floor(0.5)) // 0
//Math.ceil() 向上取整
console.log(Math.ceil(2.6)) //3
console.log(Math.ceil(5.8)) // 6
console.log(Math.ceil(-1.5)) // -1
console.log(Math.ceil(0.6)) //1
//Math.round() 四舍五入取整
console.log(Math.round(2.6)) //3
console.log(Math.round(5.8)) // 6
console.log(Math.round(-1.5)) // -1
console.log(Math.round(0.6)) //1
</script>
注意:Math.round(-1.5)及Math.ceil(-1.5)会往大的取值
Math对象之获取随机数
Math.random:获取随机数(0~1)
<script>
console.log(Math.random()) //生成0~1之间的随机数
</script>
Math对象之获取[min,max]之间的随机整数
Math.floor(Math.random() * (max - min + 1)) + min;
Math对象之获取1~10之间的任意整数
<script>
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min
}
console.log(getRandom(1, 10));
</script>
Math对象之猜数字游戏
<script>
// 随机生成1~10之间的整数
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min - 1)) * min
}
var random = getRandom(1, 10)
console.log(random);
// 让用户随机输入一个整数数值
while (true) {
var username = prompt('请输入1~10之间的随机整数');
if (username > random) {
alert('数字大了 继续猜')
} else if (username < random) {
alert("数字小了 继续猜")
} else {
alert('恭喜你 正确');
break
}
}
</script>
Date对象
注意事项
- Data对象和Math对象不一样,它属于构造函数
- Data对象用来处理日期和时间。
Date对象之获取当前的时间
<script>
var time = new Date();
console.log(time) //获取当前时间
</script>
Date对象之参数
Date里面的参数是以字符串的形式写入的
<script>
var time = new Date('2020-12-28 23:36');
console.log(time);
</script>
Date对象之日期格式化
Date对象之拼出当前的日期
<script>
var date = new Date();
var year = date.getFullYear(); //年
var mouth = date.getMonth(); //年
var day = date.getDate(); //当天日期
var arr = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六']
var week = date.getDay(); //星期
console.log(year + '年' + mouth + '月' + day + '日' + arr[week])
</script>
Data对象之封装一个日期格式化对象
<script>
function getTimer() {
var date = new Date();
var h = date.getHours();
h = h < 10 ? '0' + h : h;
var m = date.getMinutes();
m = m < 10 ? '0' + m : m;
var s = date.getSeconds();
s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s
};
console.log(getTimer());
</script>
Date对象之获取日期总的毫秒数(时间戳)
四种方法
<script>
var date = new Date();
console.log(date.valueOf());
console.log(date.getTime());
console.log(+new Date());
console.log(Date.now());
</script>
Date对象之倒计时
核心算法
- 用户输入的时间减去当前的时间,即为倒计时
- 用时间戳来做,用户输入的时间总毫秒数减去当前的时间总毫秒数,得到就是剩余的时间毫秒数
- 把剩余时间的毫秒数转换成 天 时 分 秒
<script>
function countTime(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 = s < 10 ? '0' + s : s
return d + "天" + h + "时" + m + "分" + s + "秒"
}
console.log(countTime("2021-2-17 18:00:00"))
</script>
数组
- new Array() 若没有参数 则默认为空数组
- new Array(5) 参数若有一个数字 则代表当前数组的长度
- new Array(5,5,6) 参数若有2个及2个以上 里面则是数组元素
<script>
var arr1 = new Array() //声明一个空数组
var arr2 = new Array(5) //一个参数则代表数组的长度
var arr3 = new Array(5,6,9,89) //两个以上的参数则代表数组元素
console.log(arr1)
console.log(arr2)
console.log(arr3)
</script>
如何检测是否为数组呢
- 通过instanceof 用来检测类型是否为数组
- 通过Array.isArray(参数)来检测是否为数组
上述方法 若参数为数组 则显示true 若参数不是数组 则返回false
instanceof
<script>
var arr = [];
var obj = {};
console.log(arr instanceof Array);
console.log(obj instanceof Array);
</script>
Array.isArray()
<script>
var arr = [];
var obj = {};
console.log(Array.isArray(arr));
console.log(Array.isArray(obj));
</script>
通过判断数组的方法来翻转数组
<script>
function reserveArr(arr) {
if (arr instanceof Array) {
var newArr = [];
for (var i = arr.length - 1; i >= 0; i--) {
newArr[newArr.length] = arr[i]
}
return newArr
} else {
return '非数组,请重新输入'
}
}
console.log(reserveArr([20, 50, 10, 2, 5]));
console.log(reserveArr(20, 50, 2, 5, 6));
</script>
数组方法
push()
<script>
var arr = [20, 50, 30];
console.log(arr.push(50, 20, 60));
console.log(arr);
</script>
注意事项
- push是在数组的末尾添加一个或者多个数组元素
- push完毕之后,显示的是新数组的长度
- push后面的参数直接输入数组元素即可
- 原数组也会发生改变
unshift()
<script>
var arr = [50, 20, 10];
console.log(arr.unshift('尧子陌', 'hello word'));
console.log(arr);
</script>
注意事项
- unshift是在数组的开头添加一个或者多个数组元素
- unshift完毕之后,显示的是新数组的长度
- unshif后面的参数直接输入数组元素即可
- 原数组也会发发生改变
pop()
<script>
var arr = [20, 50, 20, 60, 58];
console.log(arr.pop());
console.log(arr);
</script>
注意事项
- pop()是用来删除数组的最后一项数组元素,返回的是删除的数组元素
- pop()后面没有参数
- 原数组也会改变
shift()
<script>
var arr = ['尧子陌', 50, 100, 60];
console.log(arr.shift());
console.log(arr);
</script>
注意事项
- shift()是删除数组的第一项数组元素,返回的是被删除的数组元素
- shift()后面没有参数
- 原数组也会发生改变
数组方法之习题一
一个包含工资的数组[1500,1200,2000,2100,1800],要求把数组中的工资超过2000的删除,剩余的放到新数组里面
<script>
var arr = [1500, 1200, 2000, 2100, 1800];
var newArr = [];
for (var i = 0; i <= arr.length; i++) {
if (arr[i] >= 2000) {
newArr.push(arr[i])
}
}
console.log(newArr);
</script>
数组排序
reserve()
目的:实现数组反转
<script>
var arr = ['black', 'yellow', 'red', 'blue'];
arr.reverse();
console.log(arr);
</script>
sort()
实现数组排序
- a-b:升序
- b-a:降序
<script>
var arr = [5, 20, 65, 95, 15, 3];
arr.sort(function(a, b) {
return a - b
});
console.log(arr);
</script>
数组索引方法
indexof()
- 参数为数组元素,则返回该数组元素所在的索引号,从前面开始查找
- 如果找不到该数组元素,则返回-1
<script>
var arr = ["尧子陌", "临风笑却世间", '22', '33', '55'];
console.log(arr.indexOf('临风笑却世间')) //1
console.log(arr.indexOf('惊鸿')) // -1
</script>
lastIndexof()
- 参数为数组元素,返回值为最后一个符合条件的数组元素所在的索引号,从后面开始查找
- 如果找不到该数组元素,则返回-1
<script>
var arr = ['尧子陌', '惊鸿', '220', '550', '665', '尧子陌', '惊鸿', '220', '550', '665'];
console.log(arr.lastIndexOf('惊鸿')) // 6
console.log(arr.lastIndexOf('520')) // -1
</script>
数组去重(重点)
思路如下
- 遍历求数组
- 使用旧数组元素去查询新数组,如果该数组元素在新数组元素没出现,则添加,反之,则不添加
<script>
function unique(arr) {
var newArr = [];
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i]) === -1) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique(['c', 'a', 'c', 'b', 'd', 's', 'c', 'aa', 'b', 'a', 'a']))
</script>
数组转换成字符串
toString()
利用toString()可将数组转换成字符串
<script>
var arr = [20, 50, 60, '尧子陌'];
console.log(arr.toString()) //控制台打印结果
</script
join(分隔符)
利用join可将数组转换成字符串,另外还可以加上分隔符
<script>
var arr = [20, 50, 60, '尧子陌'];
console.log(arr.join(",")) //控制台打印结果
</script>
字符串
思考问题,字符串为基本数据类型,为什么会有属性与方法呢,很简单,因为有基本包装数据类型
基本包装类型
何谓基本包装类型呢,简单而言,就是把简单的数据类型包装成复杂数据类型
<script>
var str = 'star';
console.log(str.length);
/* 第一步:把基本数据类型包装成复杂数据类型
var temp = new String('star')
第二步:temp赋值给str
str = temp
第三步:销毁临时变量
temp =null
*/
</script>
特殊引用类型
Js有三种特殊引用类型:Number String Boolean
字符串的不可变性
利用变量名可将字符串重新赋值,相当于在内存中开辟一块空间,因此不要拼接字符串,造成电脑卡顿
根据字符串返回索引位置
- indexOf('查找的字符元素‘,[起始的位置])
- lastIndexOf(查找的字符元素’,[起始的位置])
注意事项
- 使用lastIndexOf()的时候,第二个参数为从哪个索引号开始查找,是从右往左查找的
<script>
var str = 'acdefghibcdezafghdefghaijklbmnb';
console.log(str.indexOf('a', 3)); //查找a从索引3开始查找
console.log(str.indexOf('b', 3)) // 查找b从索引3开始查找
console.log(str.lastIndexOf('b', 26)) //查找b从索引26开始查找
</script>
查找字符串 出现的位置及次数
查找’abcofoxyozzopp’出现的位置及次数
<script>
var str = 'abcofoxyozzopp';
var num = 0; // 统计o出现的次数
var index = str.indexOf('o') //查找o第一次出现的位置
while (index !== -1) {
console.log(index);
num++
index = str.indexOf('o', index + 1)
}
console.log('o出现的次数:' + num)
</script>
思路如下
- 先查找第一个o出现的位置
- indexOf的索引只要不是-1,就一直往下查找
- indexOf只能查找第一个o,所以后面的索引一定要在当前的索引加1
根据位置返回字符串
charAt(index)
charAt(index)根据位置返回字符
<script>
var str = 'andy'
console.log(str.charAt(2)) //d 根据索引位置返回字符
</script>
charAt返回字符串的每一项
<script>
var str = 'YaoZiMo';
for (var i = 0; i < str.length; i++) {
console.log(str.charAt(i)) //打印字符串的每一项元素
}
</script>
charCodeAt()
根据位置返回相对应的字符串的ASCII码
<script>
var str = 'andy'
console.log(str.charCodeAt(2)) //100 根据索引位置返回相对应的字符ASCII码
</script>
str[index]:根据索引位置返回字符
<script>
var str = 'andy';
console.log(str[2]);
</script>
根据位置返回字符之案例
判断一个字符串’abcoefoxyozzopp’中出现次数最多的字符 并统计次数
- 核心算法:利用chrAt遍历这个字符串
- 把每个字符都存储给对象,若对象有这个属性,就进行加1,若没有该属性,就为1
- 利用遍历得到最大值和字符
<script>
var str = 'abcoefoxyozzopp';
var obj = {};
for (var i = 0; i < str.length; i++) {
var charts = str.charAt(i);
if (obj[charts]) {
obj[charts]++
} else {
obj[charts] = 1;
}
}
console.log(obj);
//声明一个变量max来统计出现的次数 变量ch来统计出现最大的字符 obj[k]是属性值 k是属性
var max = 0;
var ch;
for (k in obj) {
if (obj[k] > max) {
max = obj[k];
ch = k;
}
}
console.log('出现最多的次数:' + max);
console.log('出现最多的字符:' + ch);
</script>
字符串的其它方法
concat(str1,str2,str3)
concat:用于拼接两个或者多个字符串
<script>
var str = 'hello';
console.log(str.concat('word'));
</script>
substr(star,length)
从star的位置开始,截取的个数
<script>
var str = 'hello my name is china';
console.log(str.substr(2, 3)) //llo
</script>
replace(‘被替换字符’,‘替换后的字符’)
<script>
var str = 'hello hello'
console.log(str.replace('o', 'y'))
</script>
replace之案例
将下列字符串中的‘a’替换为‘b’
<script>
var str = 'aaccvricunrbeuaaaaaadeufban';
while (str.indexOf('a') !== -1) {
str = str.replace('a', 'b')
}
console.log(str)
</script>
字符串转换成数组
split(‘分隔符’)
将字符串转换成数组
<script>
var str = 'pink,blue,yellow';
console.log(str.split(','))
var str = 'hello&dark&yellow';
console.log(str.split('&'))
</script>