js总结总结

1. 三种输出方式

    // 单行注释
    /*
     shift+alt+a
     */
    //  三种输出
    console.log("在控制台打印");  //弱类型语言,可不加分号
    alert("弹窗");
    document.write("在网页显示");
    // 可解析标签类型字符串
    document.write("<h1>巴巴</h1>");

2. 声明变量

1. 常量(字面量) 一些不可改变的数据
	变量 记录一些可变化的数据

3. 变量声明规则 
		// 1.数字 字母 下划线 $组合,不能数字开头,不能汉字
        // 2. 不能使用关键字
        // 3. 不超过255字符
        // 4. 可使用小驼峰方式 见名知义
        // 5. var my_name = "张三";双引号 单引号 反撇号
        var _123a = 2;
        var my_name = "张三";
        var myName = "张三";
        var myAge = 12, mytel = 110;
//变量状态:声明变量 给变量赋值 使用变量

var let const

var
 1.声明的变量不具备块级作用域的特性,它在{}外依然能被访问到; 
 3.循环中,使用了var关键字,它声明的变量是全局的,包括循环体内与循环体外。
 4.声明的全局作用域变量属于 window对象
 5.使用 var 关键字声明的变量在任何地方都可以修改
 6.变量提升时,变量可以先使用再声明

let 
 1.声明的变量只在let命令所在的代码块{}内有效,在{}之外不能访问; 
 3.Internet Explorer 11 及更早版本的浏览器不支持 let关键字; 
 4.循环中,使用let关键字,它声明的变量作用域只在循环体内,循环体外的变量不受影响。
 5.声明的全局作用域变量不属于 window 对象
 6.在相同的作用域或块级作用域中,不能使用 let 关键字来重置 var 关键字声明的变量 ,不能使用 let 关键字来重置 let 关键字声明的变量 ,不能使用 var 关键字来重置 let 关键字声明的变量,let 关键字在不同作用域,或不同块级作用域中是可以重新声明赋值的:

const
 const 用于声明一个或多个常量,声明时必须进行初始化,且初始化后值不可再修改,块级作用域,需要先声明再使用

3. 数据类型

    //1. 基本数据类型:
    //    String字符串  
    //    Number数值类型(整数 小数 负数) 
    //    Boolean(true false)  
    //    Undifind未定义(没赋值) null是一个表示"无"的对象,转为数值时为0;
    //    Null(赋了空值) undefined是一个表示"无"的原始值,转为数值时为NaN      

    //2. 引用数据类型: 
    //      除了基本数据类型 都是引用数据类型 
    //      比如 (对象 数组 日期)对象类型 函数
    var name = "悟空"; //String
    var age = 2000;  //number
    var isGirl = false;  //Boolean

    //3. 对象
    var obj_wukong = {
        name:"孙悟空",
        age:"2000",
        address:"花果山",
        brother:{
            name:"猪八戒",
            age:3000,
            address:"高老庄",
            wife:{
                name:"高翠兰",
                address:"高老庄"
            }
        }
    }
    //4. 数组和对象相互嵌套
    var citys = [
        {
            name:"郑州",
            areaList:["经开区","高新区","金水区"]
        },
        {
            name:"周口",
            areaList:["川汇区","淮阳区"]
        }
    ];
        console.log(citys);

5. 数据类型转换

其他类型变Number Number() parseInt() parseFloat() 2+ +2 2- -2

  • (Number类型,用于编写程序逻辑运算)
    string转number:
    1.数字字符直接转
    2.空字符以及纯空格字符转为0
    3.其他字符NaN
    4.NaN不能进行运算,如果运算结果要么NaN要么false,NaN与任何数都不相等,与自身也不相等
    var res = Number(‘0’);//0
    var res = Number(’’);//0
    5.parseInt()将其他类型转为数值型的整数,除字符串外其他都是NaN
    ( parseInt()的转换规则:
    1.忽略字符串前面的空格,直到找到第一个非空格字符
    2.如果第一个字符不是数字或者是负号,返回NaN
    3.空字符串,返回NaN
    4.如果第一个字符是数字,会继续解析第二个字符,直到解析完所有后续字符或遇到了一个非数字字符。
    5.如果字符串以0x开头且后面跟数字字符,就会将其转为10进制数,同样,八进制也一样。
    )
    var res = parseInt(’’);//NaN
    var res = parseInt(‘0’);//0
    var res = parseInt([]);//NaN
    var res = parseInt([ ,012]);//NaN
    var res = parseInt([‘9’]);//9
    var res = parseInt({});//NaN
    var res = parseInt(’ 012fg’);//12
    var res = parseInt(‘0x222222’);//2236962
    6.parseFloat()也是从第一个字符开始解析每个字符,而且也是一直解析到字符串末尾,或者解析到遇见一个无效的浮点数字字符为止。规则如下:
    (1.第一个小数点是有效的,第二个小数点无效
    2.始终忽略前面的0,不分进制数
    3.十六进制会被转换成0
    4.空字符串转换为NaN)

    boolean转number:
    true 1 false 0

    数组转number:
    由于没有对应的API,先转字符串(默认触发toString()),再转number
    var res = Number([]);//0
    var res = Number([1,2]);//NaN

    对象转number:
    也是先转字符串’[Object,Object]’
    var res = Number({});//NaN
    var res = Number({name:“li”});//NaN

    总结:
    数组和对象直接运算,先转字符串,再转其他类型,最后再运算
    基本类型间的转换只转一次,引用类型转基本类型先变字符串再变其他

其他类型变String String() +’’ ‘’+ toString() join()

  • (String类型,用于展示,建立与数组联系)

     	console.log(String([]));//''
        console.log(String([1,2]));//'1,2'
        console.log(String({a:1,b:2}));//[Object,Object]
        console.log(String(undefined));//'undefined'
        console.log(String(null));//'null'
        console.log(String([123]+{}));//'null'
    

