js基础学习2

152 阅读11分钟

数据类型转换

显式转换

1.转字符串

xx.toString(); undefined / null 不可使用

String() 万能转换法 等效隐式转换的+

2.转数字

parseInt()

parseFloat()

Number() 万能转换法 等效隐式转换-0 *1 /1 %1

3.转布尔

Boolean() 万能转换法 等效!!()

只有6个值转换结果为false:0,"",undefine,null,NaN,false

常用于循环/分支的判断条件

隐式转换

运算符和表达式

1.算术运算符 +-*/%

  1. 具有隐式转换,默认转为数字再运算
  2. 特殊使用
  • +运算 只要碰上一个字符串,两边都会默认转换字符串,进行拼接
  • -*/%运算 只要是纯数字组成的字符串,都会转为数字在运算

2.比较运算符 < > <= >= == != === !==

  1. 运算的结果: true / false
  2. 具有隐式转换,默认转为数字再进行比较
  3. 注意:
  • 若参与比较的两个都是字符串,按位比较每个字符的十六进制Unicode号或十进制ASCII码

    • 0-9 < A-Z < a-z < 汉字
    • 汉字第一个:一 4e00(19968)
    • 汉字最后一个:9fa5(40869)
  • NaN:参与任何比较运算,结果都为false

    • 解决:!isNaN() (数字-结果为false;NaN-结果为false)
  • undefined==null

    • 结果:true
    • 解决:使用===,数据类型和值都相同时,结果才为true
//String(); 执行原理:任何东西都可以转换为字符串

function String(x){
    if(x===null){
        console.log(null)
    }else if(x===undefined){
        console.log(undefined}
    }else{
        console.log(x.toString())
    }
}

3.逻辑运算符 && || !

短路逻辑

只要前一个条件已经可以得出结论,则后续条件不执行

  • &&:简化if(){}
if(total>=500){total*=0.8;}

total>=500&&(total*=0.8);
  • ||:两个值二选一,可用于兼容

4.位运算

左移:m<<n 读作:m左移了n位,实际是m*2的n次方

8*2*2*2*2 == 8<<4

右移:m>>n 读作:m右移了n位,实际是m/2的n次方

8/2/2/2/2 == 8>>4

5.赋值运算 += -= *= /+ %= ++ --

  • 递增和累加

    • 递增:i++ 每次只能+1
    • 累加:i+=n 每次加的数字可以自定义
  • ++i 和 i++ 的区别

    • ++i 返回的是加了1之后的新值
    • i++ 返回的是加了1之后的旧值

6.三目运算

  1. 简化if...else

    条件?操作1:默认操作;

  2. 简化if...else if...else

    条件1?操作1:条件2?操作2:条件3?操作3:默认操作;

  3. 注意

  • 只能完成【简单】的分支:操作只能有一句话
  • 默认操作不能省略

自定义函数/方法

使用

创建/定义/声明函数&返回结果(2种方法)

  • 声明方式:用function关键字进行声明 只有变量/常量/函数具有声明方式

function 函数名(形参,...){ 函数体 return 返回值; }

  • 直接量方式(函数名也是一个变量)

var 函数名=function(形参,...){ 函数体 return 返回值; }

调用函数&接住结果

var result=函数名(实参,...);

return

本意是退出函数,但若后面跟着一个数据,则可将数据返回到全局作用域,但返回值不会自动保存,所以需要创建一个变量保存结果

  • return 一个函数只能使用一次,最好写在函数体后面
  • 何时使用:并不是任何时候都需要使用return
    • 全局想要使用局部时
    • 调用完函数还想拿到函数结果进行后续操作时
    • 若无return,会有默认返回值undefined

作用域

全局作用域

【全局变量】和【全局函数】,在任何位置都可以访问/使用

局部作用域

【局部变量】和【局部函数】,只能在当前【函数调用时内部可用】

  • 变量的使用规则:优先使用自己的,自己没有找全局,全局都没有报错
  • 不要对未声明的变量直接赋值,会导致全局污染:所有的变量在使用之前都一定要先var,不能对着没有var变量直接赋值
  • 局部变量:
    • 直接在函数作用域中创建的变量
    • 形参

