目录
预解析
JavaScript代码是由浏览器中的JavaScript解析器来执行的,JavaScript解析器在运行JavaScript代码的时候分为两步:预解析与代码执行;
预解析也叫变量提升,JavaScript引擎会把代码中所有的变量(var)以及函数(function)提升到当前作用域的最前面,因此预解析又分为变量预解析(变量提升)与函数预解析(函数提升)。
注意:变量提升只意味着将变量声明提升到当前的作用域最前面,但是变量赋值并未得到提升;如:
console.log(num); // 结果是undefined
var num = 10;
// 相当于执行了
var num;
console.log(num); // 因为只进行了声明,但是并未赋值,所以结果是undefined
num = 10;
对于函数提升意味着将所有的函数声明提升到当前作用域的最前面,并不调用函数;
而对直接定义的函数,则没影响,
fun1(); //
function fun1() {
console.log('函数提升方法~');
}
// 相当于执行了如下代码
function fun1() {
console.log('函数提升方法~');
}
fun1();
但是对通过函数表达式来说,就会报错:
fun1(); // 报错:fun1 is not a function
var fun1 = function() {
console.log('函数提升方法~');
}
// 相当于执行了如下代码
var fun1;
fun1(); // 所以报错
fun1 = function() {
console.log('函数提升方法~');
}
示例(示例还很重要):
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
// 相当于执行如下代码:
function f1() {
var a;
a = b = c = 9; // 由于bc未声明就被赋值,所以变为全局变量
console.log(a); // 9
console.log(b); // 9
console.log(c); // 9
}
f1();
console.log(c); // 9
console.log(b); // 9
console.log(a); // not defined
对象(Object)
对象定义
对象是一个具体的事物,是看的见摸得着的实物,如这个被我咬了一口的苹果,而苹果泛指则不是对象;
在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,如字符串、数值、数组、函数等;
属性:指事物的特征,在对象中用属性来表示(常用名词);
方法:指事物的行为,在对象中用方法来表示(常用动词);
对象可以用来表达一个事物的完整信息。
创建对象的三种方式
在JavaScript中,有三种方式创建对象:利用字面量创建对象、利用new Object创建对象、利用构造函数创建对象
- 利用字面量创建对象
利用一对花括号来创建对象;
里面的属性或方法采用键值对方式表示,键表示属性名 :值表示属性值;
多个属性或方法中间用逗号隔开;
方法冒号后面跟的通常是一个匿名函数;
调用对象的属性有两种方式:一种是使用对象名.属性名;另一种方法是使用对象名['属性名'];注意第二种方法中的方括号里面属性名要加引号;
调用对象的方法使用对象名.方法(); -------调用方法时一定不要忘记加小括号;
var obj = {}; // 创建了一个空对象
var obj1 = {
year: '2021',
mouth: '12',
day: '11',
getDay: function() {
console.log('今天是2021年12月11日~')
}
} // 创建了一个既有属性又有方法的对象obj1
console.log(obj);
console.log(obj1.year); // 调用obj1的属性1
console.log(obj1['year']); // 调用obj1的属性2
console.log(obj1.getDay()); // 调用obj1的方法
- 利用new Object创建对象
使用new Object()可创建一个空对象;
利用等号 = 赋值的形式添加对象的属性和方法;
每个属性和方法之间用分号结束;
对象调用与前一种方法一致;
var obj = new Object();
obj.year = '2021';
obj.mouth = '12';
obj.day = '11';
obj.getDay = function() {
console.log('今天是2021年12月11日!');
}
console.log(obj.year); // 调用对象属性1
console.log(obj['year']); // 调用对象属性2
obj.getDay(); // 调用对象方法
- 利用构造函数创建对象
因为前面两种创建对象的方式一次只能创建一个对象,所以当我们需要创建多个对象的时候就会使用构造函数,构造函数就是把对象里面一些相同的属性和方法抽象出来封装到函数里面;
官方说法:构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与new运算符一起使用,把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面;
语法格式如下:
function 构造函数名() {
this.属性 = 值;
this.方法 = function() {
// 方法体
}
}
var obj1 = new 构造函数名('属性值1', '属性值2', '方法1')
用this特指当前这个对象!
注意:
- 构造函数名字首字母要大写;
- 构造函数不需要return就可以返回结果;
- 调用构造函数,必须使用new;就可以创建一个独一无二的对象;利用函数创建对象的过程称为对象的实例化;
- 属性和方法前面必须添加this;
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
} // 构造函数
var ldf = new Star('刘德华', 18, '男'); // 创建对象
console.log(ldf.name);
ldf.sing('冰雨');
补充:变量、属性、函数、方法、new关键字的总结
变量:单独声明赋值,单独存在;
属性:对象里面的变量成为属性,不需要声明,用来描述该对象的特征;
函数:单独存在的,通过“函数名()”的方式调用;
方法:对象里面的函数称为方法,方法不需要声明,使用“对象.方法名()”的方式就可调用,方法用来描述该对象的行为和功能;
new在执行时会做四件事情:
- 在内存中创建一个新的空对象;
- 让this指向这个新的对象;
- 执行构造函数里面的代码,给这个新对象添加属性和方法;
- 返回这个新对象(所以构造函数里面不需要return);
- 遍历对象属性
利用for...in 对数组或对象的属性进行循环操作。
for (var k in 对象名) {
console.log(k); // 拿到属性名
console.log(obj[k]); // 拿到属性值
}
内置对象
JavaScript中的对象分为3种:自定义对象、内置对象、浏览器对象;
其中前两种对象是js基本内容,属于ECMAScript;
内置对象是js语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或是最基本必要的功能;主要介绍Math、Date、Array、String等
Math对象
Math对象不是构造函数(所以不用new一个对象),它具有数学常数和函数的属性和方法,跟数学相关的运算(求绝对值、取整、最大/小值)等都可以使用Math中的成员;
Math.PI; // 圆周率
Math.floor(); // 向下取整
Math.ceil(); // 向上取整
Math.round(); // 四舍五入,数值加上0.5,然后再向下(小的数)取整
Math.abs(); // 绝对值
Math.max(); // 最大值
Math.min(); // 最小值
Math.random(); // 在[0,1)取随机数,左闭右开
Date对象
Date是个构造函数,因此必须要用new创建对象;
var date = new Date(); // 对象实例化
console.log(date); // Sat Dec 11 2021 20:03:43 GMT+0800 (中国标准时间)
var year = date.getFullYear(); // 获取当年
var month = date.getMonth() + 1 ; // 获取当月,记住月份是从(0-11)获取;所以获取当月的方法要加1
var day = date.getDate(); // 获取当天日期
var week = date.getDay(); // 获取当天是周几(周日0-周六6)
var hour = date.getHours(); // 获取当前小时
var minute = date.getMinutes(); //获取当前分钟
var second= date.getSeconds(); //获取当前秒
console.log(year,month,day,week,hour,minute,second); // 2021 12 11 6 20 3 43
获取时间戳:
时间戳是指距离1970年1月1日过了多少毫秒数,由于时间戳是唯一的,经常用于标定文件的唯一性;有三种方法获取当前时间戳:
- 通过valueOf()或者getTime()方法;
- 通过+new Date();
- h5新增方法----Date.now();
var date = new Date(); // 不管干啥,先要构建Date对象
console.log(date.valueOf()); // 1639224675994
console.log(date.getTime()); // 1639224675994
console.log(+new Date()); // 1639224675994
console.log(Date.now()); // 1639224675994
Array对象
此处补充创建数组的两种方法:一种是用字面量方法创建,即
var array = [1,2,3]
第二种,则是通过new Array()方式,
var arr1 = new Array(); // 创建了一个空的数组
var arr2 = new Array(2); // 表示创建了一个长度为2的空数组
var arr3 = new Array(2, 3); // 等价于[2, 3]表示array3里面有两个数组元素,即2,3
注意Array()括号中的内容只有两个以上才表示是数组内容,若只有一个,则代表的是数组的长度;
数组对象中有如下提供的API方法:
检测是否是数组:Array.isArray()和instanceof
Array.isArray() // 用于确认传递的参数是否是一个数组
Array.isArray('Array') // false 'Array'是一个字符串
Array.isArray([1,2,3]) // true [1,2,3]是一个数组
var arr = [1,2,3];
var str = '123';
console.log(arr instanceof Array); // true
console.log(str instanceof Array); // false
Array.isArray
能检测 iframes
添加/删除数组元素:push()、pop()、unshift()、shift()
push() 在数组的末尾添加一个或多个数组元素;
var arr = ['小明', '小红', '小丽'];
console.log(arr); // ['小明', '小红', '小丽']
console.log(arr.push('小美')) // 4 arr.push返回追加后的数组长度
console.log(arr); // ['小明', '小红', '小丽', '小美'] 新数组已被追加长度
即push方法返回的是追加后的新数组的长度;参数里面写的是要追加的数组内容;
unshift()是在数组的开头添加一个或多个数组内容,和push方法一样,返回的是追加后的新数组的长度,参数里面写的是要追加的数组内容;
var arr = ['小明', '小红', '小丽'];
console.log(arr); // ['小明', '小红', '小丽']
console.log(arr.unshift('小华')); // 4
console.log(arr); // ['小华', '小明', '小红', '小丽']
pop()方法用于删除数组的最后一个元素,且每次只能删除一个元素,括号中无参数
var arr = ['小明', '小红', '小丽'];
console.log(arr); // ['小明', '小红', '小丽']
console.log(arr.pop()); // 小丽
console.log(arr); // ['小明', '小红']
pop()方法返回的是被删除的数组元素内容;
相反,shift()方法用于删除数组的第一个元素,也是每次只能删除一个元素,括号里面无参数,
var arr = ['小明', '小红', '小丽'];
console.log(arr); // ['小明', '小红', '小丽']
console.log(arr.shift()); // 小明
console.log(arr); // ['小红', '小丽']
shift()方法返回的是被删除的数组内容;
数组排序:reverse()、sort()
reverse()方法会颠倒数组中元素的顺序,括号内无参数,返回一个改变顺序的新数组;
var arr = ['小明', '小红', '小丽'];
console.log(arr); // ['小明', '小红', '小丽']
console.log(arr.reverse()); // ['小丽', '小红', '小明']
console.log(arr); // ['小丽', '小红', '小明']
sort()方法会对数组的元素进行排序,但是有些瑕疵,会一位一位的进行排序;
var arr = [1, 2, 23, 3];
arr.sort();
console.log(arr); // [1, 2, 23, 3] 会先排第一位,再排第二位...
var arr = [1, 2, 0, 3];
arr.sort();
console.log(arr); // [0, 1, 2, 3]
sort排序原理采用冒泡排序,返回值规则如下:
- 当返回值为负数时,那么前面的数在前面,也就是不动
- 当返回值为正数时,那么后面的数在前
- 为0,不动
改进如下:
- 升序排序
var arr = [1, 2, 23, 3];
arr.sort(function(a, b) {
return a - b;
})
console.log(arr); // [1, 2, 3, 23]
其实是以下代码的简写形式:
arr.sort(function(a,b){
if(a>b){
//返回正数 b就和a位置互换,小的在前面了
return a-b;
}else{
//返回负数
return a-b;
}
})
- 降序排序
var arr = [1, 2, 23, 3];
arr.sort(function(a, b) {
return b - a;
})
console.log(arr); // [23, 3, 2, 1]
其实是以下代码的简写形式:
arr.sort(function(a,b){
if(a<b){
//返回正数 b就和a位置互换,大的在前面了
return b - a;
}else{
//返回负数
return b - a;
}
})
数组索引方法:indexOf()、lastIndexOf()
indexOf() 用于数组查找给定元素的第一个的索引,若存在该元素内容,则返回该元素的索引号,若不存在,则返回-1;
var arr = [12, 13, 24, 'one', 'three', 12, 13, 13];
console.log(arr.indexOf(12)); // 0 返回的是第一个12的索引值,而非后面12的索引值
console.log(arr.indexOf('one')); // 3
lastIndexOf() 用于数组查找给定元素的最后一个的索引,若存在该元素内容,则返回该元素的索引号,若不存在,则返回-1;
var arr = [12, 13, 24, 'one', 'three', 12, 'three', 13];
console.log(arr.lastIndexOf(12)); // 5 返回的是后面12的索引值
console.log(arr.lastIndexOf('three')); // 6
数组转换为字符串:toString()、join('分隔符')
toString()方法将数组转换为字符串,结果返回一个以逗号分隔每一项的字符串;
var arr = [12, 13, 24, 'one', 'three', 12, 'three', 13];
console.log(arr.toString()); // '12,13,24,one,three,12,three,13' 以逗号分给每个元素
join('分隔符')方法用于把数组中的所有元素以参数中的分隔符隔开,返回一个字符串,若不加参数,则默认以逗号分隔开;
var arr = [12, 13, 24, 'one', 'three', 12, 'three', 13];
console.log(arr.join()); // '12,13,24,one,three,12,three,13'
console.log(arr.join('-')); // '12-13-24-one-three-12-three-13'
console.log(arr.join('')); // '121324onethree12three13'
console.log(arr.join('&')); // '12&13&24&one&three&12&three&13'
数组连接:concat()
用于连接两个或多个数组,结果返回一个新数组;不影响原来的数组;
var arr = [12, 13, 24, 'one', 'three', 12, 'three', 13];
var arr1 = arr.concat([1, '4', 3])
console.log(arr); // [12, 13, 24, 'one', 'three', 12, 'three', 13] 未影响原先的数组内容
console.log(arr1); // [12, 13, 24, 'one', 'three', 12, 'three', 13, 1, '4', 3]
String对象
基本包装类型:即将简单的数据类型包装成为复杂数据类型,这样就使基本数据类型有了属性和方法;如String/Number/Boolean,所以字符串才会有长度length;
字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串。
查找字符串中字符位置indexOf()/lastIndexOf():
indexOf('要查找的字符',开始查找的位置):返回要查找的字符在字符串中的第一个的位置,找不到则返回-1;
lastIndexOf('要查找的字符'):返回要查找的字符在字符串中最后一个的位置,找不到则返回-1;
var str = '1222stre';
console.log(str.indexOf('2', 1)); // 1
console.log(str.lastIndexOf('2')); // 3
console.log(str.indexOf('3')); // -1
根据字符位置返回对应字符charAt(index)/charCodeAt(index)/str[index]:
charAt(index):返回指定位置对应的字符
charCodeAt(index):获取指定位置处字符的ASCπ码
str[index]:获取指定位置对应的字符
var str = 'goodgoodstudy';
console.log(str.charAt(3)); // d
console.log(str.charCodeAt(3)); // 100
console.log(str[3]); // d
连接字符串concat():
concat()方法用于连接两个或多个字符串,即拼接字符串,但不如+省事;生成一个新字符串;
var str1 = 'good';
var str2 = 'good';
var str3 = 'study';
var str = str1.concat(str2, str3)
console.log(str); // goodgoodstudy
取子串substr(start,length)、slice(start, end)、substring(start,end)
substr(start,length)方法用于从start位置开始去length个数的子串;返回截取后的子串,
var str = 'goodgoodstudy';
console.log(str.substr(0, 4)); // good
console.log(str); // goodgoodstudy
slice(start, end)从start位置开始,截取到end位置(左闭右开);start和end都是指索引号;
var str = 'goodgoodstudy';
console.log(str); // goodgoodstudy
console.log(str.slice(0, 3)); // goo
substring(start,end)从start位置开始,截取到end位置(左闭右开);start和end都是指索引号;他和上面的方法区别是substring不接受负值
var str = 'goodgoodstudy';
console.log(str); // goodgoodstudy
console.log(str.substring(0, 3)); // goo