有一些很基础的就不重温了,主要记录一些比较会忘记,较难理解的,或者常用的内容
一、类型
常量 const PI=3.1415926
js是一种弱类型脚本语言,不需要明确申明变量类型
var num=3; //es5写法,结尾可以不写分号,但建议写上
let num=3; //es6写法,解决变量“红杏出墙”的问题,建议这种写法
变量类型,用typeof(变量)可以得到变量类型。
undefined
string
number
boolean
function
object
1)undefined
表示还无法确认类型,声明了变量,但尚未赋值,还不知道变量的类型
let v1;
console.log(typeof(v1)); //undefined
console.log(typeof(undefined)); //undefined
2)object
console.log(typeof(null)); //object,null并不是一种类型,而是一个值
3)基础类型
typeof("123"); //string
typeof(123); //number
typeof(true); //boolean
typeof(Object()); //object
typeof({a:1,b:"2"}); //object
typeof(function() {alert("123")}); //function
typeof(()=>alert("123")); //function
typeof([]); //object //数组也是对象
typeof([1,2,3]); //object //数组也是对象
4)模板字符串
es6的字符串新增加内插值的写法,与c#有类似之处,即把变量插入到字符串中
let a="hello";
let b=`${a} world!`; //键盘左边数字1键的旁边那个
console.log(b); //hello world~
5)数值转换
转数值有3个函数:Number(),parseInt(),parseFloat()转换成功后的类型都是number
Number("123") ; //123
Number("123.5") ; //123.5
Number("123a") ; //NaN
parseInt("123") ; //123
parseInt("123.5") : //123
parseInt("123a") : //123
parseFloat("123") : //123
parseFloat("123.5") : //123.5
parseFloat("123a") : //123
可以看到Number的转换比较严格,而parse转换会丢弃非数字字符
忠告:不要试图用js来计算小数
数值判断方法
isNaN(NaN=Not a Number)判断是否数值
isFinite方法返回一个布尔值,表示某个值是否为正常的数值。
6)是否整型 Number.isInteger
Number.isInteger(1); //true
Number.isInteger(1.2); //false
7)base64转码
//base64互转
console.log("hello转base64:" btoa("hello")); //aGVsbG8=
console.log("aGVsbG8=转普通字符:" atob("aGVsbG8=")); //hello
二、运算符
1)=>
es6新的箭头符号=>,很像c#的写法,或者说c#借用了js的写法?
function fn(){
alert("hello world!");
}
简化写法
let fn=()=> { alert("hello world!") }
let arr=[1,2,3,'a','b','c']
arr.forEach(x=>{
console.log(x);
});
2)链判断运算符?.
是否null,如果是null取??后面的值
let obj={hasVal:"abc",noVal:null}
console.log(obj?.hasVal??"空值"); //abc 因为obj.hasVal有值,显示值abc
console.log(obj?.noVal??"空值"); //空值 因为obj.noVal为null,所以显示默认值-空值
console.log(null??"空值"); //空值
3)in
判断key是否存在对象中
let obj={username:"jasonlee",age:18}
console.log("age" in obj); //true
console.log("x" in obj); //false
4)严格比较===
js是弱类型,所以1=="1"的事件会发生,但是判断绝对相同,可以使用===
console.log(1=="1"); //true
console.log(1==="1"); //false
三、数组
本质上,数组属于一种特殊的对象。typeof运算符会返回数组的类型是object。
在前后端的数据交互时,数组会用得比较多!
1)数组定义
let arr1=[];
let arr2=[1,2,'a'];
let arr3=new Array();
2)多维数组
let arr1=[[],[]]; //二维数组
let arr2=[[[],[]],[]]; //三维数组
let arr2[0][0][0]="a" //赋值
3)数组下标
下标非常的灵活,可以把字符串也看成数组
"123abc"[3] //"a"
[1,2,'a'][0] //1
4)数组的添加和移除
var arr=[1,2];
从末位追加一个元素push
arr.push('a'); //[1,2,'a']
从末位称除一个元素pop
arr.pop(); //[1,2]
从第一位添加一个元素
arr.unshift(0); //[0,1,2]
从第一位移除一个元素
arr.shift(); //[1,2]
从任意下标增加一个或者多个元素 splice
arr.splice(起始下标,要移除的位数,要添加的数据)
arr.splice(2,0,'b','c'); //1,2,'b','c'
删除一个元素
arr.splice(0,1); //移除首位元素
arr.splice(3,1); //移除任意位置的元素
let index=lstMail.findIndex(x=>x.Value==rowData.user_email);
lstMail.splice(index,1); //找到下标并删除
清空数组
arr.splice(0,arr.length);
5)数组转字符串 join
arr.join(','); //1,2,a
6)数组合并 concat
let arr1=[1,2,3]
let arr2=['a','b','c']
let arr3=arr1.concat(arr2);
console.log(arr3); //1,2,3,'a','b','c'
7)颠倒排序 reverse
console.log(arr3。reverse()); //'c','b','a',3,2,1
8)排序 sort
console.log("顺序:[1,3,7,0,9].sort():",[1,3,7,0,9].sort());
console.log("逆序:[1,3,7,0,9].sort((a,b)=>b-a):",[1,3,7,0,9].sort((a,b)=>b-a));
9)去重 Set
let arr=[];
arr.push(1);
arr.push(2);
arr.push(3);
arr.push(1);
let setNoRepeat=new Set(arr);
console.log(setNoRepeat); //[1,2,3] 注意,他的原型(Prototype)是Set
//转成数组
let arrNoRepeat=Array.from(setNoRepeat);
arrNoRepeat.forEach(x=>{console.log(x)});
上面只是对于基本类型数组的去重,但对于对象数组,却并不适合,因为对象数组要比较对象的所有成员
class Utils {
isObjectEqual = (a, b) => { //判断2个对象是否相等
let propertiesA = Object.getOwnPropertyNames(a);
let propertiesB = Object.getOwnPropertyNames(b);
if (propertiesA.length != propertiesB.length) {
return false; //2个对象的属性个数都不一样,当然不相等
}
for (let i = 0; i < propertiesA.length; i ) {
let attrName = propertiesA[i];
if (a[attrName] != b[attrName])
return false; //两个属性的值不一样
}
return true;
}
UnRepeat = (arr) => { //去重
let lst = [];
arr.forEach(x => {
if (!lst.some(y => { return this.isObjectEqual(x, y) })) //some类似于c#的any,委托返回一个布尔值,满足一个条件即可
lst.push(x);
});
return lst;
}
}
//调用方法 new Utils().UnRepeat(lst)
10)快速查找
在数组中如何快速查找到元素或者下标呢?
let field_db_type=[
{Text:'文本',Value:'NVARCHAR'},
{Text:'日期时间',Value:'DATETIME'},
{Text:'整型',Value:'INT'},
{Text:'小数',Value:'DECIMAL(19,7)'}
];
//查找元素
let obj=field_db_type.find(x=>x.Value=="INT");
console.log(obj); // {Text: '整型', Value: 'INT'}
console.log(obj?.Text??""); //整型
//查找下标
let index=field_db_type.findIndex(x=>x.Value=="INT");
console.log(index); //2
11)是否存在
let child={Text:'整型',Value:'INT'};
let isExists=field_db_type.some(x=>x.Value=="INT");
console.log(isExists); //true
12)求最大值、最小值
let arr=[1,6,9,5,10,7]
let maxValue=arr.sort((x,y)=>{ return y-x })[0];
let minValue=arr.sort((x,y)=>{ return x-y })[0];
console.log("最大值",maxValue); //最大值 10
console.log("最小值",minValue); //最小值 1
同理,对象数据也可以用sort进行排序,ex.
let arrObjs=[
{name:"老三",sort:3},
{name:"老大",sort:1},
{name:"老二",sort:2}
];
arrObjs.sort((x,y)=>{ return x.sort-y.sort });
console.log(arrObjs);
/*
//结果
{name: '老大', sort: 1}
{name: '老二', sort: 2}
{name: '老三', sort: 3}
*/
四、函数
1)简写
原来的写法
let fn=function(){alert("123")}
简写方法
let fn=()=>{alert("123")}
let fn=(str)=>{alert(str)}
2)回调函数
可以把方法当做参数来传递,类似于指针或者委托
let fn1=()=>{console.log("吃完了")};
((x)=>{console.log("吃饭了...");x();})(fn1);
结果:
吃饭了..
吃完了
3)日期函数
new Date(Date.now()); //日期时间
new Date(Date.now()).toJSON().substring(0,10) //只取日期 2022-08-06
new Date(Date.now()).toTimeString().substring(0,8) //只取时间 17:26:42
new Date(Date.now()).toLocaleDateString('zh-CN'): //2022/8/6
new Date(Date.now()).toLocaleTimeString('zh-CN'): //17:26:42
自定义日期
//注意:表示月份的参数介于 0 到 11 之间。也就是说,如果希望把月设置为 8 月,则参数应该是 7。
let d=new Date(2022,7,7,10,0,0);
console.log(d.toJSON().substring(0,10)); //2022-08-07 注意月份要-1
读取或者设置日期
//五天后
d.setDate(d.getDate() 5);
console.log(d.toJSON().substring(0,10)); //2022-08-12
d.getFullYear(); //获取完整的年份(4位,1970-???)
d.getMonth(); //获取当前月份(0-11,0代表1月) // 所以获取当前月份是myDate.getMonth() 1;
d.getDate(); //获取当前日(1-31)
d.getDay(); //获取当前星期X(0-6,0代表星期天)
d.getTime(); //获取当前时间(从1970.1.1开始的毫秒数)
d.getHours(); //获取当前小时数(0-23)
d.getMinutes(); //获取当前分钟数(0-59)
d.getSeconds(); //获取当前秒数(0-59)
d.getMilliseconds(); //获取当前毫秒数(0-999)
日期扩展
Date.prototype.formatDate=function(d=new Date(Date.now())){
return this.toJSON().substring(0,10);
}
4)不定参数arguments
当不指定参数时,可以用arguments来获取动态参数
let fn=function(){
console.log(arguments[1]); //输出第2个参数
}
fn(1); //undefined
fn(1,2); //2
不定参数还可以用rest参数,形式是 ...变量名,这相法于把参数都放到一个数组
let add=(...parameters)=>{ //这里...parameters 表示会把多个参数,放到一个数组里面(数组名称parameters),所以可以用forEach遍历
let sum=0;
parameters.forEach(x=>{
sum =x;
})
return sum;
}
console.log(add(1,2,3)); //6
5)参数默认值
let defParam=(p1,p2="world")=>{ console.log(p1,p2) };
defParam("hello"); //hello world
6)扩展函数
这些都是js自带的扩展函数,当然自己也可以进行扩展
//包含
[1,2,3,'a'].includes(2); //true
"1,2,3,a".includes("a"); //true
//左起字符判断
"1,2,3,a".startsWith(1); //true
//右起字符判断
"1,2,3,a".endsWith('a'); //true
//左填充
"123".padStart(5,"0"); //00123
//右填充
"123".padEnd(5,"0"); //12300
//清除左右空字符串
" 123 ".trim().length; //3
//左清除空字符串
" 123 ".trimStart().length; //4 清除了左边2个空字符串
//右清除空字符串
" 123 ".trimEnd().length; //5 清除了右边1个空字符串
//替换所有
"aaabc".replaceAll("a","1") //111bc,原es5的replace只会替换第一个匹配项
五、对象
除了基础类型外,都是对象
什么是对象?简单说,对象就是一组“键值对”(key-value)的集合
键默认是字符串,可以不加引号
值可以是任意类型
1)定义对象
let obj1=new Object();
let obj2={
name:"cat", //属性
age:3, //属性
eat:()=>{ console.log(`猫(${obj2.name})正在吃饭`) } //方法
}
2)遍历对象
对象不是数组,不能用forEach遍历。可以用for in遍历
let obj={name:"jasonlee",age:18};
for(let key in obj){
console.log(`key:${key} value:${obj[key]}`);
}
//结果:
//key:name value:jasonlee
//key:age value:18
但可以提取所有key或者value,这是数组
查看所有key:Object.keys(obj),返回一个数组!
查看所有value:Object.values(obj),返回一个数组!
3)增加属性
obj.username="jasonlee";
4)删除属性
delete obj.age;
5)对象的扩展
所有的对象都是继续自Object
静态方法
直接从Object派生出一个属性或者方法
Object.class="五班";
Object.show=()=>{console.log(`${Object.class}上课了`)};
Object.show(); //五班上课了
实例(prototype原型继承)方法
Object.prototype.eat=(animal)=>{console.log(`${animal}正在吃东西`)}
let cat={
name:"hellokit"
}
cat.eat(cat.name); //hellokit正在吃东西, cat是实例,可以调用eat方法
6)this
this就是属性或方法“当前”所在的对象
this都有一个共同点:它总是返回一个对象。
7)原型继承
继承的目的是为了减少代码重复
原型继承可以直接拥有被继承者的属性或者方法
let Animal={
name:"动物",
set:(_name)=>{this.name=_name;},
eat:(food)=>{ return `${this.name}在吃${food}`}
}
let Cat=function(){}; //这里不能用new Object()声明,否则Cat就是一个实例了
Cat.prototype=Animal; //继承自Animal,拥有Animal的所有属性和方法
let tom=new Cat();
tom.set("汤姆猫");
console.log(tom.eat("曲奇")); //汤姆猫在吃曲奇
8)字符串转对象
后端和前端交互的时候,往往会写入一些字符串,那要怎么转成js的对象呢,其实用eval就可以了。
//字符串转对象
let txt="{username:\"jasonlee\",age:18}";
let obj=eval('(' txt ')');
console.log(typeof(obj));
console.log(`姓名:${obj.username},年龄:${obj.age}`);
//字符串转JSON
let txt2="{\"username\":\"jasonlee\",\"age\":18}"; //json的key必须显式为字符串,不然报错
let jsonObj=txt2.toJSON();
console.log(typeof(jsonObj));
console.log(`姓名:${jsonObj.username},年龄:${jsonObj.age}`);
输出:
object
a.html:124 姓名:jasonlee,年龄:18
object
a.html:124 姓名:jasonlee,年龄:18
9)对象合并
let a={a:1};
let b={b:2};
let c=Object.assign({},a,b,{c:3});
六、JSON和对象
JSON数据必须符合规则,键必须是字符串,要带上单引号/双引号,比如{"username":"jasonlee"}
对象的键默认是字符串,不用带绰号,比如{username:"jasonlee"}
对象和JSON没有明确的界限,可以直接使用,如
let json={"username":"jasonlee"};
json.age=18;
console.log(json.age); //18
1)JSON转字符串
let json={"username":"jasonlee","age":18};
let str=JSON.stringify(json);
2)字符串转JSON
let str="{\"username\":\"jasonlee\",\"age\":18}";
let json=JSON.parse(str);
console.log(json.age); //18
3)扩展方法 toJSON
String.prototype.toJSON=function(){
//console.log(this.toString());
return JSON.parse(this.toString());
}
let str="{\"username\":\"jasonlee\",\"age\":18}";
let json=str.toJSON();
console.log(json.age); //18
七、class
1)类的定义
class相当于语法糖,作为对象的模板,类的命名首字母要大写
class Animal{
name=""; //属性
age=1;
constructor(_name){ //构造方法,参数的入口
this.name=_name;
}
eat(food){ //方法
console.log(`${this.name}正在吃${food}`);
}
get(){
return this;
}
talk(){
console.log(`i am a cat,my name is ${this.name}`);
}
}
new Animal("汤姆猫").eat("猫粮"); //汤姆猫正在吃猫粮
//链式调用
new Animal("汤姆猫").get().talk(); //i am a cat,my name is 汤姆猫
2)类的实例
let cat=new Animal("汤姆猫"); //cat 是 Animal的实例
3)判断是否包含属性
let cat=new Animal("汤姆猫");
cat.hasOwnProperty("name"); //true
cat.hasOwnProperty("name1"); //false
4)属性存取器
class Animal{
animal_type="";
get type(){ //属性type
return this.animal_type; //getter
}
set type(value) { //属性type
this.animal_type=value; //setter
}
}
let cat=new Animal();
cat.type="短尾猫";
console.log(cat.type); //短尾猫
5)类的继承
继承的目的是为了复用,继承使用关键字extends
class Cat extends Animal //接上面的Animal类
{
catchMouse(){
console.log(`${this.type}抓老鼠`);
}
}
let cat=new Cat();
cat.type="狸花猫"; //复用了super的属性
cat.catchMouse(); //狸花猫抓老鼠
6)静态方法和静态属性
静态方法和静态属性不会被继承,只能用类来调用
class Animal{
static className="Animal"; //静态属性
static getClassName(){ //静态方法
return "Animal";
}
}
class Cat extends Animal
{
//
}
let cat=new Cat();
console.log(cat.className); //undefined
console.log(Animal.className); //Animal
try{
console.log(cat.getClassName()); //抛出错误
}catch{
console.log("cat没有方法getClassName"); //cat没有方法getClassName
}
console.log(Animal.getClassName()); //Animal
7)私有属性和私有方法
私有就是在方法或者属性名称前面加上符号"#"
私有的不能被继承,也不能外部调用,私内部使用
class Animal{
#className="Animal";
#getClassName(){
return "Animal";
}
static show(){
console.log(`私有属性#className:${this.className}`)
}
}
class Cat extends Animal
{
//
}
let animal=new Animal();
console.log(animal.className); //undefined 不能外部调用
Animal.show(); //私有属性#className:undefined 可以内部使用
八、控制台输出
在谷歌浏览器按F12,并选择Console,可以查看控制台输出内容
1)console.log
最基本的输出方法
var obj=new Object();
obj.name="jsonlee";
//console可以输入多个参数,最后合并输出
console.log(obj,"123",456);
2)console.warn("警告");
3)console.error("错误");
4)console.table
以表格的形式更加直观的显示对象内容
var table={name:"jsonlee",age:18};
console.table(table);
5)清除
console.clear()
九、模块
模块就是实现特定功能的一组方法
1)立即执行函数 (方法体)(参数)
(function(){console.warn("立即函数")})();
2)匿名函数
(function(x,y){console.log("x y:",x y)})(1,2);
console.log(eval("(function(x,y){return x y})(1,2)"));
3)模块
这是一个方法块
var module1 = (function () {
var _count = 0;
var m1 = function () {
console.log("m1")
};
var m2 = function () {
//...
};
return {
m1 : m1,
m2 : m2
};
})();
module1.m1();
var singoo=(function($){
var show=function(){
console.log($("body").html().length)
}
return {show:show}
})(jQuery);
singoo.show();
十、AJAX
这里只介绍jquery的异步方法
1)get
从url读取数据,并以JSON格式返回
paramObj是一个对象,如{username:"jasonlee"}
$.getJSON(url,paramObj,function(result){
//
});
2)post
以post方式提交到url,并以JSON格式返回结果
$.post(url,paramObj,function(result){
//
},"JSON");
3)定时器
当页面需要不断刷新状态时,需要用到定时器
setInterval(function,1000);
//示例
setInterval(()=>{ console.log("hello world!") },1000); //不断重复
let fn1=()=>{ console.log("hello world!") };
setInterval(fn1,1000);
setTimeout(function,1000)
//示例
setTimeout(()=>{ console.log("已经执行完成!") },1000); //只执行一次
let fn2=()=>{ console.log("已经执行完成!") };
setTimeout(fn2,1000);
十一、异常处理
当有错误抛出的时候,整个html可能都无法响应js效果,所以捕捉异常显得犹为重要!
try{
var err=new Error("错误");
throw err; //抛出错误
}catch(err){
console.log(err.message); //错误
}finally{
console.log("清除错误"); //清除错误
}
十二、Promise
我的理解是一个容器,里面定义了很多分支,最基本是的True/False.
function timeout(ms) {
return new Promise((resolve, reject) => {
throw new Error("error");
setTimeout(resolve, ms, 'done');
});
}
timeout(100).then((value) => {
console.log(value);
},(err)=>{
console.log(err.message);
});
十三、window.localStorage
window.localStorage 允许在浏览器中存储 key/value 对的数据,类似于缓存
let storage = { //缓存选择的工位
isSupport: window.localStorage,
read: function (key) {
if(this.isSupport){
return window.localStorage.getItem(key);
}
return null;
},
set: function (key,val) {
if(this.isSupport){
window.localStorage.setItem(key,val);
}
},
del:function(key){
if(this.isSupport){
window.localStorage.removeItem(key);
}
}
}
let name=storage.read("name");
console.log(`name未赋值:${name}`); //name未赋值:null
storage.set("name","jasonlee");
name=storage.read("name");
console.log(`name已赋值:${name}`); //name已赋值:jasonlee
storage.del("name");
name=storage.read("name");
console.log(`name已删除:${name}`); //name已删除:null
十四、Object.create 继承对象
语法:
Object.create(proto[,propertiesObject]) //原型继承
参数1表示被继承的对象
参数2表示要添加的新的属性,注意写法是:{属性名称:{value:属性值}}
示例如下:
let obj1={
a:1,
b:function(){
console.log("我是刘备");
}
}
let obj2=Object.create(obj1,{UserName:{value:"关羽"},Age:{value:18}}); //obj2继承了obj1,拥有了obj1的属性和谅
console.log(obj2);
十五、随处调用的函数call
定义一个不同对象都可以调用的函数,相当于一个公共函数了。
let publicObj1={UserName:"张三"}
let publicObj2={UserName:"李四",Age:18}
function show() { console.log(`我是:${this.UserName},今年:${this.Age||0}`) }
show.call(publicObj1); //我是:张三,今年:0
show.call(publicObj2); //我是:李四,今年:18
函数里面的"this"指定的是代入的对象!
十六、$.extend
1)扩展jquery方法
扩展方法
$.extend({
method:function(){}
});
扩展对象
$.extend({ //调用$.mob.method()
mob:new ctt.mobile()
});
2)深度copy
let newStyle=$.extend(true,[],btnStyle);
十七、转码与压缩
我们编写的ES6代码,可能在比较老的设备上不能使用,需要先转码成ES5!
幸好有个这个网站:https://babeljs.io/repl,直接把包含es6的代码复制上去就会自动转换。
然后打开网站:https://www.wetools.com/js-compress,把转码成es5的代码复制进行进行压缩!
参考:
https://wangdoc.com/javascript/basic/index.html
https://wangdoc.com/es6/index.html