其他类型变Boolean Boolean() 除了下边这写是true其余都是false ==比较运算符个别关系运算符时

  • (BOOlean类型,用于条件句,或循环语句)

     	console.log(Boolean(false));//false
        console.log(Boolean(0));//false
        console.log(Boolean(''));//false
        console.log(Boolean(undefined));//false
        console.log(Boolean(null));//false
        console.log(Boolean(NaN));//false
        console.log(Boolean([]));//true
        console.log(Boolean({}));//true
    
  • null类型,用于 清理内存

  • undefined类型,表示某个变量已声明但未赋值用以判断函数是否有结果

  • array

  • function

6. 数据类型验证

    var a =1;
    // 验证是否是number
    console.log(typeof(a) ==='number');
    console.log(a instanceof Number);
	**arr instanceof Object验证的可能是数组也可能是对象**
    console.log(a.constructor===Number);
	//验证是否是数组
	console.log(Array.isArray(Date))
    // 验证是否是NaN
    console.log(isNaN(a));
    // 验证是否是undefined
    console.log(typeof(a) ==='undefined');
    console.log(a===undefined);
    // 验证是否是null
    console.log(!a && !isNaN(a) && typeof(a) != 'undefined' && a != 0)
    //判断思路:所有数据转化false只有undefined null 0 NaN false 
    //如果一个数据不是undefined 0 NaN false ,那么根据排除法 返回true就是null 返回false就是上面其中一个

7. 运算符

    //1. 算术运算符 + -  * %
    //2. 比较运算符(关系运算符)> < >= <= ==
        var str1 = "z张";
        var res = str1 + 123; //这里加是字符串拼接的意思
        console.log(res);
        console.log(str1 + res);
    //3. 逻辑运算符 ||或  &&且  !非  
        // && 叫逻辑与,在其操作数中找到第一个虚值表达式并返回它,如果没有找到任何虚值表达式,则返回最后一个真值表达式。它采用短路来防止不必要的工作。
        // || 叫逻辑或,在其操作数中找到第一个真值表达式并返回它。这也使用了短路来防止不必要的工作。在支持 ES6 默认函数参数之前,它用于初始化函数中的默认参数值。
        // ! 运算符可以将右侧的值强制转换为布尔值,这也是将值转换为布尔值的一种简单方法。
    var ab = false;
    var ac = false;
    console.log(ab || ac);
    //4. 赋值运算符 =

    //5. 判断数据类型的运算符
    var a = null;
    console.log(typeof a); //object
        //NaN 的数据类型是数值
        // 数组的数据类型是对象
        // 日期的数据类型是对象
        // null 的数据类型是对象
        // 未定义变量的数据类型是 undefined
        // 尚未赋值的变量的数据类型也是 undefined
    //6. constructor 属性返回所有 JavaScript 变量的构造器函数。
    "Bill".constructor
    //返回"function String(){[native code]}"

8. 渲染页面

        var arr = singers.data.artistList;
        var  htmlStr = "<div class='boxall'>";
         
        for(var i=0; i<arr.length; i++){
        htmlStr += "<div class='box'><img src="+arr[i].pic+"><br> <b>"+arr[i].name+"</b><p>"+arr[i].artistFans +"</p></div>";
        }
        htmlStr += "</div>";
        document.write(htmlStr);


        //var a = ```'a'''""`;
        //不能嵌套相同的引号,只有``能换行能添加变量

        var b = `sgdg${arr[i].name}gshghg`;//必须用``
        var b = "fds"+arr[i].name+"sgfdgs";//里外引号要一样
        var c = `dsds`+arr[i].name+`ffhhh`;//里外引号要一样

9. js内置对象

Math
Date
时间戳
    // Math内置API
        alert(Math.random());//0-1随机数不包括1
        console.log(Math.random()*5);//0-5随机数不包括5

        console.log(Math.ceil(1.5));//向上取证
        console.log(Math.floor(1.5));//向下取整
        console.log(Math.round(3.33));//四舍五入  结果3

        console.log(Math.ceil(Math.random()*5));
        console.log(Math.floor(Math.random()*8+4));
        // console.log(Math.random*(b-a+1)+a);

        console.log(Math.PI);
        console.log(5*5*Math.PI.toFixed(3));//保留三位小数,如果不传参数四舍五入
        console.log(12.58.toFixed());

        console.log(Math.pow(2,10));//2的10次方
        console.log(Math.pow(2));//NAN not a number

        console.log(Math.sqrt(9));//对9开平方根 结果3

        console.log(Math.abs(-3));//绝对值
        console.log(Math.max(1,2,3,4,5,6));//最大值
        arr=[6,7,8];
        console.log(Math.max(...arr));//...拓展arr数组,不能直接放arr数组
        console.log(Math.min(...arr)); 
    
    

    // data日期对象API
        var date = new Date();//日期构造函数
        console.log(date);

        var year = date.getFullYear();//年
        var month = date.getMonth();//月 返回0-11 比月份实际小1       
        var day = date.getDate();//日   
        var week = date.getDay();//星期几 周日0 1-6
        console.log(year +"-" + month + "-" + day + "-" + week);

        var hour = date.getHours();//时
        hour = hour<10 ? "0" + hour : hour;
        var minutes = date.getMinutes();//分
        minutes = minutes<10 ? "0" + minutes : minutes;
        var seconds = date.getSeconds();//秒
        seconds = seconds<10 ? "0" + seconds : seconds;
        console.log(hour+ ":" + minutes + ":" + seconds );

        var milliseconds = date.getMilliseconds();//毫秒
        

    // 设置日期对象
        var date = new Date();

        date.setFullYear(2000,1,1);//设置年 2000年1月1日        
        date.setMonth(1,6); //设置月 1月6日
        date.setDate(22);

        date.setHours(3);
        date.setMinutes(3);
        date.setSeconds(3);
        date.setMilliseconds(999);
        console.log(date);


   //传入字符串 如果不写时分秒 默认08:00:00
        console.log(new Date('2021-02-02 12:00:00'))
        ;                                    
        //除了2021-02-02 其他的如果不写时分秒 默认00:00:00
        console.log(new Date('2021 02 02 12:00:00'));                                    
        console.log(new Date('2021,02,02 12:00:00'));                                    
        console.log(new Date('2021*02*02 12:00:00'));                                    
        console.log(new Date('2021.02.02 12:00:00'));                                    
        console.log(new Date('2021/02/02 12:00:00'));                                    



    // 时间戳
    
    // 计算机元年1970年1月1日
        function Timer(){
            var date = new Date();
            console.log(Date.now());//当前时间距1970年1.1毫秒数
            var date1 = new Date('2023.2.21');
            console.log(date1,date1.getTime(), date1.valueOf());//2023年距1970年毫秒数

            var time = date1.getTime() - date.valueOf();//2023年2.21距当前毫秒数

            var d = parseInt(time/1000/60/60/24);
            var h = parseInt(time/1000/60/60%24);
            var m = parseInt(time/1000/60%60);
            var s = parseInt(time/1000%60);                          
            setTimeout(Timer,1000); 
            document.getElementById('timer').innerHTML=('2023.2.21距当前时间' + d + '天' + h + '小时' + m + '分钟' + s + '秒');
        };
        Timer();

    // 将时间戳转为标准时间
        var chuo = new Date(555555555);
        console.log(chuo);
    
