JS学习笔记2

 数据类型转换  (强制类型转换 和 隐式类型转换)

  强制类型转换的方法  String()  Number()  Boolean()

    // String()     把其他类型转化为字符串类型

    // Number()     把其他类型转化为数字类型

    // Boolean()    把其他类型转化为布尔类型

String()     把其他类型转化为字符串类型 (将数据包裹到字符串中即可)

    // console.log(String("hello")); // "hello"

    // console.log(String(100)); // "100"

    // console.log(String(true)); // "true"

    // console.log(String(false)); // false

    // console.log(String(null));  // "null"

    // console.log(String(undefined)); //"undefined"

Number()     把其他类型转化为数字类型

    // (1)  纯数字类型的字符串 => 直接转数字

    //      非纯数字类型的字符串 => NaN

    // (2)  true转数字类型 1   false转数字类型0

    // (2)  null转数字类型0  undefined转数字类型NaN 

    // var result = Number("100");  // 先存储转化后的结果

    // console.log(result);   // 打印结果

    // console.log(1 / 0);  // Infinity (正无穷)    

    console.log(Number("100"));

    console.log(Number("hello"));  // NaN  (not a number => 表示非数字(结果不是一个数字))

    console.log(Number("100px"));  // NaN  (not a number => 表示非数字(结果不是一个数字))

    console.log(Number(10));  

    console.log(Number(true));  

    console.log(Number(false));  

    console.log(Number(null));  

    console.log(Number(undefined));

 Boolean()    把其他类型转化为布尔类型

    "" 0 NaN false null undefined 转布尔值为false,其他的均为true

    // console.log(Boolean("100"));  // true

    // console.log(Boolean("hello")); // true

    // console.log(Boolean(" "));  // true

    // console.log(Boolean(""));  // false

    console.log(Boolean(100));  // true

    console.log(Boolean(1));  // true 

    console.log(Boolean(Infinity));  // true

    console.log(Boolean(0));  // false

    console.log(Boolean(NaN));  // false

    console.log(Boolean(null));  // false

    console.log(Boolean(undefined));  // false

隐式类型转换

算术运算符的隐式类型转换

    //  (1) 算术运算符 常用于做数字运算

    //  (2) 当其他类型参与算术运算时,会发生隐式类型转换

    //      a.字符串遇到 "+" 会拼接形成新的字符串 (字符串拼接)

    //      b.字符串遇到 "- * / %" 会先隐式转化为数字, 在参与运算

    //        其中:纯数字类型的字符串 => 直接转数字

    //            非纯数字类型的字符串 => NaN  (NaN 和 任何数运算得到的结果均为NaN)

    //      c. 布尔值遇到算术运算符,会先隐式转化为数字, 在参与运算  =>   true转数字类型 1   false转数字类型0

    //      d. null undefined 遇到算术运算符,会先隐式转化为数字, 在参与运算 => null转数字类型0  undefined转数字类型NaN 

  小结: 除字符串遇到"+"会拼接形成新的字符串外,其他数据均会先会先隐式转化为数字, 在参与运算