声明提前

程序执行前,将var声明的变量和function声明的函数,集中提前到当前作用域的顶部,但:1.赋值留在原地;2.变量比函数轻,变量在前

//1
var a=10;
function f1(a,b,c){
    console.log(a);//undefined
    var a=20;
    console.log(a);//20
}
f1();
console.log(a);//10
//2
function fn(){
    console.log(2);
}
fn();//2
var fn=100;
fn();//报错:fn不是一个方法
//3
var fn=function(){
    console.log(1)
};
fn();//1
var fn=100;
fn();//报错
var fn=function(){
    console.log(2)
};
function fn(){
    console.log(3)
};
fn();//不执行
//4
function fn(){
    console.log(1)
}
fn();//1
var fn=100;
var fn=function(){
    console.log(2)
}
fn();//2
//5
function fn(){
    console.log(1);
}
fn();
var fn=100;
var fn=function(){
    console.log(2);
}
fn();
function fn(){
    console.log(3);
}
fn();

按值传递

两个变量之间进行赋值

  1. 传递原始类型的值:两个变量之间赋值、做操作互不影响
  2. 传递引用类型的值:(Array、Function) 两个变量之间赋值、做操作会互相影响,因为引用类型传递的是地址值,共用地址值

预定义的全局函数

编码和解码

前端将用户输入的网址的中文编码为单字节字符,后端再将前端传递的内容解码为原文

  • 编码 var code=encodeURIComponent("str");
  • 解码 var 原文=decodeURIComponent(code);

isFinite(num)

判断num是否再有效范围内

  • 三种情况会为false:分母为0,NaN,Infinity

重要的:parseInt/Float()、eval()、isNaN()

分支结构

if...else结构

switch...case结构

switch(变量/表达式){ case 值1: 操作1; break; case 值2: 操作2; break; default: 默认操作; }

注意:

  1. 默认只要满足一条路,会把后面的所有操作做完 -->break:通常放在操作后面
    • 最后的default默认操作不用加break
    • 连续多个操作相同,可省略中间部分
  2. 不具有隐式转换
  3. default可以省略

if 和 switch的比较

switch

优点:效率相对较高,因为不需要做任何范围判断

缺点:不能实现范围判断,必须要知道用户有可能输入的结果是什么才能使用

if

优点:实现范围判断

缺点:效率相对较低

循环结构

while循环

var 循环变量=几; while(循环条件){ 循环体; 变量变化; }

do...while循环

var 循环变量=几; do{ 循环体; 变量变化; }while(循环条件)

while 和 do...while的区别?只看第一次

  1. 如果第一次大家都满足条件,两者没有区别,无非do...while更麻烦

  2. 如果第一次大家都不满足条件,while一次都不会执行,而do...while至少会执行一次

for循环