</script>

10. 数组

.slice(start,end)截取  (开始索引,结束索引不包括) 返回截取下来的数组 对原数组无影响 
只写一个值的话就从这个数字截取到最后
         var res9 = arr7.slice(0,3);//134
         console.log(res9,arr7);
.splice(start,count,newItem) 删除数组中某些项 返回删除的数 改变原数组
(开始值,要删几个 非必填 不填则删除后面所有 填0则不删 , 从开始删除的位置添加新的项)
         arr7=[7,8,7,8]
         var res10 = arr7.splice(1,2,6);
         var res10 = arr7.splice(1,2);
         var res10 = arr7.splice(1);
         var res10 = arr7.splice(1,2,6,7,7,8);
         console.log(res10,arr7);
.filter()   
    过滤数组 
    参数:函数
    回参1:表示数组的元素
    回参2:数组索引
    return 过滤条件
    返回值:返回满足条件所有元素的新数组
        var res = arr.filter(function (item,index){
             return item.age>13;
         })
         console.log(res);
.forEach()  遍历数组
         var arr = [
             {age:12},
             {age:13},
             {age:15},
             {age:123},
         ]
         arr.forEach(function(item,index)  {
             console.log(item,index);
         });
.some()api  检查数组中是否存在 符合条件的元素
    作用:检查数组中是否存在 符合条件的元素
    参数:回调函数
    返回值:true存在 false不存在
    一旦存在满足条件的元素函数就不循环执行
        var array = [1,4,3,9,5];
        var even = function(element){
            return element % 2 === 0;//验证的条件
        }
        var res = array.some(even);
        console.log(res);
        //模拟api
        Some(array,function(element){
        return element%2===0;
    })
    function Some(array,cb){
        var flag=false;//初始化结果
        
        for(var i=0;i<array.length;i++){
            
            if(cb(array[i])){
                flag = true;
                break;
            }

            if(i===array.length-1){
                flag=false;
            }
        }
        console.log(flag);
        return flag;
    }
.map()api
    作用:创建新数组
    参数:回调函数,arr多长,函数就执行多少次
    返回值:新的数组map map.length ===array.length
    新数组中的元素来自于回调函数的return
    用于:数组重组,数据处理
         var arr = [1,2,3];
         var map_arr=map(arr,function(element){
             // console.log(element);
             return element;
         })
         console.log(map_arr);
        
         function map(arr,cb){
             var res=[];
            
             for(var i=0 ; i<arr.length ;i++){
                 res.push(cb(arr[i]));
             }
             console.log(res);

             return res;
         }
.ruduce()一般用于数学运算,累加累乘 
    参数一:回调函数
    参数二:回参一的初始值
    回参一pre:上一次函数执行的return运算结果
    回参二current:是arr数组的元素
    返回值:运算结果,一个单一的数 
       var arr = [1,2,3,4,5];
       var initialValu = 0;
       var res = reduce(arr, function (pre,current) {
           console.log('-------------');
           console.log(pre,current);
           return pre+current
       },initialValu)
       console.log('运算结果------',res);
       // arr 是做什么的  init 是干什么的
         // 写什么东西可以完成reduce的功能
         function reduce(arr,cb,init){
             for(var i = 0;i<arr.length;i++){
                 init = cb(init,arr[i]);
            
             }
             return init
         }