关系运算符的隐式类型转换  (>  >=   <  

    // (1) 字符串,布尔值和数字比较时,会先隐式转化为数字,在参数比较

    // (2) 字符串 和 字符串 比较时, 依次比较字符对应的ASCII码(unicode码)  => 第一个字符不同就比较第一个,第一个相同就比第二个

    // (3) null 和 undefined 遇到 > >= < 

    //     null 和 undefined 遇到 ==  != 时,  不会转化而是直接比较(没有可比性)

    // (4) null 和 undefined 在数值上是相同的(官方规定)

    // (5) NaN和其他数据没有可比性, 和任何值比较都是false  => NaN != NaN

++ --的隐式类型转换

//其他数据类型遇到++和--也会先隐式转化为数字类型,再自增或自减

程序的三大流程控制

    // 顺序结构:  代码自上而下 依次执行

    // 选择结构:  根据不同的情况,执行对应代码

    // 循环结构:  重复的做一件事

    // 表达式  => 由运算符和操作数组成的式子

    // 运算符:  算术  关系  逻辑  赋值

    // 操作数:  变量和常量(常规数据(也叫字面量/直接量) -> 基本数据,无需声明可以直接使用)  

    // 字面量 直接量

    // 100

    // "hello"

    // true

    var a = 10;

    a + 5  ; // 算术表达式

    a > 5  ; // 关系表达式(条件表达式->单)

    a > 5 && a < 20; // 逻辑表达式(条件表达式->多) 

    a 

    5

选择结构:  if

        单分支:  爱走不走,不走拉倒

            if(表达式){

                执行语句;

            }

            首先求解表达式, 当括号内的表达式结果成立(为true时),则执行大括号内的语句,否则不做任何操作,继续执行后续的代码。

            括号里的表达式一般是关系表达式或者逻辑表达式(如果表达式的结果不是布尔值,会隐式转化为布尔值,在判断)

        双分支: 二选一,必须选一个

            if(表达式){

                执行语句1;

            }else{

                执行语句2;

            }

            首先求解表达式,括号内的表达式结果成立(为true时),则执行if之后大括号内的语句1, 否则执行else后大括号中的语句2;

        多分支: 比如填报志愿

            if(如果清华北大录取我?){

                去清华北大;

            }else if(武汉科技大学录取我?){

                去武汉科技大学;

            }else if(武汉工程大学录取我?){

                去武汉工程大学;

            }else if(如果江西软件大学录取我?){

                去江西软件大学;

            }else{

                家里蹲大学;

            }

            if(表达式1){

                执行语句1;

            }else if(表达式2){

                执行语句2;

            }else if(表达式3){

                执行语句3;

            }else{

                执行语句4;

            }

            首先求解表达式1, 如果表达式1成立,则执行语句1,语句1执行完毕,跳出当前选择结构,代码执行向后执行

                如果表达式不成立, 求解表达式2,依此类推,全都不成立就走else后大括号中的语句;

            从上往下,满足哪个条件就执行其相对应的语句,都不满足时,执行最后的else的语句,只能进入其中之一。

            多分支至少是三分支  if...else if...else

选择结构的嵌套:  在满足特定条件的情况下,进行二次判断
断点调试:

    // 目的: 让代码执行到某个位置后停止, 后续手动操作代码一步一步向后执行

    // 如何使用断点:

    // (1)  哪里不会点哪里?   => 打断点(debugger)

    // (2)  打开页面 => 开发者工具 => source(资源)  => 找到断点所在位置

    // (3)  触发断点 =>  让页面中的代码重新执行 (因为页面加载时,代码默认执行完毕)

    //     a. 如果断点所在的代码在页面加载时执行 => 刷新页面

    //     b. 如果断点在事件中, => 触发事件(点击事件)

    // (4) 如何让代码继续向后执行

    //    F9  F10  F11  => 代码继续向后执行一步 (fn + F9)

    //    F8  恢复脚本执行   => 代码继续向后自动执行 (结束断点或跳到下一个断点所在位置)

    // (5) 代码调试完毕 => 删除/注释debugger

选择结构 switch =>  多分支

        switch(表达式){

            case 常量1: 执行语句1; break;

            case 常量2: 执行语句2; break;

            case 常量3: 执行语句3; break;

            case 常量4: 执行语句4; break;

            default: 

                执行语句5; 

                break;

        }

        switch中的表达式一般是一个变量, 在case中列举出所有变量可能出现的情况, 执行对应的语句,语句执行完毕跳出当前选择结构, 

        执行流程: switch中的表达式(变量),依次和case中的常量(字面量/直接量)做全等(===)比较,如果

        结果为true,则执行对应的语句,语句执行完毕跳出当前选择结构, 否则继续向后比较,以此类推,全都不满足就执行default之后的语句

 break的作用是跳出当前的选择结构, 如果不添加break,会进行执行后续分支中的执行语句,而不进行判断(switch穿透/case穿透)

        小结: 

        if 一般常用于做条件判断 (if中的表达式一般是一个条件表达式)

        switch 一般常用于做数值判断 (switch中接收一个变量,列举改变了所有可能出现的情况)

 三元运算符 /  三目运算符 (条件运算符)  => 简单的双分支

    // 语法:

    // 表达式1 ? 表达式2 : 表达式3;

    // 首先求解表达式1, 如果表达式1成立,则求解表达式2, 否则求解表达式3;

    // 常用于: 判断赋值

 循环结构  => 循:沿着  环: 圆 / 环   循环: 周而复始,循环往复

    // 循环就是重复做一件事

    // 在满足特定条件的情况下,重复的做一件事, 直到条件不满足为止

    // 常见循环

    // while

    // do...while

    // for

循环的三要素

    // (1) 初始值    (初始值 => 循环开始的位置)

    // (2) 循环条件  (满足条件就循环,否则就跳出循环)

    // (3) 自增/自减  (计数)

while循环

    // while(表达式){

    //     执行语句;

    // }

    // 首先求解表达式,如果表达式成立,则执行对应的循环语句(while对应的{}内的语句), 本次循环执行完毕, 再次求解表达式, 依次类推知道条件不满足位置

while循环流程图:

do...while循环  => 不论条件成立与否, 先执行一次,再判断 (冲动型)

        缺点: 即便条件不成立,也会执行一次

    do{

        执行语句;

    }while(表达式);

while和do...while的区别:

        while循环  => 先判断条件是否成立,条件成立再执行 (谨慎型)

        do...while循环  => 不论条件成立与否, 先执行一次,再判断 (冲动型)

while和do...while选择:

        一般情况下更倾向于使用while, 

        当while处理循环逻辑比较别扭时(先取值,在判断),使用do...while

while循环  => 先判断条件是否成立,条件成立再执行 (谨慎型)

    while(表达式){

        执行语句;

    }

for循环

while循环 => 先判断条件是否成立,条件成立再执行 (谨慎型) while(表达式){ 执行语句; } for循环 for(初始值;循环条件;自增/自减){ 执行语句; }

    for(初始值;循环条件;自增/自减){

        执行语句;

    }

    while循环 和 for循环

        while循环 每次循环执行完毕后继续求解表达式

        for循环 每次循环执行完毕后,会先自增/自减,然后在求解表达式 (好处:将循环三要素整合到一起)

    while循环和for循环选择:

        一般情况下,已知循环次数(循环三要素都知道),用for循环

        如果不知道循环次数, 可以选中while循环

while  do...while  for  之 常见死循环

    while(true){

    }

    while(true);

    do{

    }while(true);

    for(;;){

    }

    for(;;);

continue   循环关键词(仅能在循环中使用)

    // (1) 跳过本次循环进入下一次循环

    // (2) 位于continue之后的代码不执行(直接跳过本次,进入下一次)

break   循环的关键词

    // (1) 在switch中使用时表示跳出当前的选择结构, 在循环中使用表示跳出当前循环结构,循环会被终止

    // (2) 位于break关键词之后的语句 也不执行

    // (3) 如果存在循环嵌套, 一个break语句只向外跳一层(使用break的该层循环)。

判断一个数是不是素数。(除了1和它本身以外不再有其他的除数整除。)

 素数: 除了1和它本身以外不再有其他的除数除。  2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 

    // 7 =>  1 2 3 4 5 6 7 => 除了1和它本身以外  2 3 4 5 6  => 素数

    // 9 =>  1 2 3 4 5 6 7 8 9 =>  除了1和它本身以外  2 3 4 5 6 7 8  => 3(合数=> 非素数)

函数封装概念:

        函数就是把完成特定功能的一段代码抽象出来,使之成为程序中的一个独立实体,起个名字(函数名)。可以在同一个程序或其他程序中多次重复使用(通过函数名调用)。

        函数的定义语法:

        function 函数名(形参1,形参2,……){ // 函数可以没有形参

            执行语句;

            [return 返回值;]  //函数可以没有返回值(默认返回undefined)

        }

        函数名();

        函数封装的步骤:

        1. 要对封装的代码/功能足够熟悉(先完成特定功能的代码)

        2. 将完成特定功能的代码抽离出来, 放到函数中,并起一个函数名

        3. 把可变参数提取为形式参数(可以理解为也是一个变量)  => 形式参数是函数内和函数外交流的唯一入口 (可以接收函数调用时传入的实际值) 

        4. 确定函数的返回值 => 函数执行完毕之后返回的结果

        5. 如何调用函数?    

            函数名()

        关于形参(形式参数)和实参(实际参数)

        形参(形式参数):  形式参数是函数内和函数外交流的唯一入口 => 可以理解成是一个变量(存储数据),用于接收函数调用时传入的实际值

        实参(实际参数):  实际参数函数调用时实际传入的值 

        形参和实参一一对应

        关于函数的返回值

            (1) 返回值表示函数执行完毕之后返回的结果 => 可以由用户自行决定(根据需求)

            (2) 如果不设置返回值, 函数默认返回undefined (此处缺少一个值)

            (3) 返回值表示函数执行完毕之后返回的结果(函数的唯一出口) => 一个函数只能设置一个返回值, 表示函数执行完毕 => 位于return之后的语句不执行

        关于函数调用:

            (1) 对应函数名调用函数,如果函数不调用,函数中的代码不执行

            (2) 每次调用函数都会执行函数中的上下文 (从函数function对应的{}中的第一行 一直执行到最后一行)

函数的创建方式

    (1) 命名函数 (声明式创建)  => 函数创建过程中定义函数名,

      注意: 可以直接通过函数名获取函数, 函数不会被调用,输出的是函数封装的内容 (可以理解函数名类似变量名, 可以对应函数名查找该函数)  

     函数()

function sum(a,b){
        return a + b;
    }
    console.log(sum);
    var result = sum(1,2);
    console.log(result);
(2) 匿名函数  => 函数在创建时没有添加函数名, 无法通过函数名调用该函数

    匿名函数没有办法直接单独收声明

    function(a,b){  // 语法有问题 => 需要函数名

        return a + b;

    }

    (2.1)  赋值式 可以将匿名函数存储到变量 / 其他数据类型当中
var sum = function(a,b){
        return a + b;
    }
    console.log(sum);
    var result = sum(10,20);
    console.log(result);
将匿名函数存储到数组
// 将匿名函数存储到数组
    var arr = [1,2,function(a,b){
        return a + b;
    }];

    console.log(arr[2])

    var result = arr[2](100,200);
    console.log(result);
将匿名函数作为属性值存储到对象
// 将匿名函数作为属性值存储到对象
    var zhang = {
        name:"张三",
        age:18,
        sum:function(a,b){
            return a + b;
        }
    }
    console.log(zhang.sum);

    var result = zhang.sum(100,200);
    console.log(result);
绑定点击事件 => 元素被点击后执行对应的函数

绑定点击事件 => 元素被点击后执行对应的函数
    btn.onclick = function(){

    }
(2.2) 自执行函数(自调用函数)  => 匿名函数创建完毕之后立即调用, 此时匿名函数只能执行一次
(2) 自执行函数(自调用函数)  => 匿名函数创建完毕之后立即调用, 此时匿名函数只能执行一次

    var result = (function(a,b){ 
        console.log("函数执行了",a,b);
        return a + b;
    })(10,20);
    console.log(result);
3. 通过官方给定构造函数创建(了解)  =>newFunction("a","b","return a + b");

     注意: new Function执行过程中 最后一个实际参数是执行语句, 除最后参数以外的所有参数都是形式参数

通过构造函数创建对象的方式 => 实例化

被创建的对象也叫实例化对象

函数也是一个特殊的实例化对象

var sum = new Function("a","b","return a + b");   
    console.log(sum);

局部变量

    (1) 在函数内通过var关键词声明的变量叫做局部变量

    (2)  形参也是一个局部变量

    特征

    (1) 局部变量仅在函数内生效,对函数外没有任何影响

    (2) 函数中的局部变量和方法仅在函数内有效, 当函数执行完毕,对应的局部变量和方法都会被释放, 下次函数调用时会重新生成

全局变量

    (1) 在函数外(脚本中)外通过var关键词声明的变量叫做全局变量

    (2) 不通过关键词直接声明的变量,也是全局变量, 缺点: 没有变量提升

作用域: 代码生效的区域

    局部作用域(函数作用域) => 变量和方法仅在函数内有效

    全局作用域:  自当前script标签开始的任何位置均可访问

    局部变量和全局变量混用

    对于函数而言: (1)  访问自己作用域内声明的变量   (2) 可以访问全局变量   => 先后顺序

    函数内访问变量和方法的顺序

    (1) 自己有先找自己的 (访问自己作用域内声明的变量)

    (2) 自己没有,向外跳一层找父作用域(包裹函数的作用域 => 函数作用域/全局作用域)

    (3) 依此类推, 全都找不到,就找全局作用域, 全局作用域也找不到=> 变量/方法还未定义

arguments  参数集合

    (1) 函数的内置参数(所有的函数都有)

    (2) 用于存储函数本次调用时,所有实际参数的集合

arguments特征(同数组)

    (1) 有length属性,表长度(本次函数调用时,实际参数的个数)

    (2) 可以通过下标取值和赋值  (下标的最大值 = arguments.length - 1)

        如果取值取不到 默认返回undefined

    (3) 可以循环遍历

    作用: 参数不定项 ()

数组 => 一组数,一般放置一组相同类型的数(不同类型也可以)

如何创建数组?
(1) 字面量(直接量)创建 => 不经声明可以直接使用
var arr = [1,2,3];
    console.log(arr);
var brr = [];  // 空数组
    console.log(brr);
(2) 构造函数创建 =>  Array官方提供专门创建数组的方法

   

(2) 构造函数创建 =>  Array官方提供专门创建数组的方法
    var arr = new Array(1,2,3);
    console.log(arr);

数组的特征:

    (1) 有length属性,表长度(数组中元素的个数    元素/成员:组成数组的每项数据)

    (2) 可以通过下标取值和赋值  (下标的最大值 = 数组.length - 1)

        如果取值取一个不存在的下标 默认返回undefined

        如对一个不存在的下标赋值, 会新增该数组到数组中,如果存在空余下标,会用,分隔预留位置

    (3) 可以循环遍历

var list = [1,4,7,2,5,8,3,6,9];

    console.log(list);
    
    下标取值和赋值
    console.log(list[3]);
    list[3] = 22;
    console.log(list);
    
    
    console.log(list[100]);
    list[100] = 100;  // [1,4,7,2,5,8,3,6,9,,,,,,,,,,,,,,,,,,,,,,,,,,,,,....100];
    console.log(list);
循环遍历:
for(var i=0;i<list.length;i++){
        var item = list[i];
        console.log(item);
    }

数组的递增赋值

var list = [];
    for (var i = 1; i <= 100; i++) {
        if (i % 3 == 0 || i % 7 == 0) {
            // 怎么存?
            // list[0] = xxx;
            // list[1] = xxx;
            // list[2] = xxx;

            // 数组的递增赋值
            // 初始数组长度 len: 0
            // list[list.length] = 3;  // list[0] = 3;   len:更新1
            // list[list.length] = 6;  // list[1] = 6;   len:更新2

            // (1) 数组中新增元素后, lenth也会自动更新
            // (2) 下标的最大值 = 数组.length - 1      =>    数组.length = 下标的最大值 + 1  => 在数组中所有元素的最后方新增元素


            list[list.length] = i;
           
        }
    }
    console.log(list);

JS代码从加载到执行经过了哪些流程?

    1. 语法解析

=> 发生在代码执行之前,通篇排查脚本中是否存在语法错误(SyntaxError),如果有错,脚本将不会执行

    2. 预编译(预解析)  

=> 发生在代码执行之前,代码执行之前的准备工作

     (1) 脚本执行之前的预编译 (全局作用域)

        a.  变量提升   => 把(全局)变量声明提升到当前作用域最前面(当前脚本的最前面)

        b.  确定函数体(函数体提升  => 把(命名)函数的整个函数声明提前)

     (2) 函数执行之前的预编译 ()

        a.  变量提升   => 把(局部)变量声明提升到当前作用域最前面(当前函数作用域的最前面)

        b.  确定函数体(函数体提升  => 把(命名)函数的整个函数声明提前)  

        c.  把实际参数赋值给形式参数 => 形参和实参一一对应

    3. 解释执行  => 代码自上而下依次执行

   

    // 注意: 不通过关键词直接声明的变量,也是全局变量, 缺点: 没有变量提升

   

函数嵌套

    // 嵌套调用(在函数内调用另一个函数)

    // 嵌套封装(在函数内封装另一个函数)

    // 注意:

    // (1) 外层函数在执行过程中,调用内层函数

    // (2) 外层函数需要等待内层函数执行完毕后,才会继续向后执行

    // (3) 外层函数和内层函数都可以设置自己的返回值, 内层函数的返回值不会直接传递给外层

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值