for(var 循环变量=几;循环条件;变量变化{循环体}

循环终止语句:

  • break 退出整个循环
  • continue 退出本次循环

数组

1.创建:2种

  1. 直接量:var arr=[值1,....];

  2. 构造函数:var arr=new Array(值1,....);//缺陷:

new Array(3);//设置一个长度为3的空数组

2.访问

获取:arr[i]; 下标越界:得到undefined

添加/替换:arr[i]=新值; 下标越界:得到稀疏数组

3.三大不限制:不限制长度、类型、下标越界

4.length

获取倒数第n个元素:arr[arr.length-n];

向末尾添加元素:arr[arr.length]=新值

缩容:arr.length-=n;

5.遍历

for(var i=0;i<arr.length;i++){ arr[i];//当前次元素 }

6.如何释放一个引用类型

找到这个引用类型对象有几个变量名引用着,每个变量都要释放才能真的释放干净

7.数组分类

索引数组:下标都是数字组成的数组

关联(hash)数组:下标是可以自定义的数组

  1. 创建:2步

    • 创建一个空数组:var arr=[];
    • 添加自定义下标并且赋值:arr["自定义"]=值
  2. 访问:arr["自定义下标"];

  3. 遍历:把所有的元素都取出来执行 相同 或者 相似的操作

    问题:不能使用for循环,因为length失效了,关联数组永远为0,而且下标也在是一个数字

    解决:for in循环 for(var i in 数组名){ 数组名[i] }

    不光可以遍历关联数组,也可以遍历索引数组

  4. JS中除了undefined和null不是一个对象,万物皆对象,而且一切对象的【底层都是hash数组】

  5. hash数组的原理:

    • hash算法:将字符串交给hash算法,会得到一个尽量不重复的数字,但是字符串内容相同的,那么得到的数字一定也是相同的

    • 添加元素:将自定义的下标交给hash算法,得到一个数字(地址值),把要保存的数据放到那个地址之中

    • 获取元素:将指定的下标交给hash算法,得到一个和添加时完全相同的数字(地址值),得到这个地址值之中保存的数据

数组的API

1. 数组转字符串

var str=arr.join("自定义连接符");

注意:

  1. 如果没有传入实参,则和toString/String,完全一样,默认由,分割

  2. 固定使用

  • 提供一个数组给你,无缝拼接数组里面的内容变为一个字符串
var arr=["h","e","l","l","o"," ","w","o","r","l","d"];
var str=arr.join("")
console.log(str);//"hello world";
  • 将数组中的数据拼接为页面上的元素:初级版数据渲染
var cities=["北京","南京","西京","东京","重庆"];
var str="<option>"+cities.join("</option><option>")+"</option>";
sel.innerHTML=str;//innerHTML可以识别标签
//二级联动
//1.必须使用二维数组,而且二维数组的数据顺序一定要和一级的对应上
//2.select专属事件:select.onchange:状态改变事件:选中项发生改变才会触发
//3.select具有一个属性:this.selectedIndex;获取选中项的下标 - 只有select不需要自定义下标
//4.其实绑定事件的部分就是函数名,也可以拿来调用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <select name="" id=""></select>
    <select name="" id=""></select>

    <script>
        var sel1=document.getElementsByTagName("select")[0],
            sel2=document.getElementsByTagName("select")[1];
        
        var cities=["-请选择-","北京","南京","东京","西京","重庆"],
            counts=[
                ["-请选择-"],
                ["-请选择-","东城区","海淀区","通州"],
                ["-请选择-","玄武区","秦淮区","鼓楼区","雨花台区"],
                ["-请选择-","开封","汴京","龙亭区","杞县","兰考县"],
                ["-请选择-","西安","碑林区","未央区","长安区","临潼区"],
                ["-请选择-","渝中区","江北区","南岸区","渝北区","巴南区"]
            ]

        sel1.innerHTML="<option>"+cities.join("</option><option>")+"</option>";
        sel1.onchange=function(){ 
            var i=this.selectedIndex;
            sel2.innerHTML="<option>"+counts[i].join("</option><option>")+"</option>"
        }
        sel1.onchange();
    </script>
</body>
</html>

2.拼接数组

var newArr=arr.concat(值1,arr1...);

注意:

  1. 此方法不修改原数组,只会返回一个新数组
  2. 此方法传参支持数组参数,并且会悄悄的打散这个数组,单独传入

3.截取子数组

var subArr=arr.slice(starti,endi+1)

从starti位置截取到endi+1位置的元素,组成一个新数组

注意:

  1. 此方法不修改原数组,只会返回一个新数组

  2. 含头不含尾,从strati 到 endi,不含endi-1

  3. 第二实参可以省略:从starti截到末尾

    第一实参也可以省略:从头截到尾 - 昨天按值传递(浅拷贝)

    深拷贝:复制了一个副本给对方

  4. 支持负数参数,-1代表倒数第一个

4.删除、插入、替换

删除:var dels=arr.splice(starti,n);//从starti开始删除n个

特殊:此方法其实有返回值,所有删除的元素组成的一个新数组

插入:arr.splice(starti,0,值1,...);//从starti开始删除0个,插入了新元素

特殊:原来starti位置的元素以及后续元素都会被向后移动

替换:var dels=arr.splice(starti,n,值1,...);

特殊:插入的个数和删除的个数可以随意

5.翻转数组

arr.reverse();

6.排序

arr.sort();

注意:

  1. 默认按照字符串按位PK每个字符的unicode号排序
  2. 按照数字排序
//正序:从小到大
arr.sort(function(a,b){
    return a-b;
})
//降序:从大到小
arr.sort(function(a,b){
    return b-a;
})
  • function(){}回调函数:不需要程序员调用的函数:悄悄的带有循环,提供了两个形参:a是后一个数,b是前一个数

  • return a-b

    • 如果a>b,返回是一个正数
    • 如果a<b,返回是一个负数
    • 如果a==b,返回是一个0,sort根据你反复的结果,来判断两者要不要交换位置
//冒泡排序:把数组中的每一个数字取出来,前一个和后一个进行比较,如果前一个>后一个,两者就要交换位置:

var arr=[13,25,4,3675,12,23,3,215,2,1,42,4,65,473,2431,123];
for(var j=0;j<arr.length-1;j++){
    for(var i=0;i<arr.length-(j+1);i++){
        if(arr[i]>arr[i+1]){
        var m=arr[i];
        arr[i]=arr[i+1];
        arr[i+1]=m;
        }
    }
}	
console.log(arr);

7.栈和队列

一端封闭,只能从另一端进出的操作

开头进:arr.unshift(值1,...);

开头出:var first=arr.shift();//一次只能删掉一个,并且会返回删除的元素

结尾进:arr.push(值1,...);

结尾出:var last=arr.pop();//一次只能删掉一个,并且会返回删除的元素

队列

只能从一端进入,另一端出

//轮播
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .banner{
            position: relative;
        }
        img{
            width: 100%;
        }
        .banner>div{
            height:20px;
            width: 30px;
            background: rgb(255, 255, 255,0.5);
            line-height: 20px;
            text-align: center;
            color:#333;
            font-size:18px;
            position:absolute;
            top:50%;
            margin-top: -10px;
        }
        .banner>div:nth-of-type(1){
            border-radius:0 10px 10px 0;
            left: 0;
        }
        .banner>div:nth-of-type(2){
            border-radius:10px 0 0 10px;
            right: 0;
        }
    </style>
</head>
<body>
    <div class="banner">
        <img src="./img/1.jpg" alt="">
        <div class="button"><</div>
        <div class="button">></div>
    </div>
    
    <script>
        var images=["./img/1.jpg","./img/2.jpg","./img/3.jpg"],
            btns=document.getElementsByClassName("button"),
            img=document.getElementsByTagName("img")[0];

        var div=document.getElementsByClassName("banner")[0];
        
        for(var i=0;i<btns.length;i++){
            btns[i].onclick=function(){
                if(this.innerText==">"){
                    var first=images.shift();
                    images.push(first);
                    img.src=images[0]
                }else{
                    var last=images.pop();
                    images.unshift(last);
                    img.src=images[0];
                }
            }
        }

        timer=setInterval(function(){
            var first=images.shift();
            images.push(first);
            img.src=images[0]
        },1000);
        
        div.onmouseover=function(){
            clearInterval(timer);
        }
        div.onmouseout=function(){
            timer=setInterval(function(){
                var first=images.shift();
                images.push(first);
                img.src=images[0]
            },1000);
        }





    </script>
</body>
</html>

二维数组

创建

var arr=[["张三丰",128,3500],["张翠山",30,4500],["张无忌",18,5500]];

访问

arr[r][c];

  1. 列下标越界:返回undefined
  2. 行下标越界:报错:undefined不能使用[]

遍历二维数组

必然需要两个循环嵌套:外层循环控制行,内层循环控制列

for(var r=0;r<arr.length;r++){
    for(var c=0;c<arr[r].length;c++){
    console.log(arr[r][c]);
    }
}
  1. 定时器 开启定时器:timer=setInterval(function(){操作},间隔毫秒数)

关闭定时器:clearInterval(timer);

2、鼠标移入:onmouseover

3、鼠标移除:onmouseout

//淡入淡出轮播
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            list-style: none;
        }

        img {
            width: 100%;
            vertical-align: top;
            opacity: 0;
        }

        .banner {
            position: relative;
        }

        .banner>.banner_img>img {
            position: absolute;
            left: 0;
            top: 0;
            transition: all 1s linear;
        }

        .banner>button {
            height: 30px;
            width: 40px;
            background: rgba(0, 0, 0, 0.3);
            border: none;
            font-size: 20px;
            text-align: center;
            line-height: 30px;
            cursor: pointer;
            position: absolute;
            top: 50%;
            margin-top: -15px;
        }

        .banner>button:active {
            background: rgba(0, 0, 0, 0.5);
        }

        .banner>button:nth-of-type(1) {
            left: 0;
            border-radius: 0 15px 15px 0;
        }

        .banner>button:nth-of-type(2) {
            right: 0;
            border-radius: 15px 0 0 15px;
        }

        .banner>ul {
            width: 60px;
            text-align: center;
            display: flex;
            justify-content: space-around;
            position: absolute;
            left: 50%;
            margin-left: -30px;
            bottom: 15px;
        }

        .banner>ul>li {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: #999;
            cursor: pointer;
        }

        img.active {
            opacity: 1;
        }

        .banner>ul>li.active {
            background: #eee;
        }
    </style>
</head>

<body>
    <div class="banner">
        <div class="banner_img">
            <img src="./img/1.jpg" alt="" class="active">
            <img src="./img/2.jpg" alt="">
            <img src="./img/3.jpg" alt="">
        </div>
        <img src="./img/2.jpg" alt="">
        <button><</button>
        <button>></button>
        <ul>
            <li cli="0" class="active"></li>
            <li cli="1"></li>
            <li cli="2"></li>
        </ul>
    </div>

    <script>
        var btns=document.getElementsByTagName("button"),
            lis=document.getElementsByTagName("li"),
            imgs=document.getElementsByTagName("img"),
            j=0,
            div=document.getElementsByClassName("banner")[0];

        for(var i=0;i<btns.length;i++){
            btns[i].onclick=function(){
                if(this.innerText==">"){
                    j++;
                    j==lis.length&&(j=0);

                    for(i=0;i<lis.length;i++){
                        lis[i].className="";
                        imgs[i].className="";
                    }
                    lis[j].className="active";
                    imgs[j].className="active";
                }else{
                    j--;
                    j==-1&&(j=lis.length-1);

                    for(i=0;i<lis.length;i++){
                        lis[i].className="";
                        imgs[i].className="";
                    }
                    lis[j].className="active";
                    imgs[j].className="active";
                }
            }
        }

        for(var i=0;i<lis.length;i++){
            lis[i].onclick=function(){
                j=this.getAttribute("cli");

                for(i=0;i<lis.length;i++){
                    lis[i].className="";
                    imgs[i].className="";
                }
                lis[j].className="active";
                imgs[j].className="active";
            }
        }
            
        timer=setInterval(function(){
            j++;
            j==lis.length&&(j=0);

            for(i=0;i<lis.length;i++){
                lis[i].className="";
                imgs[i].className="";
            }
            lis[j].className="active";
            imgs[j].className="active";
        },2000)

        div.onmouseover=function(){
            clearInterval(timer);
        }
        div.onmouseout=function(){
            timer=setInterval(function(){
                j++;
                j==lis.length&&(j=0);

                for(i=0;i<lis.length;i++){
                    lis[i].className="";
                    imgs[i].className="";
                }
                lis[j].className="active";
                imgs[j].className="active";
            },2000)
    
            }

    </script>
</body>

</html>

String

概念

多个字符组成的【只读】字符【数组】

  1. 字符串也可以叫数组
  • 和数组有共同点:

    • 支持下标 - 获取某个字符
    • 支持length - 字符的长度
    • 遍历
    • 数组不修改原数组的API,字符串也可以使用(concat、slice)
  • 不同点:数组修改原数组的API,字符串都不可以使用,但是字符串也有很多属于自己的API

  1. 只读:字符串中的所有的API都不会修改原字符串,只会返回新字符串

引用类型的对象: 11个

String(字符串) Number(数字) Boolean(布尔) - 具有包装类型

Array(数组) Function(函数) Math(数学) Date(日期) RegExp(正则) Error(错误) Object(面向对象)

Global - 全局对象:在浏览器端被window对象给代替了:window对象可以省略不写出来

包装类型

将原始类型的值变为一个引用类型的对象

  1. 为什么:前辈们发现字符串/数字/布尔经常都会被拿来使用,所以提前提供了包装类型封装为一个引用类型的对象,提供我们一些属性和方法(便于程序员操作)
  2. 何时使用:只要在你试图用原始类型的值去调用属性或者方法时,会自动套上包装类型
  3. 何时释放:属性或方法调用完毕后,包装类型自动释放
  4. 为什么undefined和null不能使用.:不具有包装类型,没有任何的属性和方法

String的API

\ 转义

  1. 字符串中如果出现了和字符串冲突的符号,可用\将其转义为原文"
  2. 特殊功能
  • 换行:\n
  • 制表符:\t
  1. 可以书写unicode号 表示一个字\uXXXX
  • 汉字的第一个字4e00 汉字的最后一个字9fa5

1.转换大小写

【统一的】转为大写或小写,再比较,忽略大小写:- 验证码

大写:var newStr=str.toUpperCase();

小写:var newStr=str.toLowerCase();

2.ascii码

获取字符串中指定位置的字符的ascii码var ascii=str.charCodeAt(i);

通过ascii码转回原文var 原文=String.fromCharCode(ascii);

3.检索字符串

var i=str/arr.indexOf("关键字",starti); 检查索引/下标:从starti位置开始找右侧的第一个关键字的下标

注意:

  1. starti可以省略,若省略则从0开始
  2. 返回值:找到则返回第一个字符的下标;没找到则返回-1
  3. 数组也可以使用该方法
  4. 找到所有关键字的位置
var str="no zuo no die no can no bibi";
var i=-1;
while((i=str.indexOf("no",i+1))!=-1){
    console.log("找到了:"+i);
}

4.拼接字符串

var newStr=str.concat(str1,str2...)

5.截取字符串(3种)

var subStr=str/arr.slice(starti,endi+1);

var subStr=str.substring(starti,endi+1);不支持负数参数

*var subStr=str.substr(starti,n);截取的个数,不必考虑含头不含尾

6.替换字符串-配合正则使用

var newStr=str.replace("关键字"/正则表达式,"新内容");

7.切割/分割字符串

作用:str <=> arr

var arr=str.split("自定义切割符");

注意:

  1. 切割符可以自定义,切割过后返回一个数组,数组中不再包含切割符
  2. 如果传入的切割符是一个"",每一个字符都会被切开

创建元素并且渲染页面

  1. 创建空标签var elem=document.createElement("标签名");

  2. 设置必要的属性或事件

elem.属性名="属性值";

elem.on事件名=function(){函数体} -事件都可以在创建时提前绑定上

  1. 创建好的元素渲染到DOM树上父元素.appendChild(elem);
//将数据渲染到页面上,形成表格
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        table{
            width: 900px;
            margin:50px auto;
            text-align: center;
            border:1px solid #000;
            border-collapse: collapse;
        }
        td{
            border:1px solid #000;
        }

    </style>
</head>
<body>
    <script>
        var body=document.getElementsByTagName("body")[0];
        var str="Tom@补给兵@60%#Mary@医护兵@80%#John@特种兵@30%";

        var table=document.createElement("table");
        var arr=str.split("#");
        for(var i=0;i<arr.length;i++){
            var tr=document.createElement("tr");
            var people=arr[i].split("@");
            for(var j=0;j<people.length;j++){
                var td=document.createElement("td");
                td.innerHTML=people[j];
                tr.appendChild(td);
            }
            table.appendChild(tr);
        }
        body.appendChild(table);
    </script>
</body>
</html>