js内置处理数组方法
     1.合并数组concat 有返回值 返回一个新数组 对原数组没有影响
         var arr1=[1,2];
         var arr2 = [3,4];
         var res = arr1.concat(arr2);
         console.log(res);

     5.shift删除数组中的第一个 返回删除的项 改变原数组  
         var res4 = arr3.shift();
         console.log(res4);

     4.unshift 向数组头部添加 返回添加后的长度 改变原数组
         var arr3 = [1,2,3];
         var res3 = arr3.unshift(1,1);
         console.log(res3);

     3.pop删除数组中最后一个 有返回值 返回删除的项 改变原数组
         var res2 = arr3.pop();
         console.log(res2);

     2.push 向数组尾部添加项 有返回值 返回添加项之后的长度 改变原数组 同时向添加多项 用逗号隔开即可
         var res1 = arr3.push(5,6);
         console.log(res1); 

    练习1. 将两数组合并 并将合并后的数组首尾交换
         var arr4 = [1,2,3,4];
         var arr5 = [5,6,7,8];
         var res = arr4.concat(arr5);
         console.log(res);
         var one = res.shift();
         var last = res.pop();
         res.push(one);
         res.unshift(last);
         console.log(res);


    
     6.toString(); 将数组转换为字符串 不改变原数组
         var arr6 = [1,2,3,4,5,6];
         var res5 = arr6.toString();
         console.log(res5,arr6);
     7.join()将数组转为字符串 不添加值默认逗号隔开 添加值则由添加的值隔开 原数组不变
         var res6 = arr6.join(6);
         console.log(res6 , arr6);

     8.reverse 翻转数组 改变原数组值
         console.log(arr6.reverse(),arr6 );

     9.indexOf() 获取收个指定元素在数组中的位置的索引,若不存在返回-1 
         var arr7 = [1,3,4];
         var res7 = arr7.indexOf(4);//2
         console.log(res7);
     lastIndexOf()从后往前
         var res8 = arr7.lastIndexOf(1);//0
         console.log(res8);

    练习2.不带7
         arr7 = []; 
         for(var i=1 ;i<=100 ;i++){
             if(i%7==0 || i%10==7 || i-(i%10)/10==7 ){
                 continue;
             }
             arr7.push(i);
         }

    delete 删除某个 可以删除 但位置会保留 数组长度不会变
         delete arr7[0];
         console.log(arr7);

    练习3.数组去重
    法一双重for循环判断(从后边删除的)
         var arr11 = [1,2,412,4,51,312,4551,2,31,51,1,88];
         for (let i = 0; i < arr11.length; i++) {
             for (let j = i+1; j < arr11.length; j++) {
                 if(arr11[j]=arr11[i]){
                     arr11.splice(j,1);
                     j--;//arr11.length变化
                 }
             }
         }
         console.log(arr11);
          
    法二根据indexOf返回值是否为-1判断
         var arr11 = [1,2,412,4,51,312,4551,2,31,51,1,88];
         var newArr11=[];
         for(var i=0 ;i<arr11.length ; i++){  
             var res11 = newArr11.indexOf(arr11[i])
             if(res11 == -1){
                 newArr11[newArr11.length]=arr11[i]
                 continue;
             }
         }
         console.log(newArr11);

    法三前后索引对比(从前边删除的)
         var arr11 = [1,2,2,3 ];
         for (let i = 0; i < arr11.length; i++) {
             if(arr11.indexOf(arr11[i]) != arr11.lastIndexOf(arr11[i])){
                 arr11.splice(i,1);
             }
         }
         console.log(arr11);

    法四indexOf索引与下标对比
         var arr11 = [1,2,2,3 ];
         for (let i = 0; i < arr11.length; i++) {
             if(arr11.indexOf(arr11[i]) != i){
                 arr11.splice(i,1);
                 i--;
             }
         }
         console.log(arr11);

11. 字符串

.split();将字符串分割为数组 返回分割后的数组 不会改变原来的数组 
        console.log(str2.split("人"), str2);//以"人"分割
        console.log(str2.split(), str2);
    模拟split():
     var str='fdj,kggd';
     var arr=split(str,',')
     console.log(arr,str);
     function split(str,substr){
         var res=[];
         var str_init = '';//空字符串
         str=str + substr;//给最后加逗号
         for(var i=0;i<str.length;i++){
             if(str[i]==substr){
                 console.log(str_init);
                 res.push(str_init);
                 str_init = '';
                 continue;
             }
             str_init = str_init + str[i];
         }
         return res;
      } 
.slice(start,end);截取 不包括end 返回截取的字符串 不影响原字符串  第一个数如果为负数,从后往前查
        console.log(str2.slice(0, 2), str2);
        console.log(str2.slice(2), str2);
        console.log(str2.slice(-4), str2);
    模拟slice():
     var str = slice('dfsfsdfdsfs',1,3);               
     function slice(str,start,end){
         var res = '';
         for(var i=0 ; i<str.length ; i++){
             if(i>=start && i<end){
                 res = res + str[i];
             }
         }
         return res;
     }
.substr(from,count) 截取 (从哪里开始 , 截取几个) 返回截取下来的字符串 不影响原字符串
    console.log(str2.substr(2, 3), str2);
.substring(start,end)  截取 不包括end 第一个参数如果为负数还是从0开始
       console.log(str2.substring(1,3));
       console.log(str2.substring(-1000));

.sort排序 会改变原数组 有返回值 返回拍好的数组 默认从小到大升序 
     var res=arr.sort();//把数组里面的元素当成了字符串 按unicode码 ascii码 英文字符 数字 英文小写 汉字 中文字符
     console.log(res);

 for循环遍历字符串
        var str = '123456789';
        for (let i = 0; i < str.length; i++) {
            console.log(str[i]);
        }

 字符串拼接
        var str1 = "1"; var str2 = "2"; var str3 = "3";
        console.log(str1 + str2 + str3);

.concat 拼接 连接 字符串
        var res1 = "你好".concat(str1, str2, str3);
        console.log(res1);

 indexOf和lastIndexOf 跟数组中的用法是一致的
        var str1 = "撒娇女人最好命";
        console.log(str1.indexOf("女女"));//-1
        console.log(str1.lastIndexOf("撒娇"));//2

.replace()替代 替换 有返回值 返回替换后的字符串 替换多个相同的字符的话 智能替换第一个 不改变原来的字符串
        var str2 = "男人得有钱";
        console.log(str2.replace("有钱", "^^"), str2);//只替换一个$,别的符号例外   且只能替换第一个匹配的"有钱""
.replaceAll()存在兼容问题
        console.log(str2.replaceAll("钱", "//"), str2);//只替换一个$,别的符号例外 

        //建议用for循环一个个替换 , 或使用正则表达式替换
        // i不区分大小写 g全局匹配 m多行匹配
        console.log(str2.replace(/钱/g, "$"), str2);

    

    小练习:
	1.加密电话
        var num = "15188470181";
        var num1 = num.replace(num.substr(3, 4), "****");
        console.log(num1, num);

    2.大小写转换 原字符串不变
        var str4 = "sdggfgg";
        console.log(str4.toUpperCase(), str4);//变大写
        var str5 = "HJUYHIUIUIU";
        console.log(str5.toLowerCase(), str5);//变小写

    3.互相转换
        var str6 = "JAVAsCRIPT";

        var res = "";
        for (let i = 0; i < str6.length; i++) {
            var code = str6[i];
            if (code == str6[i].toLowerCase()) {
                res += code.toUpperCase();
            } else {
                res += code.toLowerCase();
            }
        }
        console.log(res);

   .trim(); 去除字符串两边空白符 不影响原字符
        var str7 = " 今天周三 ";
        console.log(str7.trim());//去掉两边空格
        console.log(str7.trimLeft());//去掉左边空格
        console.log(str7.trimRight());//去掉右边空格

