JavaScript知识梳理
- JavaScript到底可以做什么
- 应用程序接口(API)
- 声明变量(var/let)
- 变量名命名规则
- 数据类型(6种)
- JavaScript弱类型机制
- 数据类型检测(typeof关键字)
- 数据类型转换
- JavaScript运算符
- JavaScript语句(流程控制语句)
- JavaScript函数
- 数组(array)
- JS面向对象
JavaScript到底可以做什么
- 在变量中存储有用的值
- 操作一段文本(在编程中成为“字符串”)
- 运行代码以响应网页中发生的特定事件
应用程序接口(API)
是已经建立好的一套代码组件,可以让开发者实现原本很难甚至无法实现的程序
API分类
- 浏览器API
文本对象模型API(DOM)
地理位置API(Geolocation API)
画布(Canvas)和 WebGI API - 第三方API
声明变量(var/let)
var 和 let 的区别
var可以多次声明相同的变量,let不行
var a="hello";
var a="world";
__
let b="hello";
b="world";
只定义不赋值则值为undefined(未定义)
变量名命名规则
- 以字母开头、或下划线、$开头,后可接任意字母、下划线、美元符号或数字。不能以数字开头。
- 不能是系统中的关键字或保留字
- 见名知意
- 采用小驼峰命名法,若是一个组合单词(firstStudent)
数据类型(6种)
1. 字符串(String)
var text=""; (引号不分单双)
2. 数字类型(Number)
· 在js中只有number没有int之类的区分
· 所有无法用阿拉伯数字表示的Number类型都用NaN表示
3. 布尔类型(Boolean)
4. 未定义类型(undefined)
在计算机内存中不存在
5. 空类型(null)
在计算机中占一个空间,但内容为空
6. 对象
一个对象中往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器
var user={
name:"",
age: ,
}
JavaScript弱类型机制
在js中,变量会根据赋值的数据类型而变化类型
数据类型检测(typeof关键字)
typeof 变量名; | typeof(变量名);
特别注意
对象返object,数组返object,undefined返undefined,null返object
数据类型转换
转十进制数字
一、字符串(必须是数字字符串)
var a=“123” ; | var b=“abc123”; |
var c=“123abc”; | var d=“123.123”; |
var e=“-123”; | var f=“hello”; |
Number()
Number(a) | 123 | Number(b) | NaN |
Number© | NaN | Number(d) | 123.123 |
Number(e) | -123 | Number(f) | NaN |
只能转换合法数字字符串,当字符串中包含非数字的字符时,转为NaN
parseInt()
parseInt(a) | 123 | parseInt(b) | NaN |
parseInt© | 123 | parseInt(d) | 123 |
parseInt(e) | -123 | parseInt(f) | NaN |
可将字符串转为整体的
- 以非字符串字符开头的转为NaN
- 以数字字符开头的,从第一个非数字字符开始全部丢弃
- 有小数点的,将小数点后面全部丢弃,不四舍五入
parseFloat()
和parseInt()一样,小数点后面的数字保留
二、布尔类型
true | Number(true) | 1 |
flase | Number(false) | 0 |
三、null和undefined
Number(null) | 0 |
Number(undefined) | NaN |
其他类型转字符串(直接加引号)
一、String()
直接按字面量转换
二、直接将这个变量加一个空字符串
var a1=a+"";
三、toString()
var str=a.toString();
不能转换空和未定义
其他类型转换布尔类型
Boolean()
在整个体系中,只有6个值(0,空字符串,false,NaN,null,undefined)能被描述成false
数字间的进制转换
1.十进制转其他
toString(进制数)
转16进制要在结果前加ox
2.其它进制转其他
parseInt(原来的数字,原来的进制)
JavaScript运算符
一元操作符
只能操作一个值的操作符,一元运算的操作结果一定是个Number类型
1.递增递减操作
a++; 先输出后调用
++a; 先调用后输出
2.特殊类型值的递增递减
- 一元操作符的结果一定是Number类型
- 非数字类型数据会先进行Number()操作
- NaN不参与操作,即使参与,结果也是NaN
3.一元加减运算(a=+a;a=-a;)
- 结果一定是Number类型
- 非数字类型的数据通过Number()
- NaN不参
- 如果是一元减法运算,选Number()后乘以-1
var a=1;
a=!a; //false
a=+!a; //0
var b=0;
b=!b; //true
b=+!b; //1
加法运算
-
如果执行加法有字符串,则结果是一个拼接字符串
-
NaN不参与运算,参结果一定是NaN
-
对非数字类型,使用Number()
字符串>NaN (加法字符串优先)
减法运算
- 结果一定是number类型
- NaN和任何值减都是NaN
- 若不是数字,则Number()
乘法运算
和减法运算原则保持一致
除法运算
和减法操作保持一致
(如果除以0,则最终结果为Infinity无穷大)
取余(取模)运算
遵减法操作原则(除数为0,则结果为NaN)
幂运算(**)
5**5相当于55555
逻辑运算
运算符 | 结果是否为布尔值 | 补充 |
---|---|---|
非(!) | 是 | 如果操作的值不是布尔值,则Boolean() |
与(&&) | 不一定 | 一假则假(短路原则:遇false停,取false,全true取最后) |
或(两个竖杠) | 不一定 | 一真全真(短路原则:遇true停,取true。全false取最后),若不为布尔值,则Boolean() |
先非再与最后或
比较运算
若比较双方并不是数字,则比较字符的ASCII码值
运算符 | 名称 | 作用 |
---|---|---|
=== | 严格等于 | 测试左右值是否相等 |
!== | 严格不等于 | 测试左右值是否不相等 |
</> | 小于/大于 | |
<=/>= | 小于等于/大于等于 |
JavaScript语句(流程控制语句)
if语句
如果条件不为布尔值,则Boolean()
if(可以得到任意数据类型结果的表达式){
true时执行;
}else{
false时执行;
}
for循环语句
for(初始值;循环条件;自变量){}
while循环
初始值;
while(循环条件可以为任意数据类型值){循环体;}
do…while循环语句
初始值;
do{循环体;}while(循环条件)
break和continue
break:中断最内部的循环,退出最外部循环,后面的循环次数不做
continue:跳出当前循环的次数不执行,执行后面的
label语句
break outer;
一般使用于循环的嵌套中,当内部循环使用break|continue时跳出的是内循环,这是使用label语句跳出外部循环(将break改成label语句便可实现)
switch语句
switch中的break不写的话,switch会选择一个符合的case执行,但不会停止,一直到default停止。
JavaScript函数
一个封装任意多条执行语句的过程
1.函数定义function
用typeof检测的结果是function
function 函数名(参数,...){
//函数体
}
另一种定义方法:函数表达式
var 函数名=function(){
//函数体
}
//调用的时候会报错:函数名is not a function
2.函数调用
函数名();
//函数名为调,括号为用
3.函数重载
JavaScript不存在重载,当出现同名时会覆盖
原因:js是弱类型语言,变量未赋值前都是undefined,不能通过类型来区分,也不能通过参数个数区分
4.返回值
return 参数;
当return不接值的时候可用来跳出函数
5.递归函数
自己内部调自己,类似循环
6.变量的作用域
局部变量不能被跨域调用,局部变量只有在函数被调用的时候才会被声明调用,函数执行完毕后会被垃圾回收机制释放掉,保障了数据的安全性。
通过var定义的变量是没有所谓的“块级作用域”:
{var a=123; //全局变量}
但function的大括号会形成作用域
function abc{var a=123; //局部变量}
7.函数的参数
形参:定义时括号里的
实参:调用时括号里的
function add(a,b){
var num=a+b;
return num;
}
var x=add(1,2); //3
var y=add(1,2,3); //实参>形参 3
var z=add(1); //实参<形参 NaN
arguments实参数组
该arguments并不是一个数组,而是一个类数组(具备数组特征,但不具备数组方法)的概念
function add(a,b){
console.log(a); //a
console.log(b); //b
console.log(argument[2]); //c
}
add(a,b,c);
数组的基槽方法 | 索引属性length | |
---|---|---|
array | 有 | 有 |
arguments | 无 | 有 |
arguments只能在函数体内使用,一个函数体只有一个arguments
8.立即执行函数
不用调用直接执行,在函数前加上 !/+,后面加上();
var username="lisi";
var x=! function abc(){
userName="zhangsan";
console.log(userName);
return userName;
}();
console.los(x);
//zhangsan
//false
立即执行函数不能返回内部的值到外面
数组(array)
在JavaScript中,数组长度和所存储的类型不强制
1.数组的定义
var arr=new Array();
不存放为空,存放单个数字为length,多个为静态化创建
var arr=[];
直接放值或为空
2.数组的检测
(1)instanceof
通过关键字右边设置的类型来判断左边的是否为该类型
arr instanceof Array; //true|false
(2)Array.isArray()
var a=[1,2,3];
var b=new Array();
Array.isArray(a); //true
Array.isArray(b); //true
3.方法
方法名 | 含义 | 返回值 |
---|---|---|
lenght | 数组长度 | 后无括号 |
push() | 向数组后面添加元素 | 长度 |
pop() | 从数组中移除最后一个元素 | 被删除元素 |
unshift() | 向数组前面添加元素 | 长度 |
shift() | 从当前数组最前溢出一位元素 | 该元素 |
concat() | 将多个数组拼接成一个新数组,原数组不变 | |
slice() | 截取数组 | 一个新数组 |
arr.slice(a,b)从a开始b结束截取/arr.slice()复制arr | ||
reverse() | 翻转 | 新数组 |
toString() | 将数组中的元素转换为字符串,每个元素之间用逗号相连 | |
join() | 用指定符号隔开数组元素并转换为字符串 | arr.join(字符) |
include() | 判断数组是否具备指定元素 | boolean |
splice()
指定位置删除指定个数元素/放入指定个数元素,返回删除的元素组成的数组
- arr.splice(1,2) 索引1的位置删除2个元素
- arr.splice(1,0,“a”,“b”) 索引1的位置加元素
- arr.splice(1,1,“a”,“b”) 索引1的位置删1个元素加两个元素
特殊情况:
- arr.splice(1) 从1删到尾
- arr.splice(-2) 从倒数第二个删到尾
- arr.splice(1,-1) 保持不变
- arr.splice(1,“a”) 保持不变
- arr.splice(1,“1”) 将字符串1转为数字1
删除当前数组的奇数项
var arr=[1,2,3,4,5];
for(var i=0;i<arr.length;i++){
if(arr[i]%2==1){
arr.splice(i,1);
i--; //splice会缩短lenght
}
}
cosole.log(arr);
indexof()
查位置,返索引,无返-1
indexof在查找中执行的是全等操作,强判断,只能查出基础数据类型(String,number,boolean),只会查到遇到的第一个
indexof(元素,索引值),从指定位置开始查
lastIndexof()
查最后一次出现的位置,返索引,无返-1
4.数组的迭代方式(遍历)
- 不能使用break和continue来中断遍历
- 所有遍历都是静态遍历
(1).for循环遍历
(2).forEach()
var arr=["a","b","c"];
arr.forEach(function(item,index,_arr){
console.log(item,index);
})
item:当前遍历的这一项
index:item的索引
_arr:正在遍历的数组
(3).map()
将每次迭代的返回值接收下来组成一个新数组
var arr=[a,b];
var newArr=arr.map(function(item,index,_arr){
console.log(item,index);
var x=item*2;
return x;
})
console.log(newArray); //[2a,2b]
(4).filter()
在原数组中符合条件的元素组成数组返回出来
var arr=[a,b];
var evenArr=arr.filter(function(item,index,_arr){
//这里返回一个条件,原数组根据该条件返回符合值
return item%2===0;
})
console.log(evenArr);
通过该方法可快速查重:
var arr=[...];
var noRepeatArr=arr.filter(function(item,index,_arr){
return index==_arr.indexof(item);
//该index为该元素的index,_arr.indexof(item)从第一个出现item的位置
(5).every()
对arr里每个元素进行遍历,回调函数返回一个条件,根据该条件决定返回的结果是true还是false,再执行一个&&
var arr=[...];
var result=arr.every(function(item,index,_arr){
return item>10;//判断arr里的元素是否每个都大于10
//进行&&运算返回boolean
})
console.log(result);
(6).some()
和every()一样,只不过最后执行||(或)
5.数组的归并方法
(1)reduce()
var result=arr.reduce(function(pre,current,index,_arr){
//代码
//求和:
//var num=pre+current;
//return num;
})
参数 | 含义 |
---|---|
pre | 前一个的回调函数的返回值(本次回调函数返回值会被下一个pre使用) |
current | 当前遍历的这一次的值(reduce是从数组的第二个开始) |
index | 当前遍历索引 |
_arr | 正在操作的数组 |
result | 最后一次回调函数返回值 |
(2)reduceRight()
和reduce一样,只不过是从右边开始遍历
6.排序方法sort()
将当前数组进行重新排序,返回一个新排序的数组
var arr=[...];
arr.sort(function(a,b){ //定义排序规则的回调函数
if(a<b){
return -1; //a在b前
}else if(a==b){
return 0; //不变
}else if(a>b){
return 1; //a在b后
}
//return a-b; 从小到大
//return b-a; 从大到小
})
console.log(arr);//得到一个经过重新排序的数组
7.二维数组
js中无二位数组的概念,只有多维数组的概念,js数组不限制数据类型,不限制长度
8.多维数组遍历
var stus=[
["a","b","c","[d,e]"],
[1,2,3],
"f",
["g",[["h","i"],"j"],"k"]
]
function printArr(arr){
for(var z=0;z<arr.lenght.lenght;z++){
if(Array.isArray(a[z])){ //a[z]是否是数组
printArr(a[z]); //如果是数组再遍历
}else{
console.log(a[z]); //知道单个元素输出
}
}
}
printArr(stus);
JS面向对象
一、对象具备的特点
- 具备属性(用于描述当前对象的特征)
- 具备方法(对象的功能)
- 可以继承(父的方法和属性,子可以继承)
二、创建对象(对象的封装)
1.通过键值对创建
var 对象名={
属性:属性值,
key:value,
...
}
如何在对象中创建方法并拿到当前对象的属性
var stu={
name:"张三";
sayHello1:fuction(){
console.log(stu.name);
}
sayHello2:fuction(){
console.los(this.name);
}
}
//该方法中的name一发生改变则均发生改变,不好
2.通过object创建
var obj=new Object(); //创建对象
obj.name=""; //向对象添属性和方法
obj.sayHello=function(){...}
3.使用构造函数创建对象
var 对象名=new 函数(); //函数以大写字母开头
带参构造:
function Student(name,age){
this.name=name;
this.age=age;
this.sayHello=function(){
console.log("i am"+this.name);
}
}
var stu=new Student("YY",20);
无参构造:
function Abc(){
console.log("Hello");
}
new abc();
4.工厂模式创建对象
function creatStudent(name,age){
var obj={
name:name,
age:age
};
return obj;
}
var stu=creatStudent("YY",20);
三、构造函数与普通函数的区别
- 构造函数new来调用,普通函数()调用
- 构造函数返回值为对象,普通函数返回值由return决定
- 构造函数this指向创建的对象,普通this指向window对象
- 构造函数若无实参,执行时可不要小括号,如:new abc;
四、构造函数与工厂模式的区别
构造函数:
var stu=new Student(...);
stu instanceof Student ; //true
工厂模式
var stu=creatStudent(...);
stu instanceof Object; //true
五、对象属性调用
一般属性:
stu.name | sayHello();
特殊属性名:
console.log(stu[1] | stu["a-b"]);
六、Object.defineProperty()定义对象属性
1.数据属性
数据属性包含一个数值的位置,可以在这个位置写入或读取数值。有四个描述写具体行为的特征
var stu={};
//添加特殊数据属性
Object.defineProperty(stu,"name",{
configurable:true;
//表能否通过delete删除该属性,或能否改为访问器属性,默认true
enumerable:false;
//表能否通过for...in循环遍历返回该属性,默认false
//for(var i in stu){
//console.log(i);
//}
writable:true;
//表能否修改属性的值,默认true
value:"张三";
//该属性的数据值,默认undefined
})
2.访问器属性
-
configurable:
-
enumerable:
-
Get:
在读取属性的时候调用的函数,默认undefinedget:function(){ return "你正在读取name属性" },
-
Set:
在写入属性的时候调用的函数,默认undefinedSet:function(v){ //v为要赋的值 console.log("你正在对name赋值,赋值"+v); }
(1)访问器属性不能直接定义,只能使用object.defineProperty()来定义
(2)get()主要针对取值的时候进行属性取值的控制,set()针对赋值的时候对赋值操作进行控制
(3)未写set()表示该属性只能读取不能赋值
七、Object.defineProperties()定义对象属性
Object.defineProperties(stu,{
name:{},
age:{},
})
八、构造函数与特殊属性相结合
//先定义构造函数
function person(name,birthday){
//定义对象属性
Object.defineProperties(this,{
name:{},
birthday:{},
age{},
})}
var person1=new Person("张三","2001-10-20");
console.log(person1.age);
九、对象的遍历
1.for…in (enumerable:true)
for( var 变量 in 对象){
document.write(变量);
}
无序输出,若对象属性值为null或undefined,会报错或不执行循环体
2.Object.keys() (enumerable:true)
Object.keys(对象)会将对象里面所有可以遍历出来的属性拿出来组成一个数组返回出来
3.Object.getOwnPropertyNames() (enumerable:true|false)
获取对象的所有属性名arr
十、判断对象是否具备某一属性
- 遍历判断
- in关键字
“name” in stu; //true|false - 继承来检测
stu.hasOwnProperty(“name”); //true|false
十一、对象与对象之间的关系
(1)继承
1. 通过call/apply来继承
① apply和call都是用来修饰函数中this的指向问题
② call()可将传给该函数的参数分别作为自己的多个参数,apply()将传给该函数的参数合并成一个数组作为自己的一个参数
var name="Pig";
var age=20;
var person={
name:"Cat",
age:19,
dayIntroduce:function(){
return "i am" + this.name+",age" + this.age;
}
sayHobby:function(val1,val2){
return "i am" + this.name + ",i like" + val1 + "and" +val2;
}
}
var person1={
name:"Dog"
}
console.log(person.sayIntroduce()); //i am Pig,age 20
//不传参数时,this指向windows
console.log(person.sayIntroduce.call()); //i am Pig,age 20
console.log(person.sayIntroduce.apply()); //i am Pig,age 20
//传参数时,this指向第一个参数
console.log(person.sayIntroduce.call(person())); //i am Dog,age undefined
console.log(person.sayIntroduce.apply(person())); //i am Dog,age undefined
//传参数时,call可写多个参数,apply需用数组传
console.log(person.sayHobby.call(person1,"swimming","hiking")); //i am Dog,like swimming and hikking
console.log(person.sayHobby.apply(person1,["swimming","hiking"])); //i am Dog,like swimming and hikking
2. 通过原型来实现继承
在JS面向对象中,一个对象原型中__proto__等于这个对象的构造函数prototype
s1.__proto__==Student.prototype; //true
function Person(){
this.sayHello(){
console.log("i am"+userName);
}
}
function Student(userName){
this.userName=userName;
}
//让Student继承Person
var s=new Student("张三");
//第一种方式
s.__proto__=new Person();
s.sayHello();
//第二种方式
Student.prototype=new Person();
function Student(userName){
this.__proto__=new Person(userName);
}
- 要想实现继承,在子对象的构造函数中,将this._ _ proto _ _赋值父对象的构造函数的执行
- 父对象的构造函数中需传的参数,全部添加到子对象的构造函数中
(2)包含
一个对象包含其他对象
十二、this指向
(1)对象中this:
-
全局环境下,指向window
this.name==window.name
-
自定义对象中指向调用该方法的对象
(2)构造函数中this
- Person();
指向window - new Person();
指向当前创建的对象
(3)call()/apply()
手动改变指向
(4)bind()
调用的时候不会立即执行原来的方法,而是会返回一个新的方法名,通过新的方法名再去调用原方法
var name="张三";
function abc(a,b){
console.log(this.name,x,y);
}
var stu={...};
var a=abc.bind(stu,90,15);
a();
var b=abc.bind(stu);
b(90,15);
//this指向stu对象
十三、内置对象
Math对象
(1).常数
Math.PI | 圆周率 | 3.14 |
Math.E | 自然对数的底数 | 2.718 |
Math.LN10 | 10的自然对值 | 2.302 |
Math.LN2 | 1的自然对值 | 0.693 |
Math.SQRT2 | 2的平方根 | 1.414 |
Math.SQPT1_2 | 0.5的平方根 | 0.707 |
(2).方法
方法 | 含义 | 注解 |
---|---|---|
Math.abs() | 绝对值 | |
Math.round() | 四舍五入 | 求整 |
Math.floor() | 向下取整 | 返回小于或等于这个数的最大数,Math.floor(99.2);//99 |
Math.ceil() | 向上取整 | Math.ceil(); //100 |
Math.pow(x,n) | 取x的n次方 | |
Math.max() | 求最大值 | |
Math.max.apply(Math.arr) | 取数组最大 | |
Math.min() | 取最小值 | |
Math.sqrt(n) | 取数字n的平方根 | |
Math.random() | 取0-1中的随机数 |
Date对象
var time=new Date(//"2020-5-1 12:44:22");
方法:
方法 | 含义 |
---|---|
Date.now() | 返回1970-1-1到现在的毫秒数 |
getFullYear() | 获取当前年份 |
getMonth() | 获取当前月份,月份从0开始 |
getDate() | 日 |
getDay() | 星期几 |
getHours() | |
getMinutes() | |
getSeconds() | |
getMilliseconds() | 获取毫秒 |
get获取,set设置 | |
toString() | 将日期转换为字符串 |
toDateString() | 只转换日期 |
toTimeString | 只转换时间 |
toLocaleString() | 转换为本地时间 |
toLocalDateString()/toLocaleTimeString() | |
toGMTString() | 将当前时间转换为0时区的时间 |
获取两个时间的年份差
d1=new Date(...);
d2=new Date(...);
var totalTime=d2-d1; //获得时间戳(毫秒差)
var yearCount=parseInt(totalTime/1000/60/60/24/365); //转换
包装对象
String字符串对象
var str="hello";
---------------
var str=new String("hello");
方法
方法 | 含义 |
---|---|
length/str[0] | |
concat() | 破解(可用“+”实现) |
slice() | 和数组一样,截取 |
subString() | 专属于字符串的slice() |
subStr() | 截取字符串,传两个参数(开始索引,长度) |
indexOf()/lastIndexOf() | 查第一次/最后一次出现的位置,返回索引 |
splice() | 将字符串隔开成一个数组,与join()相反 |
charAt(index) | 通过索引来获取字符串中的字符 |
charCodeAt(index) | 通过索引获取字符串中某个字符的unicode编码 |
startsWith() | 判断某个字符串以什么开头 |
endWidth() | 判断某个字符串以什么结尾 |
includes() | 判断是否包含某个字符串,返回boolean |
trim()/trimLeft()/trimRight() | 去除字符串两边/左边/右边空格 |
replace() | 替换字符(就近原则)var str=“hello”;str.replace(/e/g,“o”); //hollo |
toUpperCase()/toLowerCase() | 返大小写转化后的字符 |
anchor | 锚方法,生成一个a标签html代码(var s=“hello”;s.anchor(“xx”); //hello) |
big()/small() | 把字符串放到对应标签(var s=“hello”;s.big(); //hello) |
padStart/padEnd(位数,字符) | 指定字符位数补齐 |
Number对象
方法 | 含义 |
---|---|
toString() | 转字符 |
toFixed() | 将数字转字符串,可四舍五入保留指定位数小数(var num=123.456;num.toFixed(2); //123.46) |
Boolean()
toString()