出售域名 11365.com.cn
有需要请联系 16826375@qq.com
在手机上浏览
在手机上浏览

重温js(es5 es6)教程

发布日期:2022-08-07

有一些很基础的就不重温了,主要记录一些比较会忘记,较难理解的,或者常用的内容

 

一、类型
常量 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