es6 .includes(); 搜索字符是否存在 true存在 false不存在
        console.log(str7.includes("周三"));//false


.charAt(index) 通过索引值 找到指定位置的字符
        console.log(str7.charAt(3));//周

.starsWith().endsWith()判断字符串是否是以某个字符开头和结尾的 返回值true false
        console.log(str7.startsWith("周"), str7.endsWith("三"));//false

 isNaN判断是不是数字 数字:false 不是数字:true    
    //NaN:not a number 属于number类型 
    //NaN不等于任何值,包括他本身
        console.log(typeof ("1"));
        console.log(typeof ("g"));

        console.log(isNaN("1"));//false 1是个数字
        console.log(isNaN("g"));//true  g不是个数字

    练习: 长度11,开头1,全是数字,不符合则提示输入有误,正确则把手机号中间四位换成****
        var tel = prompt("请输入电话号码");
        if (isNaN(tel)) {//true不是数字 
            alert("请输入数字");
        } else {//false是数字
            if (tel.charAt(0) == 1) {//true是1开头 charAt和startsWith能判断字符串,但不能判断数字
                if (tel.length == 11) {
                    var tel1 = tel.replace(tel.slice(3, 7), "****");
                    alert(tel1);
                } else {
                    alert("长度不是11");
                }
            } else {
                alert("数字开头不是1");
            }
        }

12. Object对象

获取对象中所有键 返回一个由键组成的数组
        var keys=Object.keys(obj);
        console.log(keys);

获取值
        var values = Object.values(obj);
        console.log(values);

    小练习:判断obj1中是否存在eat这个属性
        var obj1 = 
        {
            name:"明",
            eye:2,
             hair:"black"
         }
         flag=false;//假设不存在
         for(var key in obj1){
             //var keys=Object.keys(obj1);//key数组
             // for (let i = 0; i < keys.length; i++) {
                 if(key=="eat"){
                     flag=true;
                     break;
                 // console.log("yes");
             }
             }
         }
        if (!flag) {
            console.log("不存在");
        }
        else{
            console.log("cunzai");
        }
        Object.keys(ogj1).indexOf('eat') == -1 ? alert("不存在") : alert("存在");

    
 声明对象  
        var obj={
            name:"老王"
        }
        var obj3= new Object(8);
        console.log(obj3);

 取属性值
        console.log(obj.name) ;
        console.log(obj["name"]) ;
        
 添加属性值
        obj.age="1";
        obj["hair"]="black";

 删除属性
        delete obj.hair;
        // console.log(obj);

 更改属性值
        obj.age=18;

        //对象有可扩展性 默认扩展性为true 
 检查是否有扩展性的方法: Object.isExtensible(obj);
        Object.isExtensible(obj); 

 阻止拓展 禁止给对象添加新属性 但可以修改和删除属性 Object.preventExtensions()
        Object.preventExtensions(obj);

 冻结 Object.freeze() 无法添加修改删除
        Object.freeze(obj);

13. 函数

1. 函数的定义

        // 函数:也叫做方法,它的作用主要就是用来封装重复的代码,来达到代码复用的效果
		function func1 () {
			alert('我是func1')
		}
		func1(); 

		// 匿名函数/函数表达式  通过一个变量来接收函数
		var fn2 = function () {
			alert('我是fn2');
		};
		console.log(fn2); //此时fn2是一个函数表达式
		fn2(); 

2. 函数的参数

        // 函数中的参数:实参和形参,实际参数、形式参数
		// 形式参数:在定义函数时,写在括号中的自己定义,每个形参之间用逗号隔开
		function add (a, b) {
			// 在函数中就要使用这两个形式参数;
			return a + b;
		}

		// 实际参数:在调用函数时,写在括号中的参数;
		console.log(add(1, 2));
		console.log(add(123, 4124));

3. 作用域

变量状态:声明变量 给变量赋值 使用变量
判断使用的是那一个变量:在当前作用域中查找,是否声明,如果声明,找最近一次的赋值
        // 作用域:全局作用域和局部作用域
		// 全局作用域:范围指的整个script代码块中
		var a = 1;

		// 局部作用域/函数作用域:声明在函数内部的变量,只能在函数中使用,函数内的变量在函数执行时才声明
		function f1 () {
			var b = 2;
			console.log(a);
			console.log(b);
		}
		f1();
		//console.log(b); //Uncaught ReferenceError: b is not defined

		function f2 (params) {
			var a = 10;
			// 当访问一个变量时,会优先在自己的作用域中寻找,如果没有,就往上找;
			console.log(a);
		}

		f2();
		console.log(a);
	// 全局作用域(整个script标签或一个单独的js文件 或 函数内部没有声明直接定义的变量) 
    // 局部作用域/函数作用域(函数内部的名字只在函数内部起作用 函数形参也是局部变量 function max (a,b)这种函数默认是全局变量)
    	 console.log(qqq);//访问不了
    	 function jisuan(){
    	     console.log(ppp);
    	 }    
    	 var qqq = 1;      
    	 console.log(ppp);//访问不了
    // 变量会提升声明但不提升值,函数如果是变量形式也会同样提升,函数如果是函数命名形式会将内容一并提升

4. 变量提升

// 变量提升
		var a;
		console.log(a); // undefined

		var a = 100;

		// 函数提升
		f1();

		function f1 (params) {
			alert('我是f1')
		}

// add(3,4);//变量命名的函数前面不能调用,函数不提前  匿名形式的提前能调用
//函数表达式(匿名函数)  add是变量不是函数名 
       function add(a,b){//形参可看做不用声明的变量    
         console.log(a+b);
         }
         add(1,2,3);//实参多于形参的不参与计算
         add(2);//2+undifind  结果是NaN

5. arguments

argumnets对象,接收所有传入的实参,是一个类数组,可以通过索引去获取到传入的参数,只能在函数体内使用 与数组的区别是没有数组的一些方法如pop
        function f1 (a, b, c) {
			console.log(a, b, c);
			// argumnets对象,接收所有传入的实参,是一个类数组,可以通过索引去获取到传入的参数,只能在函数体内使用
			console.log(arguments, arguments[3]);

			// instanceof 用来判断引用类型Function Object Array
			console.log(arguments instanceof Math);
			var arr = [1, 2, 3];
			console.log(arr instanceof Array);
		}

		f1(1, 2, 3, 4, 5, 6, 7, 8);
		f1(1);
		// 形式参数的作用主要就是为了接受调用函数时,传入的实际参数
		/*
			当实际参数的个数<形式参数时,从左开始接受,多余的显示为undefined
			当实际参数的个数>形式参数时,那么形式参数就按照实际参数从左到右的顺序接收,多余的则不再接收
		*/

6. 回调函数

将一个函数当成另一个函数的实参,这个作为参数的函数就叫做回调函数,callback;
		// sayName为回调函数
		function sayName (name) {
			alert('Hi,' + name);
		}
		function f1 (func, value) {
			console.log(func);
			func(value);
		}
		f1(sayName, 'Jack');
		sayName('jack');

7. 函数构造对象

//函数构造对象
	 function Star(uname,uage){
	     this.name = uname;
	     this.age = uage 
	 }
	 var ldh = new Star("刘德华",18);
	 console.log(ldh.age);

8. 定时器和延时器

setInterval(callback,time);
定时器:每隔多少秒,执行一次callback中的代码;
一直执行

var res = setTimeout(callback, timeout);
延时器:设置一个时间delay,推迟多少秒执行这个代码;
只执行一次,写在函数里面也可实现setInterval的效果
慢执行程序,不阻塞下面程序
clearTimeout(res),注意是否全部清空
返回值 执行的第几个setTimeout

性能优化:把所有延时程序的返回值加到Timer数组中,在程序结束之前找到一个点,遍历Timer清空所有的延时程序

//性能优化:     
var timesr = []//保存所有setTimeout的id值
        var id = setTimeout(function () {
            console.log(2);
        }, 1000)
        timesr.push(id)

        for (var i = 0; i < 3; i++) {

            var res = setTimeout(function () {
                console.log(i) // 3 3 3
            }, 5)
            timesr.push(res)
        }

        function foo() {
            timesr.push(setTimeout(function () {

            }, 10))
        }

        if (true) {
            var res_ = setTimeout(function () {

            }, 10)
            timesr.push(res_)
        }

        for (var j = 0; j < 91; j++) {
            var id_= setTimeout(function () {

            }, 10)
            timesr.push(id_)
        }

        console.log(timer)
        timesr.push(setTimeout(function(){
            for(var i=0;i<timer.length;i+++){
                clearTimeout(timer[i])
                console.log(1)
            }
        },1001))
for(var i=0;i<3;i++){
    setTimeout(function(){
        console.log(i);
    },1000)
    //打印3 3 3
    //变量污染
}
//程序是自上而下的快执行,慢的程序默认在快的程序后面执行,注意当慢程序执行时,快程序中变量的值是什么

//解决变量污染,使用闭包
for(var i=0;i<3;i++){
    (function(i){
        setTimeout(function(){
        console.log(i);
        },1000)
    })(i)
    //打印0 1 2
}
    //每秒页面上输出一次:距离2022年3月1日还有xx小时xx分钟xx秒,小时可以超过24,分钟不能超过60,秒不能超过60;

    //法一 setInterval(function(){},1000);
        var h;
        var m;
        var s; 
        var aaa='2022/3/1';
        setInterval(function(){
            var now = new Date();
            var future = new Date(aaa);
            var nowSecond = Date.now();//当前时间戳
            var futureSecond = future.getTime(future);//2022.3.1时间戳
            var timeDeffierence =  futureSecond - nowSecond//时间戳差值
            h =parseInt(timeDeffierence/1000/60/60) ;//时
            m =parseInt(timeDeffierence/1000/60%60) ;//分
            s =parseInt(timeDeffierence/1000%60) ;//秒
            num.innerText = `距离2022年3月1日还有${h}小时${m}分钟${s}秒`;
        },1000);    
        
    //法二  setInterval("time('2022/3/1')",1000); 
        var h;
        var m;
        var s; 
        setInterval("time('2022/3/1')",1000); //回调函数有参数时需要用引号包括  没有参数时直接setTimeout(Timer,1000); 
        function time(aaa){
            var now = new Date();
            var future = new Date(aaa);
            var nowSecond = Date.now();//当前时间戳
            var futureSecond = future.getTime(future);//2022.3.1时间戳
            var timeDeffierence =  futureSecond - nowSecond//时间戳差值
            h =parseInt(timeDeffierence/1000/60/60) ;//时
            m =parseInt(timeDeffierence/1000/60%60) ;//分
            s =parseInt(timeDeffierence/1000%60) ;//秒
            num.innerText = `距离2022年3月1日还有${h}小时${m}分钟${s}秒`;
        }   

        
    //法三  setTimeout("time('2022/3/1')",1000);
        var h;
        var m;
        var s; 
        function time(aaa){
            var now = new Date();
            var future = new Date(aaa);
            var nowSecond = Date.now();//当前时间戳
            var futureSecond = future.getTime(future);//2022.3.1时间戳
            var timeDeffierence =  futureSecond - nowSecond//时间戳差值
            h =parseInt(timeDeffierence/1000/60/60) ;//时
            m =parseInt(timeDeffierence/1000/60%60) ;//分
            s =parseInt(timeDeffierence/1000%60) ;//秒
            num.innerText = `距离2022年3月1日还有${h}小时${m}分钟${s}秒`;
            setTimeout("time('2022/3/1')",1000);
        }   
        time('2022/3/1');

14. 深拷贝 浅拷贝

    //深拷贝 复制一个变量 当改变一个变量时 对另一个的变量没有影响
        var a=1;
        var b=a;//a或b改变 另一个不改变
        a=3;
        b=4;
        console.log(a,b); 

    //浅拷贝 复制一个引用类型的变量 当改变一个变量中的属性时 另一个变量也会跟着变化
        var obj={
            name:"王"
        };
        var obj1=obj;//改变obj或obj1 另一个也改变
        obj.age=20;

	//对象数组深拷贝: 
    //若果想要实现引用类型的深拷贝 就可以使用遍历把一个对象或数组中每一个值复制到另一个变量中
        var obj2={};
        for(var key in obj){
            obj2[key] = obj[key];
        } 
        obj.age = 30;
        obj2.name = "李";
	
    //基本数据类型变量和值都存在栈中,
    //引用数据类型变量和值的指针存在栈中,真正的值存在堆中 指针指向堆中值的地址

15. unll undefined区别

undefined在内存中占据了空间,没有赋值
null没有占据空间
优化内存,吧不使用的变量使用null清空

16. 有var变量和没var变量的区别

var声明的变量可以在当前作用域中任意位置都能使用,其作用是将变量提升到当前作用域顶端
没用声明的变量需要先有再使用

17. not defind和undefined

is not defined 报错原因:没有发现变量 
eg: console.log(a); a=2;

undefined 有var变量但没有值 
eg:console.log(a);var a=2;

18. 数据结构

  • 队列
  • 集合
  • 链表
  • 字典

当一个数组或者对象,具备某种特殊规律的时候,就形成了数据结构

栈(基本类型数据)

先进后出(进,将数据添加到数据中;出,将数据从中删除)存基本类型的变量和值,引用类型的变量和指针

基本数据类型是独立的

堆(引用类型数据)

存引用类型的值

1646790853943

拷贝

让一个变量给另一个变量赋值的过程叫做拷贝

拷贝结果:两个变量的数据一模一样

  • 深拷贝:(基本类型都是深拷贝)

  • 浅拷贝:(默认情况,引用类型都是浅拷贝)

  • 对象数组深拷贝:

队列

先进先出

// 队列 模拟等待执行的任务
        var quen=[];
        quen.push('任务一')
        quen.push('任务二')
        quen.push('任务三')
        //先执行完毕的 先推出
        quen.shift()
        quen.shift()
        quen.shift()

执行上下文

执行上下文栈(执行:执行的代码,上下文:理解为对象,栈:数组)
模拟js引擎执行过程:
1.创建执行上下文栈,运行js代码
2.创建全局的执行上下文 global
3.全局的执行上下文添加到 [执行上下文栈]中
4.全局的开始运行
5.遇到函数代码执行,创建一个函数执行上下文
6.将函数执行上下文 添加到 执行上下文栈中
7.函数执行完毕 将执行上下文 推出 执行上下文
8.函数销毁 js通过进栈与出栈方式完成程序运行 浏览器关闭, global出栈 --> golbal销毁 --> 栈销毁

预编译

语言分析

检查是否有语法错误 (SynataxError unexpected token)

预编译(针对函数执行)

简单理解就是在内存中开辟一些空间,采用南方一些变量与函数

    1. 创建go(global object)对象 也是 全局执行上下文
    1. 将全局中 var function 定义的变量和函数,作为go的属性,也叫做变量提升,函数声明提升

函数执行时

  1. 创建AO
  2. 形参 和 变量提升, 值都为undefined
  3. 将实参赋值给形参(形参和实参相统一)
  4. 在函数体内找函数声明, 值赋予AO函数名
       function foo(){
            var a = 213
        //     ao:{
        //     arguments:{
        //         length:0
        //     }
        //     a:123
        //     b:function
        //     d:unfined
        // }
        
            function b (){}
            var d = function(){}
              //     ao:{
        //     arguments:{
        //         length:0
        //     }
        //     a:123
        //     b:function
        //     d:function
        // }
        }
        foo() // 执行完毕  AO销毁
        /*
        ao:{
            arguments:{
                length:0
            }
            a:undefined
            b:function
            d:unfined
        }
        */
        // 练习 编译过程
        
        // 5 
        // 代码开始执行前
        // 代开浏览器
        // 创建执行上下文栈
        /*var EackStack= [];*/
        // 创建全局上下文GlobalContext
        /*var GlobalContext = {
            scope
            this
        }*/
        // 添加到执行上下文栈中
        /*EackStack.push(GlobalContext)*/

        // 变量提升 函数声明提升
        /*
          GlobalContext = {
              scope
              this
              a:undefined
              b:undefined
              foo:function
              f : undefined
              d:undefined
          }
        */
        // 开始执行:
        var a = 123;
        /*
      GlobalContext = {
          scope
          this
          a:123   (undefined-->123)
          b:undefined
          foo:function
          f : undefined
          d:undefined
      }
    */
        b = 234
        /*
      GlobalContext = {
          scope
          this
          a:123   (undefined-->123)
          b:234   (undefined-->234)
          foo:function
          f : undefined
          d:undefined
      }
    */
        var b = 123;
        /*
      GlobalContext = {
          scope
          this
          a:123   (undefined-->123)
          b:132   (234-->123)
          foo:function
          f : undefined
          d:undefined
      }
    */
        function foo() {
            // 创建 fooContext
            // 形参 函数 变量提升
            /*
              var fooContext = {
                  scope
                  this 
                  c:undefine

              }
            */
            // 添加到执行上下文栈中
            /* EackStack.push(fooContext) */
            c = 456;
            /*
             var fooContext = {
                 scope
                 this 
                 c:456

             }
           */
            var c = 123;
            /*
             var fooContext = {
                 scope
                 this 
                 c:123

             }
           */
            b = 456
            /*
        GlobalContext = {
            scope
            this
            a:123   
            b:456   (234--->456)
            foo:function
            f : undefined
            d:undefined
        }
      */
            if (b) {
                c = a;
                 /*
             var fooContext = {
                 scope
                 this 
                 c:123 (123-->123)

             }
           */
            }
        }
        // 函数执行完毕  fooContext 移除 执行上下文栈 函数中变量销毁
        /*EackStack.pop()*/
        foo(1,2)  // 开始执行前创建fooContext
        var f = d;
            /*
        GlobalContext = {
            scope
            this
            a:123   
            b:456   (234--->456)
            foo:function
            f : undefined  (undefined ---> undefined)
            d:undefined
        }
      */
        var d = function () {
            console.log(f)
        }
             /*
        GlobalContext = {
            scope
            this
            a:123   
            b:456   
            foo:function
            f : undefined 
            d: function  (undefined --->function)
        }
      */
        d() // 开始之前  创建 dContext 

解析执行

对上下文 对象属性重新赋值的过程

面试:预编译

预编译发生在函数执行前,创建AO对象,形参,变量,函数 声明提升,形参实参相统一,最后解析执行

19. 验证一个字符是否存在

for if
str.indexOf()

20. 验证一个字符串片段是否存在

indexOf()
正则表达式

21. js为什么基于对象

    • 声明的变量或函数,都变成了window属性,window是一个对象
    • 学习的都是js内置对象,以及对象下的api
    • 函数 模拟api方式实现函数应用
    • 常见数据处理 封装函数
  • 学习api思路:
    • 知道是哪个对象下的
    • api的作用效果
      • 复制示例代码查看运行结果,推测作用
    • api实参是做什么的
      • 参数是回调函数
      • api中回调函数自动执行,可能多次可能单次
      • 回参的值是什么
      • return 的作用是什么(相对api来说意义是什么)
    • api的反回值
    • 总结什么情况下可能用到
    • 深入 完成api模拟

22. 封装函数思路

  • 0.确定函数名
  • 1.确定作用是什么
  • 2.确定是否有返回值 有( 确定返回值是什么类型的数据)
    • 告诉外界,函数运算结果是什么
    • 如果是字符串,初始化空字符串 return
    • 数组,初始化空数组 return
    • 对象,初始化空对象 return
    • num,初始化0 return
    • bool,初始化true false return
    • 不知道,初始化null return
  • 3.确定形参
  • 4.根据外界提供的数据以及预期输出的结果 完成方法体中编码
    • 分析原始值是什么 输出什么
    • 怎样从你能输出预其
    • 在做业务中,缺内容就声明变量
    • 先写一个静态的
    • 在用代码代替静态的
    • 在想多个的时候,怎么输出多个结果
    • 在想多个静态的,怎么动态
    • 再重复的代码找规律 ,用代码实现找到的规律

23. 闭包

  • 闭包语法
         function foo(){
             var i=0;
             i+=1;
             bar()
        //bug问题:为什么return 可以调用bar函数 ; 有了return bar is not defined
        //return可以将bar属性从fooContext中删除 , 相当于只有匿名函数
             return function bar(){
                 console.log('bar run');
             }
         }
  • 闭包特点
        //程序一
        function foo(){
            var i=0;
            var b = 0;//没有销毁
            return function(){
                i+=1;
                console.log(i);
            }
        }
        //1.函数内部的变量没有被销毁 AO 对象没有被销毁
        var a = foo()
        a()
        a()
        //2.外面的函数执行多次 彼此独立 
        //3.执行多次 形成多个独立 AO 对象
        var b = foo()
        b()
        b()
        //i没有销毁 因为在未来程序中 随时可能需要i变量
        //已知 函数执行结束函数中的变量销毁  
        //原因:接下来不需要使用了,所以就销毁了

        //程序二
        function foo1(){
            var i=0;
            function bar(){
                i+=1;
                console.log(i);
            }
            bar()
            bar()
            bar()
        }
        foo1()
        foo1()
             
        //程序1中内部函数未来随时可能被触发 
        //程序二中内部函数 当外部函数执行结束 内部函数销毁

        //重点:闭包相似程序的区分
        //一个变量在什么情况下会被销毁: 用不到时销毁
闭包 : 当一个函数a return返回另一个函数,那么这个函数a就是闭包函数
优点:
1.防止变量污染  
---> 闭包在执行时彼此独立互不干扰
2.外部函数可以访问内部函数的变量(错误的观点)
---> 外部的变量只是引用了闭包函数内部的retrun函数,在作用域链的角度上,没有违背,函数变量有化的原则
缺点:容易内存泄漏  
--->正常情况函数执行结束 变量释放, 因为闭包函数中变量未来可能你会被其他程序引用 ,所以不会销毁, 占据了内存
  • 解决变量污染 ,就是让return 返回的函数在全局下标记清除法 实现零引用
        function foo(){
            var i=0;
            var b = 0;
            return function(){
                i+=1;
                console.log(i);
            }
        }
        
        var a = foo()
        a()
        a()

        a=null

        //或者让闭包函数是一个立即执行函数
        (function(){
            return function(){

            }
        })()

24. this

this是一个关键字 正常情况下 赋值对象
    在不同情况下赋值不同

    this判断
    1.看this写在哪里
    --->全局 this===window
    --->函数 看第二步

    2.是什么函数
    --->如果是function函数

    3.看函数是如何触发的
    --->call apply bind this===三个函数的实参一   
    --->new this===new 创建的对象那个
    --->事件 this===出发时间的dom元素
    --->难点: 普通对象触发 this===普通对象
        //this 练习1    
        var o={
            a:10,
            b:{
                name:function(){
                    return this;
                },
                zzz:'1'
            }
        }  
        var x=o.b.name();           
        console.log(x); //{zzz: '1', name: ƒ}    
        
        //练习2
        function Animal(name,age){
            console.log(this);
            //Animal {}
            // age: 2
            // name: "mao"
            // 构造函数中的this指向的是实例对象
            this.name = name;
            this.age = age;
        }
        var cat = new Animal('mao',2);

25. new

构造函数  构造的函数叫构造函数(实例化对象)
作用:创建对象
构造函数不能有return 因为new自带了return一些效果
        function Animal(name,age){
            console.log(this);
            // 构造函数中的this指向的是实例对象
            this.name = name;
            this.age = age;
        }
new  
作用:触发函数
返回对象
        var cat = new Animal('mao',2);
        console.log(cat);
        // Animal {name: 'mao', age: 2}
        // 获取构造函数
        console.log(cat.constructor);
        // ƒ Animal(name,age){
        //     console.log(this);
        //     // 构造函数中的this指向的是实例对象
        //     this.name = name;
        //     this.age = age;
        // }
        console.log(Animal.constructor);
        // ƒ Function() { [native code] }
        // 函数的构造函数是Function
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

几个高兴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值