# JavaScript

# JavaScript基础

历史

JavaScript:一门运行在(客户端)浏览器端的脚本 编程 语言

创造者 布兰登 艾奇 1995年利用10天完成JavaScript设计 脚本:戏剧的剧本。只要按照固定的流程走一遍,就可以把整部戏演完了。但是如果中间有演员出事了,戏就暂停了。这个脚本指的是JavaScript的一个特点:如果执行到某一行出错了,后面的就不会再继续执行了

# JavaScript的组成

  1. ECMASCRIPT: 定义了javascript的语法规范,描述了语言的基本语法和数据类型
  2. BOM (Browser Object Model): 浏览器对象模型
  • 有一套成熟的可以操作浏览器的 API,通过 BOM 可以操作浏览器。比如: 弹出框、浏览器跳转、获取分辨率等
  1. DOM (Document Object Model): 文档对象模型
  • 有一套成熟的可以操作页面元素的 API,通过 DOM 可以操作页面中的元素。比如: 增加个 div,减少个 div,给div 换个位置等 总结: JS 就是通过固定的语法去操作 浏览器 和 标签结构 来实现网页上的各种效果

# 引入方式

  • 内嵌式:demo学习阶段的主要写法
<script>
  alert('hello world');
</script>
  • 外链式:新建一个JS文件,文件里JS的代码,引入HTML页面内;作为个文件可以重复使用,项目开发阶段使用;

     <script src="./01-demo.js"></script>
    
    • 行内式:了解,一般不用
    <input type="button" value="点我" onclick="alert('helloworld')">
    

# JS 注释

  • 语法:注释更好的屡清楚你的业务逻辑;不会执行
// alert('hello world');  单行注释,一般就是简单的做个说明

/*
* 多行注释
* 一般把想要注释的内容写到这里面来,大段内容;不能 嵌套使用;
*/

# 输入输出

  • 作用:交互的简单入口,可以给页面输入我们想要输入的信息,页面输出一定的信息;为了与你写的代码更好交流和调试;

  • 输入:页面中弹出 输入框,需要输入内容后才能继续;开发不常用,我们只是为了配合学习;

// 弹框
        alert('弹框');
        // 带输入框的弹框
        prompt('带输入框的弹框');
        // 控制台输出(打印)
        console.log('控制台输出');
        // 逗号隔开可以输出多个内容
        console.log('西游记', '三国演义');
        // 在页面输出标签文字
        document.write('在页面上输出');
        document.write('<strong>哈哈哈来点字</strong>');

# 变量

注意:

  1. 一个变量名只能存储一个值
  2. 当再次给一个变量赋值的时候,前面一次的值就没有了
  3. 变量名称区分大小写(JS 区分大小写)
  // 声明变量  变量的作用是存储数据
        // var a;
        // 变量赋值 = 赋值运算符 把右边的数据存储到左边的变量里面去
        // a = 10;
        // 变量声明并赋值 变量的初始化
        // 弱数据类型
        // var a = 10;
        // var b = '哈哈哈';
        // var n1 = 100;
        // var n2 = 200;
        // console.log(n1 + n2);
        // 把用户输入的信息存储到变量里边去
        // var age = prompt('请告诉我您的芳龄');
        // console.log(age);
        //  变量可以多次赋值
        // var name = '孙悟空';
        // var name = '猪八戒';
        // console.log(name);
        // var num3 = 50;
        // 把右侧的结果赋值给左边的num3
        // num3 = num3 + 1;
        // console.log(num3);

# 交换变量的两种方法

   // 需求a=6;b=5;
        // 思路 定义一个第三方变量c 先把a变量的值赋给c,再把b的值赋值给a,把c的值赋值给b
        var a = '老孙';
        var b = '老猪';
        var c = a;
        a = b;
        b = c;
        console.log(a);
        // 交换数字变量
        // 思路2 求和 a=a+b 已知a+b的和11还有b是6
        var a = 5;
        var b = 6;
        a = b + a;
        b = a - b;
        a = a - b;
        console.log(a);

# 同时声明多个变量

//1 变量可以一次性声明多个
var a,b,c,d;

// 2 还可以声明多个的同时进行赋值;
var a = 10;
var a = 10,b = 20,c = 30;


//3 变量也可以作为另一个变量的值
var a = 10;
// 赋值给b(复制了一份),a再次变化时,b不受影响;
var b = a;

# 命名

  • 范围:字母、数字、下划线、$符号;
  • 不能:变量名字不能用数字作为开头
// 变量不能使用数字开头
var 15a = 10;

// 会在控制台中报错:Uncaught SyntaxError: Unexpected 
// Uncaught - 未捕获的
// SyntaxError - 语法错误

// Unexpected - 意料之外的
// number - 数字
// 翻译过来就是: 这行有一个语法错误,你的数字不符合语法要求
  • 变量名字不能使用JavaScript语法中的关键字和保留字
  • 关键字:在JavaScript语法中,具有特殊意义的单词,比如我们学习过的用于声明变量的var;后面要学习的if else for wihle case break....
// 变量名字不能使用关键字
var var = 20;
// 会在控制台中报错: Uncaught SyntaxError: Unexpected token var
// token - 标记,记号,在编程中我们翻译成 '标识符'
// 意思是这行有一个语法错误,出现了一个意料之外的标识符 var
  • 保留字:JavaScript是不断发展的,以前的功能用了以前的关键字,将来要加入新的功能的时候,可能要用到新的关键字,所有JavaScript在一开始的时候就保留了部分单词,以便将来把保留的单词作为关键字

  • 变量名字是区分大小写的;

// 变量名字是区分大小写的
var a = 10;
console.log(a);// 正常输出

console.log(A);// 在控制台中报错:Uncaught ReferenceError: A is not defined
// ReferenceError - 引用错误
// not defined - 未定义
// 意思是 A 这个变量我们没有定义就使用了,可见a和A是不一样的,不是同一个变量
  • 如何定义呢?
    • 设置和你公司业务有关系的变量,取英文的翻译
    • 使用驼峰(第一个单词的第一个字母小写,第二个单词的首字母大写);getData
    • 个人习惯:get_data
// 驼峰 getData
var userName = '张三';
var password = '123456';

// 个人习惯 get_data

# 字符串转义符

	类似HTML里面的特殊字符,字符串中也有特殊字符,我们称之为转义符。

	转义符都是 \ 开头的,常用的转义符及其说明如下:
转义符 解释说明
\n 换行符,n 是 newline 的意思
\ \ 斜杠 \
' ' 单引号
" ”双引号
\t tab 缩进
\b 空格 ,b 是 blank 的意思
  • 特殊的字符:"" '' \

# 数据类型

  • 是指我们存储在内存中的数据的类型
  • 我们通常分为两大类 基本数据类型复杂数据类型

# 基本数据类型

//八进制 八进1  0开头
        // var h = 011;
        // console.log(h);
        // 十六进制 由0-9,a-f组成  0x开头
        // var f = 0x10;
  1. 数值类型(number)
    • 一切数字都是数值类型(包括二进制,十进制,十六进制等)
    • NaN(not a number),一个非数字
  2. 字符串类型(string)
    • 被引号包裹的所有内容(可以是单引号也可以是双引号)
  3. 布尔类型(boolean)
    • 只有两个(true 或者 false)
  4. null类型(null)
    • 只有一个,就是 null,表示空的意思
  5. undefined类型(undefined)
    • 只有一个,就是 undefined,表示没有值的意思

# 数据类型转换

  • 数据类型之间的转换,比如数字转成字符串,字符串转成布尔,布尔转成数字等

其他数据类型转成数值

  1. Number(变量)

    • 可以把一个变量强制转换成数值类型
    • 可以转换小数,会保留小数
    • 可以转换布尔值
    • 遇到不可转换的都会返回 NaN
  2. parseInt(变量)

    • 从第一位开始检查,是数字就转换,直到一个不是数字的内容
    • 开头就不是数字,那么直接返回 NaN
    • 不认识小数点,只能保留整数
  3. parseFloat(变量)

  • 从第一位开始检查,是数字就转换,直到一个不是数字的内容

  • 开头就不是数字,那么直接返回 NaN

  • 认识一次小数点

  1. 除了加法以外的数学运算

    • 运算符两边都是可运算数字才行
    • 如果运算符任何一遍不是一个可运算数字,那么就会返回 NaN
    • 加法不可以用

# 转换为数字类型

# number方法
 var age = prompt('请输入您的年龄');
        console.log(typeof age);
        console.log(age + 10);
        // 其他类型转数值类型 Number()
        var a = '15.32';
        // 非数字字符串转成数字类型是NaN not number NaN 是数字类型
        var b = '89.9孙悟空';
        // 字符串的空  false true 转数字类型是0
        var x = '';
        var c = true;
        var d = false;
        var e;
        var f=null;
        var h=Number(b);
        console.log(h,typeof h);
# 取整parseInt
// parseInt()取整 数字开头的非纯数字字符串也可以取整
        // ''字符串的空 true false null 转数字类型是NaN
        var h = parseInt(b);
        console.log(h, typeof h);
# 取小数parseFloat
 // parseFloat()取整 数字开头的非纯数字字符串也可以取小数
        // ''字符串的空 true false null 转数字类型是NaN
        var h = parseFloat(b);
        console.log(h, typeof h);
# 隐式数据类型转换
// 隐式数据转化 - * /   如果用+号会直接用数字加字符串   特殊的true false等除外
        var a = 10;
        var b = '20';
        var c = true;
        console.log(a + b);
        console.log(a - b);
        console.log(a * b);

# 其他类型转换字符串类型

var a = '15';
        var b = '89.25';
        var c = true;
        var d = false;
        var e = null;
        var h = undefined;
        String()
        var x = String(h);
        console.log(x, typeof x);
        变量.toString() 这种方法不能转undefinednull
        var x = h.toString();
        console.log(x, typeof x);
        +号拼接  加号两边只要有一个字符串 加号就是拼接符
        h = '' + h;
        console.log(h, typeof h);

# 其他类型转换为布尔类型

// 其他类型转布尔类型
        // false ,'' , undefined , null NaN 0转换之后是false  其他转换都是true
        var f = false;
        var h = '';
        var i = undefined;
        var j = null;
        var k = NaN;
        var z = 0;
        var y = Boolean(z);
        console.log(y, typeof y);

# 操作符

数据运算:数据参加比较、运算 字符串+:与字符串临近的类型,转为字符串;里面存在一个隐式转化;看不到的转化;隐式转化:在字符串+情况下,数字隐转为字符串;

  • 情况:
    • 字符串 + ;
    • +字符串;
// 字符串 +
// 从左到右执行,数字相加,字符串拼接
var res3 = 10+10+"abc"+"def";
console.log(res3);  //输出 20abcdef
 // 算术运算符+ - * / %
        // + 只要两边有一个字符类型  +就是拼接符 2边都是数字类型  就是加运算
        // - * / 会有隐式类型转换
        // %取余(模)

# 字符串 其他

  • 字符串遇见 * / - %;
  • 隐式转化:字符串会隐式转化转为Number,再次参加运算;
var res3 = '456' - 123; 
console.log(res3); // 输出 数字 333

// 'abc' 隐式转化为NaN,所有输出NaN;
var res4 = 'abc' - 123;
console.log(res4); // 输出NaN
  • 其实字符串遇见 * / % 一样的结果;
    • 最终都是参与了隐式转化(只是我们看不见这个转化过程,但是实质还是这些数据被Number();

# 自增自减


        // ++i i++ 只操作一个 数据的叫一元运算符  2+3操作2个数据就叫二院操作符
        // 自增++i i++不参与运算的情况下 是一样的  都是自身加1
        var i = 10;
        // 自增参与运算  ++i前置自增  先自身加1 再参与运算
        var a = ++i;
        // i++后置自增  先参与运算 再自身加1
        // 注意后置自增 到了运算符另一边 已经自身加1
        var a = i++;

# 数学运算符

  1. +

    • 只有符号两边都是数字的时候才会进行加法运算
    • 只要符号任意一边是字符串类型,就会进行字符串拼接
  2. -

  • 会执行减法运算

  • 会自动把两边都转换成数字进行运算

  1. *

    • 会执行乘法运算
    • 会自动把两边都转换成数字进行运算
  2. /

    • 会执行除法运算
    • 会自动把两边都转换成数字进行运算
  3. %

    • 会执行取余运算
    • 会自动把两边都转换成数字进行运算

# 赋值运算符

  1. =

    • 就是把 = 右边的赋值给等号左边的变量名
    • var num = 100
    • 就是把 100 赋值给 num 变量
    • 那么 num 变量的值就是 100
  2. +=

    var a = 10;
    a += 10;
    console.log(a); //=> 20
    
    • a += 10 等价于 a = a + 10
  3. -=

    var a = 10;
    a -= 10;
    console.log(a); //=> 0
    
    • a -= 10 等价于 a = a - 10
  4. *=

    var a = 10;
    a *= 10;
    console.log(a); //=> 100
    
    • a *= 10 等价于 a = a * 10
  5. /+

    var a = 10;
    a /= 10;
    console.log(a); //=> 1
    
    • a /= 10 等价于 a = a / 10
  6. %=

    var a = 10;
    a %= 10;
    console.log(a); //=> 0
    
    • a %= 10 等价于 a = a % 10

# 比较运算符

  1. ==
    • 比较符号两边的值是否相等,不管数据类型
    • 1 == '1'
    • 两个的值是一样的,所以得到 true
  2. ===
    • 比较符号两边的值和数据类型是否都相等
    • 1 === '1'
    • 两个值虽然一样,但是因为数据类型不一样,所以得到 false
  3. !=
    • 比较符号两边的值是否不等
    • 1 != '1'
    • 因为两边的值是相等的,所以比较他们不等的时候得到 false
  4. !==
    • 比较符号两边的数据类型和值是否不等
    • 1 !== '1'
    • 因为两边的数据类型确实不一样,所以得到 true
  5. >=
    • 比较左边的值是否 大于或等于 右边的值
    • 1 >= 1 true
    • 1 >= 0 true
    • 1 >= 2 false
  6. <=
    • 比较左边的值是否 小于或等于 右边的值
    • 1 <= 2 true
    • 1 <= 1 true
    • 1 <= 0 false
  7. >
    • 比较左边的值是否 大于 右边的值
    • 1 > 0 true
    • 1 > 1 false
    • 1 > 2 false
  8. <
    • 比较左边的值是否 小于 右边的值
    • 1 < 2 true
    • 1 < 1 false
    • 1 < 0 false
        // >< >= <= ==(等于) === != !==  比较运算符返回的结果都是true或者false
        var a = 5;
        var b = '5';
        var c = '7';
        var d = 5;
 // == 等于 对数据类型没有要求  只要是值相等  就返回true 值不相同  返回false
        var res5 = b == c;
// != 不等于  只比较值是否不等  不等返回true 不管数据类型 只要值相等就返回false
        var res6 = a != b;
 // === 全等严格的判断  必须数据类型和值完全相等,返回true  否则就返回false
        var res5 = a === b;
 // !== 全不等  值和数据类型有一个不相等 返回true 数据类型和值完全相等返回false 
        var res7 = a !== b;

// 不同类型:特别的null 、undefined
// undefined和null与其他Number类型在进行相等判断时不进行类型转换。
console.log(null==0)         //false
console.log(0 == undefined); //false

// ECMAScript认为undefined是从null派生出来的,所以把它们定义为相等的;
console.log(null==undefined)  // true


// 输出 false ,比较两个数据的值是否不相等, 此时两个数据的 值 都 4 ,相等,结果是 false
console.log('4'!= 4); 

// 输出 true ,比较两个数据的类型和值是否不相等,此时两个数据的类型不相等,结果是 true
console.log('4'!== 4); 

# 逻辑运算符

  1. &&
    • 进行 且 的运算
    • 符号左边必须为 true 并且右边也是 true,才会返回 true
    • 只要有一边不是 true,那么就会返回 false
    • true && true true
    • true && false false
    • false && true false
    • false && false false
  2. ||
    • 进行 或 的运算
    • 符号的左边为 true 或者右边为 true,都会返回 true
    • 只有两边都是 false 的时候才会返回 false
    • true || true true
    • true || false true
    • false || true true
    • false || false false
  3. !
    • 进行 取反 运算
    • 本身是 true 的,会变成 false
    • 本身是 false 的,会变成 true
    • !true false
    • !false true
 // 逻辑运算符正常情况下返回true或者false
        // 逻辑与&& 两边都是true  返回true 只要有一边是false 返回false 见假为假
        var res = true && true;
        var res = false && false;
        // 逻辑或||两边只要有一个true 返回 true 两边都是false 返回false 见真即真
        var res = true || true;
        var res = 3 < 2 || 5 < 3;
        // 逻辑!取反
        var res = !true;
        var res = !false;

# 自增自减运算符(一元运算符)

  1. ++

    • 进行自增运算

    • 分成两种,前置++后置++

    • 前置++,会先把值自动 +1,在返回

      var a = 10;
      console.log(++a);
      // 会返回 11,并且把 a 的值变成 11
      
    • 后置++,会先把值返回,在自动+1

      var a = 10;
      console.log(a++);
      // 会返回 10,然后把 a 的值变成 11
      
  2. --

    • 进行自减运算
    • 分成两种,前置--后置--
    • ++ 运算符道理一样

# 优先级

  • 大致优先级:

    • 括号先算
    • 其次算算术:++a优先;
    • 再次算比较 > ==
    • 然后算逻辑 && ||
    • 最后算赋值 =
  • 观察代码

var a = 200 === (10 + 10) * 10 > 1;

// 先算括号
200===20*10>1

// 在算计算
200===200>1

// 算右侧;
200===true;

// false
console.log(a); 
  • 具体计算优先级
1. 第一优先级: [] . ()
2. 第二优先级: ++ -- !
3. 第三优先级: *  /  %
4. 第四优先级: +  -
5. 第五优先级: >   >=   <   <=
6. 第六优先级: ==   !=    ===    !==  
7. 第七优先级: &&
8. 第八优先级: || 
9. 第九优先级: = += -= *= /= %=  

程序:来源生活,高于生活;

# 分支结构判断

# if

// if单分支
        // if (条件表达式) {
        //     // 当条件表达式为true的时候 执行该处代码
        // }
        // 需求  判断一个男孩,如果年龄大于等于18 弹出提示框就可以进网吧了
        // if(条件表达式){
        //     如果条件表达式为true, 执行该处代码
        // }else{
        //     如果条件为false 执行该处代码
        // }
        var boy = prompt('请输入您的年龄');
        boy = Number(boy);
        if (boy > 18) {
            alert('请进吧')
        } else {
            alert('小屁孩,回家洗洗睡吧')
        }
  // 请用户输入一个数字,判断是不是偶数
        var num = Number(prompt('请输入一个数字'));
        if (num % 2 == 0) {
            console.log('这是一个偶数');
        } else {
            console.log('这是一个奇数');
        }
 if(条件表达式1){
                如果条件表达式1的结果为ture 执行该处代码
            }else if(条件表达式2){
                如果条件表达式2的结果为ture 执行该处代码
            }else if(条件表达式n){
                如果条件表达式n的结果为ture 执行该处代码
            }else{
                如果上面的条件表达式都为false 执行该处代码
            }
// 输入学生成绩 90-100A 80-90B 70-80C 60-70D <60E
        var num = Number(prompt('输入您的成绩'));
        if (90 < num && num <= 100) {
            console.log('A');
        } else if (80 < num && num <= 90) {
            console.log('B');
        } else if (70 < num && num <= 80) {
            console.log('C');
        } else if (60 < num && num <= 70) {
            console.log('D');
        } else {
            console.log('E');
        }
//第二种方法
   var num = Number(prompt('输入您的成绩'));
        if (num >= 90) {
            alert('A')
        } else if (num >= 80) {
            alert('B')
        } else if (num >= 70) {
            alert('C')
        } else if (num >= 60) {
            alert('D')
        } else {
            alert('E')
        }
//第三种
var a = Number(prompt('输入成绩'));
        var b = parseInt(Number(a / 10));
        switch (b) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                alert('e')
                break;
            case 6:
                alert('d')
                break;
            case 7:
                alert('c')
                break;
            case 8:
                alert('b')
                break;
            case 9:
                alert('a')
                break;
            case 10:
                alert('恭喜满分')
                break;
            default:
                alert('输入错误')

        }

# switch

 switch (变量) {
            case1:
                当变量和case后边的值1全等 === 数据类型和值完全相等
                执行该代码
                break的作用是阻断代码向下执行
                break;
            case2:
                当变量和case后边的值2全等 === 数据类型和值完全相等
                执行该代码
                break的作用是阻断代码向下执行
                break;
                case 值n:
                当变量和case后边的值n全等 === 数据类型和值完全相等
                执行该代码
                break的作用是阻断代码向下执行
                break;
                default:
                    当变量和case后边的值都不相等 执行该处代码
                    break;

        }
        var week = Number(prompt('亲 请输入周几  我会告诉你菜谱'));
        switch (week) {
            case 1:
                alert('红烧肉')
                break;
            case 2:
                alert('宫保鸡丁')
                break;
            case 3:
                alert('糖醋鲤鱼')
                break;
            case 4:
                alert('烧烤')
                break;
            case 5:
                alert('火锅')
                break;
            case 6:
                alert('满汉全席')
                break;
            case 7:
                alert('宫廷盛宴')
                break;
            // default:
            //     alert('宫廷盛宴')

        }

# 三元表达式

  • 表达式:有值会返回;

  • 语法:if else 的简写;有返回值;

    // 表达式1 ? 表达式2 : 表达式3;
    
    // 首先 要知道 表达式 会返回结果;
    // 过程:先执行表达式1,判断其结果是true还是false,
    // 如果是true,则执行表达式2,然后将 表达式2的执行结果 作为整个三元表达式的结果进行返回,
    // 如果是false,则执行表达式3,并将 表达式3的结果 作为整个三元表达式的结果
    
    //例如: 求二个数字中谁更大
    var a = 10; var b = 20;
    var max = a > b ? a : b;
    console.log(max);
    
       // 三元表达式
            // 表达式1? 表达式2: 表达式3
            // 如果表达式1位true 执行表达式2 如果为false执行表达式3
            var a = 10;
            var b = 50;
            // a和b的最大值
            a > b ? alert(a + '大') : alert(b + '大');
    
     var i = 0;
            // 三元表达式? 前边的表达式也会隐式类型转换为布尔值
            var num = i++ ? i++ : ++i;
            console.log(num);
    
    

# 循环结构

# for循环

  • 执行过程:
  1. 执行初始化表达式(只执行一次)
  2. 执行条件表达式
  3. 如果条件表达式的结果为false, 结束循环;
  4. 如果条件表达式的结果为true,执行循环体
  5. 执行自增表达式
  6. 重复2~5的步骤,直到条件表达式的结果为false,结束循环
for(初始化表达式; 条件表达式; 自增表达式){
  // 循环体
}
// 在页面上打印1-100
        for (var i = 1; i <= 100; i++) {
            console.log(i);
        }
 // 求1 - 10的和 1 + 2 + 3...
        var sum = 0;
        for (i = 1; i <= 10; i++) {
            sum += i;
        }
        console.log(sum);
 // 求1-100之间所有的偶数的和
        var sum = 0;
        for (i = 1; i <= 100; i++) {
            if (i % 2 == 0) {
                sum += i;
            }
        }
        console.log(sum);
 // 求1-4的乘积
        var sum = 1;
        for (i = 1; i <= 4; i++) {
            sum *= i;
        }
        console.log(sum);

# 双层for循环

  // 打印10行 每一行都是5课星
        // 循环是重复做一件事 条件不满足的时候循环结束
        // 外层for循环控制的是行数
        for (var j = 1; j <= 10; j++) {
            for (var i = 1; i <= 5; i++) {
                document.write("★");
            }
            document.write("<br>")
        }
   // 直角三角形
        for (var j = 1; j <= 9; j++) {
            for (var i = 1; i <= j; i++) {
                document.write("★");
            }
            document.write("<br>")
        }
  // 倒三角
        for (var j = 1; j <= 9; j++) {
            for (var i = 1; i <= 10 - j; i++) {
                document.write("★");
            }
            document.write("<br>")
        }
 <!-- 等腰三角形 -->
    <style>
        body {
            text-align: center;
        }
    </style>
    <script>
        for (var j = 1; j <= 9; j++) {
            for (var i = 1; i <= j; i++) {
                document.write("<span>★</span>");
            }
            document.write("<br>")
        }
    </script>
    <!-- 九九乘法表 -->
    <style>
        span {
            display: inline-block;
            width: 100px;
            height: 30px;
            line-height: 30px;
            text-align: center;
            border: 1px solid #000000;
            margin-left: -1px;
            margin-bottom: -1px;
        }
    </style>
    <script>
        for (var j = 1; j <= 9; j++) {
            for (var i = 1; i <= j; i++) {
                document.write("<span>" + i + 'x' + j + '=' + i * j + "</span>");
            }
            document.write('<br>')
        }
    </script>

# while循环

当循环次数已知的时候用for循环 当循环次数未知的时候用while和do while

    
        while (条件表达式) {
            // 当条件表达是为true的时候  执行循环体的代码  条件表达式为false的时候  循环体代码不执行
        }
        // 求1-100的和
        var i = 1, sum = 0;
        while (i <= 100) {
            sum += i;
            i++;
        }
        console.log(sum);


 // 用户名和密码只要有一个输入错误 用户就需要一直输入
        var userName = prompt('用户名')
        var passWord = prompt('密码')
        while (userName != 'admin' || passWord != '123456') {
            userName = prompt('用户名')
            passWord = prompt('密码')
        }
        alert('登录成功')

# do while

  // do{
        //     循环体
        //     循环体首先执行一次 再去看条件表达式 如果条件表达式为true 循环体继续循环 如果为false 循环结束
        // }while(条件表达式)
        do {
            var userName = prompt('用户名')
            var passWord = prompt('密码')
        } while (userName != 'admin' || passWord != '123456') {
            alert('登录成功');
        }

# break和continue

  • 循环退出:
    • 满足条件退出
    • 关键字退出:某些情况下,我们不一定要循环从头到尾执行,这个时候就要使用break和continue控制循环的次数;
// break 结束的是当前循环
/* 例子:电梯一共有6层,现在我们要上电梯,我们的教室在3楼,电梯只要到3楼就可以了。*/
for(var i = 1; i <= 6 ; i++ ){
    console.log('现在是'+i+'楼');
    if(i == 3){
        console.log('3楼到了,电梯停了,请下电梯。');
        // 程序 执行到 3,执行了四次就结束了;
        break;
    }
}
// 这里案例用的是for循环演示,while 和do-while一样;
// continue
// 电梯一共有6层,除了3楼没人下去,其他楼层都有人下去(3楼不停,其他楼层都要停)
for(var i = 1; i <= 6; i++){
    if(i == 3){
        // 执行到 3 时。当前次的程序后面的全部跳过;继续执行后面的次数;
        continiue;
    }
    console.log(i+'楼到了,电梯停了,请下电梯。');      
}

总结:这个地方只是用for做终止

  • break用于结束整个循环

  • continue用于结束整个循环中的一次,结束当前这次循环

  • break和continue后面的代码都不会执行,执行前面的代码;

# 逻辑中断 短路

// &&与操作(中断)短路 找假 如果找不到就返回最后一个的值
        // var res = null && 3 && true;
        // console.log(res);
        // || 或操作(中断)短路 找真 如果找不到到就返回最后一个的值
        var res = 0 || 3 || NaN;
        console.log(res);

# 调试

  • 对于初学者来说,感受代码的执行过程是非常重要的,浏览器中提供了一个可以观察代码执行过程的工具
  • 第一步:F12打开开发者工具,点击Sources选项
  • 第二步:在左边找到代码所在文件,双击打开
  • 第三步:在中间部分找到自己写的代码,在想要暂停的数字地方打上断点
  • 第四步:触发代码的执行,现在我们的代码是在浏览器打开的时候执行,所以我们只要刷新页面即可。当代码执行到断点所在行,会暂停
  • 第五步:通过点击右边的控制执行按钮,可以让代码按照你的意愿

1554445172614

# 习题练习

# 1- 判断时间阶段。

  • 题目描述:

    用户输入几点弹出问候信息;

      如用户输入12点中午好;
      
      用户输入18点 弹出傍晚好;
    
      用户输入23点弹出深夜好;
    
  • 题目提示:

    通过比较运算符判定输入的时间的范围,弹出相应的问候信息

       var i;
            var j = Number(prompt(i));
            if (j == 12) {
                alert('中午好');
            } else if (j == 18) {
                alert('傍晚好');
    
            } else if (j == 23) {
                alert('深夜好');
            } else {
                alert('输入错误');
            }
    

# 2 - 比较两个数的最大值

  • 题目描述:

    用户依次输入2个值,最后弹出最大的那个值

  • 题目提示:

    通过比较运算符弹出最大值

         var i = Number(prompt('请输入i的值'));
            var j = Number(prompt('请输入j的值'));
            if (i > j) {
                alert('i' + '大')
            } else {
                alert('j' + '大')
    
            }
    

# 3 - 判断奇偶性

  • 题目描述:

    用户输入一个数,判断是奇数还是偶数

  • 题目提示:

    通过%运算符可以得出数字的奇偶性

       var i = Number(prompt('请输入数字判断奇数还是偶数'))
            if (i % 2 == 0) {
                alert('偶数')
            } else {
                alert('奇数')
            }
    
    

# 4 - 判断星期

  • 题目描述:

  • 周三 周四 周五 周六 周日 周一 周二 周三 周四 周五 周六 周日 周一

  • 1 2 3 4 5 6 7 8 9 10 11 12 13

    	假设这个月1号是星期三,提示用户输入本月的日期(即1日-31日),返回用户输入的那一天是星期几
  • 题目提示:

    利用%和7取余,再判定是星期几

     var i = Number(prompt('请输入日期'));
            if (i % 7 == 0) {
                alert('今天是周二')
            } else if (i % 7 == 1) {
                alert('今天是周三')
            } else if (i % 7 == 2) {
                alert('今天是周四')
            } else if (i % 7 == 3) {
                alert('今天是周五')
            } else if (i % 7 == 4) {
                alert('今天是周六')
            } else if (i % 7 == 5) {
                alert('今天是周日')
            } else if (i % 7 == 6) {
                alert('今天是周一')
            }
    
    //第二种解法 
    var day = Number(prompt('请输入几号'));
            day = (day + 2) % 7;
            if (day == 0) {
                alert('这一天是周日')
            } else {
                alert('这一天是周' + day);
            }
    

# 5 - 请客吃饭

  • 题目描述:

    接收班长口袋里的钱数?

      若大于等于2000,请大家吃西餐。						2000<=j
    
      若小于2000,大于等于1500,请大家吃快餐。1500<=j<2000
    
      若小于1500,大于等于1000,请大家喝饮料。 1000<=j<1500
    
      若小于1000,大于等于500,请大家吃棒棒糖。 500<=j<1000
    
      否则提醒班长下次把钱带够
    
  • 题目提示:

    使用switch或者if else if 来进行逻辑书写

       var i = Number(prompt('班长口袋里面的钱数'));
            if (i >= 2000) {
                alert('请大家吃西餐')
            } else if (i < 2000 && i >= 1500) {
                alert('请大家吃快餐')
            } else if (i < 1500 && i >= 1000) {
                alert('请大家喝饮料')
            } else if (i < 1000 && i >= 500) {
                alert('请大家吃棒棒糖')
            } else {
                alert('班长下次把钱带够')
            }
    
    
            var i = Number(prompt('班长口袋里面的钱数'));
            var j = parseInt(i / 500);
            switch (j) {
                case 0:
                    alert('班长下次把钱带够')
                    break;
                case 1:
                    alert('请大家吃棒棒糖');
                    break;
                case 2:
                    alert('请大家喝饮料');
                    break;
                case 3:
                    alert('请大家吃快餐');
                    break;
                case 4:
                    alert('请大家吃西餐');
                    break;
            }
    

# 6 - 成绩表

  • 题目描述:

    分数转换,给一个分数,判定等级。大于等于90 A,大于等于80小于90 B,大于等于70小于80 C ,大于等于60小于70 D,小于60 E

  • 题目提示:

    使用if else if 来进行逻辑书写,当使用if else if 时注意判定大小顺序

      思考:是否可以使用switch完成本题目
    
var i = Number(prompt('请输入你的成绩'));
        var j = parseInt(i / 10);
        switch (j) {
            case 0:
            case 1:
            case 2:
            case 3:
            case 4:
            case 5:
                alert('E')
                break;
            case 6:
                alert('D')
                break;
            case 7:
                alert('C')
                break;
            case 8:
                alert('B')
                break;
            default:
                alert('A')
        }
    var i = Number(prompt('请输入你的成绩'));
        if (i >= 90) {
            alert('A');
        } else if (i >= 80) {
            alert('B');
        } else if (i >= 80) {
            alert('C');
        } else if (i >= 70) {
            alert('D');
        } else {
            alert('E');
        }
 var score = Number(prompt('请输入成绩'));
        switch (true) {
            case score >= 90:
                alert('A')
                break;
            case score >= 80:
                alert('B')
                break;
            case score >= 70:
                alert('C')
                break;
            case score >= 60:
                alert('D')
                break;
            case score < 60:
                alert('E')
                break;
            default:
                alert('输入错误');
                break;

        }

# 1.1 求100以内所有能被3和7整除的数的和

  • 题目描述:

    • 把1-100之间所有能够被3和7同时整除的数找出来,计算累加和
  • 题目提示:

    • 在算入累加和之前,使用%判定遍历到的数字是不是可以被3和7整除
    • ``
    var sum = 0;
            for (i = 1; i <= 100; i++) {
                if (i % 3 == 0 && i % 7 == 0) {
                    sum += i;
                }
            }
            console.log(sum);
    

# 1.2 使用for循环打印三角形

  • 题目描述:

    • 在控制台一次性打印形状如下:

      ☆ ☆☆ ☆☆☆ ☆☆☆☆ ☆☆☆☆☆

          var x = '';
              for (i = 1; i <= 5; i++) {
                  for (j = 1; j <= i; j++) {
                      // console.log('★');
                      x = x + '★';
                      // document.write('★')
                  }
                  // document.write('<br>')
                  console.log(x)
                  x = '';
              }
      
              for (i = 1; i <= 5; i++) {
                  for (j = 1; j <= i; j++) {
                      // console.log('★');
                      // x = x + '★';
                      document.write('★')
                  }
                  document.write('<br>')
                  // console.log(x)
                  // x = '';
              }
      
  • 题目提示:

    • 利用双重for循环

# 1.3 使用for循环打印99乘法表

  • 题目描述:

    • 使用for循环,打印99乘法表

    • 在控制台打印具体效果如下:

      1×1=1 1×2=2 2×2=4 1×3=3 2×3=6 3×3=9 1×4=4 2×4=8 3×4=12 4×4=16 1×5=5 2×5=10 3×5=15 4×5=20 5×5=25 1×6=6 2×6=12 3×6=18 4×6=24 5×6=30 6×6=36 1×7=7 2×7=14 3×7=21 4×7=28 5×7=35 6×7=42 7×7=49 1×8=8 2×8=16 3×8=24 4×8=32 5×8=40 6×8=48 7×8=56 8×8=64 1×9=9 2×9=18 3×9=27 4×9=36 5×9=45 6×9=54 7×9=63 8×9=72 9×9=81

  • 题目提示:

    • 利用双重for循环
    <style>
        span {
            display: inline-block;
            width: 100px;
            height: 50px;
            line-height: 50px;
            text-align: center;
            border: 1px solid #000000;
            margin-bottom: -1px;
            margin-left: -1px;
        }
    </style>
    <script>

        for (i = 1; i <= 9; i++) {
            for (j = 1; j <= i; j++) {
                document.write("<span>" + i + 'x' + j + '=' + i * j + "</span>");
            }
            document.write('<br>');

        }
    </script>

# 1.4 用户登录验证

  • 题目描述:
    • 接收用户输入的用户名和密码,若用户名为 “admin” ,且密码为 “123456” ,则提示用户登录成功! 否则,让用户一直输入。
  • 题目提示:
    • 利用while循环或者do while 循环
var userName = prompt('请输入用户名');
        var passWord = prompt('请输入密码');
        while (userName != 'admin' && passWord != '123456') {
            var userName = prompt('请输入用户名');
            var passWord = prompt('请输入密码');

        }
        alert('密码输入正确');
   do {
            var userName = prompt('请输入用户名');
            var passWord = prompt('请输入密码');
        } while (userName != 'admin' && passWord != '123456') {
            alert('密码输入正确');
        }

# 1.5 求1-100之间个位数不为3的数的累加和。

  • 题目描述:

    • 求整数1~100的累加值,但要求跳过所有个位为3的数。
  • 题目提示:

    • 使用%判个位数是否为3
    • 用continue实现
        var sum = 0;
            for (var i = 1; i <= 100; i++) {
                //如果能被3整除,跳过continue
                if (i % 3 == 0) {
                    continue;
                }
                sum += i;
            }
            console.log(sum);
    
    
    var a = 0, sum = 0;
            for ( var i = 1; i <= 100; i++) {
                a += i;
                if (i % 10 == 3) {
                    sum += i;
                }
            }
            console.log(a - sum);
    
    var sum = 0;
            for (i = 1; i <= 100; i++) {
                if (i % 10 != 3) {
                    sum += i;
                }
    
            }
            console.log(sum);
    

# 2.1 简易ATM

  • 题目描述:

    • 里面现存有 100 块钱。

    • 如果存钱,就用输入钱数加上先存的钱数, 之后弹出显示余额提示框

    • 如果取钱,就减去取的钱数,之后弹出显示余额提示框

    • 如果显示余额,就输出余额

    • 如果退出,弹出退出信息提示框

      操作界面如下

  • 题目提示:

    • 通过输入的数值判断用户操作
    • 定义一个变量,保存钱数
    • 先接收一下用户输入的数字 存到变量里边
    • 用while循环
    • whilie循环里边,switch case 比较简单
 var money = 100
        for (let i = 0; i < 5; i++) {
            var work = parseFloat(prompt("请输入你要进行的操作" + "\n" + "1.存钱" + "\n" + "2.取钱" + "\n" + "3.显示金额" + "\n" + "4.退出"))
            switch (work) {
                case 1:
                    var cun = parseFloat(prompt('请输入你要存的金额'));
                    money += cun;
                    alert("你的剩余金额是" + money);
                    break;
                case 2:
                    var qu = parseFloat(prompt('请输入你要取出的金额'));
                    money = money - qu;
                    alert("你的剩余金额是" + money);
                    break;
                case 3:
                    alert("你的剩余金额是" + money);
                default:
                    break;
            }
        }
//开关阀atm
 var flag = true;
        var money = 100;
        while (flag) {
            var mes = Number(prompt('请输入你的操作:\n1.存钱\n2.取钱\n3.显示余额\n4.退出'));
            switch (mes) {
                case 1:
                    var pay = Number(prompt('请输入您的存款金额'));
                    money += pay;
                    alert('您的余额是' + money);
                    break;
                case 2:
                    var get = Number(prompt('请输入您的取款金额'));
                    money -= get;
                    alert('您的余额是' + money);
                    break;
                case 3:
                    alert('您的余额是' + money);
                    break;
                case 4:
                    flag = false;
            }
        }

# 2.2 求从1 开始第35个能被7和3整除的整数

  • 题目描述:

    • 求从1开始第35个能被7和3整除的整数
  • 题目提示:

    • 通过变量记录是第几个可以被3和7整除的数
 var num = 1, count = 0, result = 0;
        for (var i = 1; i <= num; i++) {
            num++;
            if (i % 3 == 0 && i % 7 == 0) {
                // 使用result把i的值取出来
                result = i;
                // 取出一个i count自增一次
                count++;
                // 到第35个i的时候循环终止
            } else if (count == 35) {
                break;
            }
        }
        console.log(result);
 var i = 1, count = 0, result = 0;
        while (count < 35) { //当count等于35的时候就会停止执行
            i++; //i的自增bai
            if (i % 3 == 0 && i % 7 == 0) {
                result = i; //把能整除3和7的数字保存下来
                count++; //一旦发现一次能整除3和7的数字,就加1
            }
        }
        console.log(result);
     var a = 1; b = 0; //b 是计数器
        // b不等于35循环一直进行下去 等于35的条件表达式为false 循环结束
        while (b != 35) {
            if (a % 7 == 0 && a % 3 == 0) {
                b++;
                if (b == 35) {
                    alert(a)
                }
            }
            a++;
        }
//开关法
   var a = 1, b = 0, flag = true; //b 是计数器
        // flag为true的时候 循环一直执行  flag为false的时候 循环终止
        while (b != 35) {
            if (a % 7 == 0 && a % 3 == 0) {
                b++;
                if (b == 35) {
                    alert(a)
                    // 循环停止
                    flag = false;

                }
            }
            a++;
        }

# 2.3 斐波那契数列

兔子数列 (opens new window)”,指的是这样一个数列:0、1、1、2、3、5、8、13、21、34 ,55, 89

特点是: 后一个月是前2个月的和

求第12个月的兔子数?

提示:

 var a = 0, b = 1;
        for (i = 3; i <= 12; i++) {
            var c = a + b;
            a = b;
            b = c;
        }
        alert(c);

# 2.4 质数

质数是只能被1和他自身整除的数

比如7 1 2 3 4 5 6 7 是质数 9不是质数 1 2 3 4 5 6 7 8 9 因为9能被3整除

n 2, 3, 4 ,5 ,6 ...n - 1 , n

提示:

  开关法
// 用户任意输入一个数 如果是质数弹框提示  如果不是质数 弹出提示不是质数
        var num = Number(prompt('请输入一个数 我会告诉你他是不是质数'));
        var flag = true;
        if (num == 2) {
            alert('质数');
        }
        for (var i = 2; i < num; i++) {
            if (num % i == 0) {
                flag = false;
                alert('不是质数');
                break;
            }
        }
        if (flag) {
            alert('质数');
        } 
   var num = Number(prompt('请输入一个数  我会告诉你他是不是质数'));
        //num%2.......num-1 !=0是质数 num%2......num-1==0 说明不是质数
        for (var i = 2; i < num; i++) {
            //比如num是6 这时候6%i==0 i是2 循环结束
            //比如num7 这时候7%(2.....6) !==0 然后循环结束  循环结束的时候 i应该是num 这个数是质数
            if (num % i == 0) {
                alert('不是质数');
                break;
            }
        }
        //  当num从2一直到num-1取余不等于0 这时候上边的循环结束 循环结束的时候i++最后变成了num
        if (num == i) {
            alert('质数');
        }
var num = Number(prompt('请输入数字 判断是否为质数'));
        var con = 0;
        for (i = 1; i <= num; i++) {
            if (num % i == 0) {
                con++;
            }
        }
        // 循环结束之后 con的次数确定了 再进行判断  如果 num%(1...num)2次等于0  是质数 否则不是质数
        if (con == 2) {
            alert('质数');
        } else {
            alert('不是质数');
        }
   var count = 0;
        var num = Number(prompt('请输入数字 判断是否为质数'));
        for (i = 2; i <= num; i++) {
            if (num % i == 0) {
                count++;
            }
        }
        if (count == 1) {
            alert('质数');
        } else {
            alert('不是质数')
        }

# 介绍

  • 数组是一个有顺序有长度的数据集合;
  • 数组:类型Object;
  • 特点:
    • 把数据放在一起;
    • 有先后位置上的顺序;
    • 有数据的长度;
// 数组一组有序的有长度的数据集合 数组里面可以存储任意的数据类型
        // 声明数组
        // 1字面量声明数组
        // 数组元素顺序是靠索引来控制的 索引(下标)从0开始
		//创建一个空数组
        var arr = [];
        arr[0] = 89;
        arr[1] = 'www';
        arr[2] = true;
        console.log(arr);
		//创建一个有内容的数组
        var arr1 = [12, 39, 'hahahha', 78];
        console.log(arr1);
		//拿到索引为0 顺序上第一个位置上的数据
		//把数组[索引]格式当成一个变量使用就行了
		console.log(arr1[0])

# 存值

  • 数组中的数据使用索引管理。
  • 索引 下标:位置:方便放入存值和寻找;
  • 索引 规则:用数字表示,从0开始
//把成绩存储到数组中
arr[0] = 91;
arr[1] = 88;
arr[2] = 72;
arr[3] = 45;
arr[4] = 63;
console.log(arr); // 输出 [91,88,72,45,63] 就是一个数据集合
  • 数组[索引]格式当成一个变量使用就行,
// 初始化赋值完成后,也可以再次改变值,把前面的值覆盖掉;
arr[0] = 100;
  • 如果一开始就知道数组了,可以直接使用一个简单的语法存储数据
var arr = [91,88,72,45,63];
console.log(arr); // 输出的结果是一样的
  • 上面每个位置上存的都是数字类型,可以为其他类型;

# 取值

  • 把数据取出来,得知道你要取哪个位置上的数据把。
  • 数据取值同样使用索引取。
// 拿到索引为0,顺序上第一个位置上的数据;
// 把 数组[索引] 格式当成一个变量使用就行;
console.log(arr[0]);

// 数组求和:班里的成绩总和
var sum = arr[0] + arr[1] + arr[2] + arr[3] + arr[4];
console.log(sum); // 输出370

# 遍历

  • 求成绩总和:一个一个地把数组里面的数组取出来了,从索引 0 到最后一个索引,
  • 索引从0开始到结束的过程,有重复的思想,需要用到循环;
// 最初的写法
var sum = arr[0] + arr[1] + arr[2] + arr[3] + arr[4];


// 循环 这个从0~最后一个索引,有重复的思想在里面,使用循环。
var sum = 0;
for(var i = 0; i <= 4; i++){
  sum += arr[i];
}
console.log(sum); // 输出 370,和我们一个一个相加是一样的
  • 使用循环来遍历数组,当数组中的数据比较多的时候,会比较方便。一般是使用for循环;

# 数组长度

# 语法

  • 存取数据:涉及到就是数组的顺序问题,通过索引去存取;

  • 数组长度:数组中一共存放了多少个数据;

console.log(arr.length); // 数组.length 就是数组的长度
  • 如果数组的长度是5,最后一个元素的索引就是4;
  • 我们发现最大索引总是比长度少 1 ,所以遍历还可以这么写

# 数组的索引

  • 索引,也叫做下标,是指一个数据在数组里面排在第几个的位置

  • 注意: 在所有的语言里面,索引都是从 0 开始的

  • 在 js 里面也一样,数组的索引从 0 开始

for(var i = 0; i <= arr.length - 1; i++){
  console.log(arr[i]);
}

// 简化一下 
for(var i = 0; i < arr.length; i++){
  console.log(arr[i]);
}
 // i是索引值 从0开始
        // 数组里边的最大索引值是数组名.length - 1
        var arr = [22, 5, 6, 7, 8, 98];
        for (i = 0; i < arr.length; i++) {
            console.log(arr[i]);
        }
  var arr = [22, 5, 6, 7, 8, 98];
        /*   数组长度小于数组的实际长度 后边的元素会删除掉
          arr.length=2;
          数组长度大于数组的实际长度 后边的元素会显示empty 就是undefined */
        arr.length = 9;
		//输出数组内的所有元素
		console.log(arr);
		//输出数组的长度
        console.log(arr.length);
		//输出索引值的第七位
        console.log(arr[7]);

# 数组后面追加元素

```js

// 数组后边追加新元素 数组名[数组名.length]=值 // 0 1 2 3 4 n // 数组长度1 2 3 4 5 n+1 var arr = [22, 5, 6, 98]; arr[arr.length]=32; arr[arr.length]=50; ```

# 习题练习

# 求数组中所有数字的和以及平均值

  • 分析:
    • 总和:循环遍历,加在一个变量上得到;
    • 均值:总和 / 个数;(arr.length)
 var sum = 0;
        var arr = [2, 3, 4, 5];
        for (i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        console.log(sum, sum / arr.length);

# 求数组中的最大值

  • 分析:生活中,一堆人最高的(人很多,多到你一下看不出来);
    • 最大值:最起码得两个数比较下,得到最大值;
    • 假设:其中随便一个是最大值MAX,每个元素和max比较,
      • 若有比MAX大的,那该元素代替MAX;
      • 若都没有MAX大,恭喜,你一开始就猜对了;
  var arr = [22, 5, 6, 98];
        var max = arr[0];
        for (var i = 1; i < arr.length; i++) {
            if (max < arr[i]) {
                max = arr[i];
            }
        }
        console.log(max);

# 把老数组里面大于10的选出来 追加到新的空数组里面

  // 把老数组里面大于10的选出来 追加到新的空数组里面
            // 结果newArr=[12, 5, 6, 23, 32, 48]
            // 把老数组里面大于等于10的选项挑出来
            // for 遍历 因为要老数组里面的每一项去和10比较
            // if(arr[i]>=10) 条件大于等于10
            // newArr[newArr.length]向新数组追加元素
        var arr1 = [12, 5, 6, 23, 32, 48];
        var newArr = [];
        for (i = 0; i < arr1.length; i++) {
            if (arr1[i] >= 10) {
                newArr[newArr.length] = arr1[i];
            }
        }
        console.log(newArr);

# 翻转数组

// 翻转数组
        var arr = ['张三', '李四', '王五', '赵六', '陆奇'];
        // 结果是arr 陆奇 赵六   王五     李四    张三
        // 交换位置 交换次数
        // 交换位置 arr[i]和arr[arr.length-1-i]  交换变量的值
        // 交换需要用到数组的每一项 遍历
        for (i = 0; i < (arr.length - 1) / 2; i++) {
            var temp = arr[i];
            arr[i] = arr[arr.length - 1 - i];
            arr[arr.length - 1 - i] = temp;
        }
        console.log(arr);

        翻转数组
               arr[i]  arr[i]             arr[arr.length-1-i]   arr[arr.length - 1 - i]
        var arr = ['张三', '李四', '王五',  '赵六', '鲁七', 6];
        // // 结果是 arr = ['鲁七', '赵六', '王五','李四', '张三' ];
        // // 交换次数  交换2次
        // // 交换位置  arr[i] 和 arr[arr.length-1-i]  交换变量的值
        // // 交换需要用到数组里边的每一项,遍历
        for (var i = 0; i < (arr.length- 1) / 2; i++) {
            var temp = arr[i];
            arr[i] = arr[arr.length - 1 - i];
            arr[arr.length - 1 - i] = temp;
        }
        console.log(arr);

# 冒泡排序

   // 冒泡排序数字数组从小到大(从大到小排列)
        var arr = [5, 3, 8, 7];
        // 比较  数组里面第一个元素 第一个元素比后边大的,交换位置
        // 外边的循环控制的是交换的次数
        for (var j = 0; j < arr.length - 1; j++) {
            // 里面的循环控制是每一轮交换
            for (var i = 0; i < arr.length - 1 - j; i++) {
                if (arr[i] < arr[i + 1]) {
                    var temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
        }
        console.log(arr);
  // if(5 > 3) {
        //     交换位置
        // }
        // 第1轮     比较了3次 j  0        arr.length - 1 - j
         // [3, 5, 8, 7]

        // if(5 > 8) {
        //     交换位置
        // }
        // // [3, 5, 8, 7]
        // if(5 > 7) {
        //     交换位置
        // }
        // // [3, 5, 8, 7]

    //   第2轮  比较了2次      j  1      arr.length - 1 - j 
        // if(3 > 8) {
        //     交换位置
        // }
        // [3, 5, 8, 7]

        // if(3 > 7) {
        //     交换位置
        // }
        // [3, 5, 8, 7]
        
       // 第3轮,比较了1次     j 2    arr.length - 1 -j
        // if(8> 7) {
        //     交换位置
        // }
        // [3, 5, 7, 8]
        //   结果 arr = [3, 5, 7, 8]
  var arr = [2, 3, 56, 21]
        for (i = 0; i < arr.length - 1; i++) {
            for (j = 0; j < arr.length - 1 - i; j++) {
                if (arr[j] < arr[j + 1]) {
                    temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                }
            }
        }
        console.log(arr);
        // 第一轮  i   0         arr.length-1       j   3  arr.length-1
       /* 第一次 2<3 交换位置                  
         第二次 2<56  交换位置
         第三次 2<21   交换位置   3 56 21  2
       第二轮  i   1                                    2     arr.length-1-1 
       第一次 3<56  交换位置
       第一次   3<21   交换位置    56 21  3 2

         第三轮 i   2                                    1       arr.length-1-1-1       arr.length-1-i
         第一次 56<21             56 21  3 2
        */

# js去重


        // 去重将数组里面重复的项去掉 只保留一个 写到新数组里面
        /* 思路  拿老数组里面的某一项和新数组中的每一项比较  只要有一个相等 不用追加 除非都不相等 把老数组中的这一项 追加到新数组里面去
        双层for循环 */
        // 遍历老数组
        var arr = [1, 2, 3, 3, 2, 7, 8]
        var newArr = [];
        for (var i = 0; i < arr.length; i++) {
            // 考虑开关的位置
            var flag = true;
            // 遍历新数组
            for (var j = 0; j < newArr.length; j++) {
                // 老数组里边的某一项和新数组中的任意一项比较相等 不用追加到新数组里面
                if (arr[i] == newArr[j]) {
                    flag = false;
                    break;
                }
            }
            if (flag) {
                newArr[newArr.length] = arr[i];
            }
        }
        console.log(newArr);
    var arr = [1, 2, 3, 3, 2, 7, 8]
        var newArr = [];
        for (var i = 0; i < arr.length; i++) {
            for (var j = 0; j < newArr.length; j++) {
                if (arr[i] == newArr[j]) {
                    break;
                }
            }
             // 如果老数组中的某一项和新数组里面全部元素比较完之后 都不相等 追加到新数组里面去
            // 老数组循环一遍 都不相等 老数组循环结束 最后一次i++变成了newArr.length
            if (j == newArr.length) {
                newArr[newArr.length] = arr[i];

            }
        }
        console.log(newArr);

# 数组的构造函数

  • 数组在JS中还可以使用另一种方式创建,这个方式我们称为 : 构造函数
  • 构造函数:能构造一个你需要的东西(对象);
// 使用 构造函数 创建数组
var arr = new Array();
// 存储数据
arr[0] = 10;
arr[1] = 20;
console.log(arr);

var arr = new Array(10,20);
console.log(arr);
  • 注意:一个数据,不要使用这个方式存储数据;它会认为你想要设置数组的长度,而不是要把数据存储在数组中。
var arr = new Array(10);
console.log(arr); // 输出 [empty × 10]
  • arr.length = 0;

# 字面量创建一个数组

  • 直接使用 [] 的方式创建一个数组

    // 创建一个空数组
    var arr1 = []
    
    // 创建一个有内容的数组
    var arr2 = [1, 2, 3]
    

# 函数声明调用

     // 函数的声明 
        // function 函数名(){
        //     函数体
        // }
        // 函数调用 函数自己不执行 只有被调用的时候才执行
        // 函数名();
       // function: 声明函数的关键字,表示接下来是一个函数了
 	//getSum: 函数的名字,我们自己定义的
	// (): 必须写,是用来放参数的位置
	// {}: 就是我们用来放一段代码的位置
        function getSum() {
            var sum = 0;
            for (i = 1; i <= 100; i++) {
                sum += i;

            }
            console.log(sum);
        }
        getSum();
        getSum();
        getSum();

# 赋值式

  • 其实就是和我们使用 var 关键字是一个道理了
  • 首先使用 var 定义一个变量,把一个函数当作值直接赋值给这个变量就可以了
  • 语法:
var fn = function () {
  // 一段代码
}
// 不需要在 function 后面书写函数的名字了,因为在前面已经有了

# 参数

# 配置参数

  • 参数:对于函数来说,函数内部的变量;
  • 作用:为什么?给别人讲故事,不同的情况套用不同的人名;把函数封装的代码,变活了;
  • 定义参数:位置,小括号上自定的参数;
  • 特点:只能在内部使用,和外部没有关系;
  • 使用:传入值,给了形参;
  • 语法:
// 在小括号内的变量,对于函数来说,就是参数;
// 参数就是函数 内部的变量;
function 函数名(参数){
  // 函数体
}
// 参数:对于函数,这些参数都是形式上的参数,它就是代替位置,相当于是变量在这占了个坑;至于这个参数真实背后代表什么值,我们现在还不知道;
function tellStroy(name){
  console.log("从前有座山,山里有座庙");
  console.log("庙里有个老和尚在给小和尚讲故事");
  console.log("讲的是什么呢?");
  console.log("老和尚对"+ name +"说:");
}
  • 既然是变量,可以被改变存储值;如何改变?调用时传递一个值;
// 调用函数的时候,传入参数;
tellStroy('清风');
tellStroy('明月');
  • 需求:如果我们想在调用函数的时候,把老和尚的名字也明确一下,就把老和尚的名字作为变量改变下;
// 声明函数,配置参数;
function tellStroy(name1,name2){
  console.log("从前有座山,山里有座庙");
  console.log("庙里有个老和尚在给小和尚讲故事");
  console.log("讲的是什么呢?");
  console.log(name1 "对"+ name2 +"说:");
}

// 调用函数
tellStroy('圆通','清风');

# 参数不赋值

  • 变量:函数内部的变量,没有赋值,默认为undefined;和我们的变量一模一样;
function tellStroy(name){
  console.log("从前有座山,山里有座庙");
  console.log("庙里有个老和尚在给小和尚讲故事");
  console.log("讲的是什么呢?");
  console.log("老和尚对"+ name +"说:");   // 老和尚对undefined说;
}
  • 解决:对参数进行判断,如果是undefined,给一个默认值;
function tellStroy(name){
    
  // if 条件语句
  if(name==undefined) {
      name = '小和尚'
  }
  else {
      name = name;
  }
  
  // 三元表达式;
  name = name?name:"小和尚";
  console.log("从前有座山,山里有座庙");
  console.log("庙里有个老和尚在给小和尚讲故事");
  console.log("讲的是什么呢?");
  console.log("老和尚对"+ name +"说:");
}

# 形参与实参

  • 形参:外面不能使用;和外面没有任何关系;只能函数内部使用;
  • 实参:调用函数时,真实参与运算的数据,外部调用函数的时候,传入真实数据,实参;把真实数据赋值了一份给形参;
  • 相互不影响:传入简单值类型,互不影响;
  • 核心点:函数里面和函数外面,没有关系;
  // 特点(规则):形参与实参相互不影响;
  // 形参:外面不能使用;和外面没有任何关系;只能函数内部使用;
  // 实参:把实参的数据,赋值(复制)了一份给形参;

  function fn(a) {
    a = a + 10;
  }

  var a = 10;
  fn(a);
  // a = a;
  // 前面a:形参,只能在函数内部使用,和外面没有关系;
  // 后面a:实参,外面的实参把自己的值,赋值(复制)了给里面的形参a;
  • 什么时候配置形参:形参,内部的变量,只能在内部使用;既然只能在内部使用,和外面没有关系,那么什么时候需要配置形参?如果外面的数据需要给内部加工下,那就配置形参;实参传入真实数据;
  • 里面加工,和外面没有关系;如何把里面的加工给到外面呢?返回值值;
        // 实参多  形参少  实参会按照顺序传递给形参  多余的实参不传值
        // 形参多  实参少  多余的形参undefined
        function fn(a, b, c, d) {
            console.log(a, b, c,d);
        }
        fn(1, 2, 3)

# 函数return返回值

  • 作用:函数内部运算出来的一切和外面没有任何;如果外面想用内部运算完的结果,设置返回值;
  • return 返回的意思,其实就是给函数一个 返回值终断函数

# 终断函数

  • 当我开始执行函数以后,函数内部的代码就会从上到下的依次执行

  • 必须要等到函数内的代码执行完毕

  • return 关键字就是可以在函数中间的位置停掉,让后面的代码不在继续执行

  • 语法:
  function fn(a) {
    a = a + 10;
    // 内部:只能在函数内部使用,把变量后面真实数据返回出去;
    // 关键字:return;
    return a;
  }

  // 外面:需要找个变量接受
  var b = fn(10);
  console.log(b);
  • 特点规则:
// 特点(规则):
//  1. 作用:函数返回值,把内部的值进行返回,返回到外面;
//  2. 只要函数内部出现了return,函数内return下面的代码(函数内)不再执行;
//  3. 如果return 后面没有任何数据(变量),默认返回undefined;
//  4. 如果连return都没有,函数就没有返回值,执行函数,默认返回undefined;


// 规则2:
function fn(a) {
    a = a + 10;
    // 内部:只能在函数内部使用,把变量后面真实数据返回出去;
    // 关键字:return;

    return a;
    // 函数内部 return下面的代码不再执行;
    console.log("--------------------------------------------");
}


// 规则3:
function fn() {
    return;
}
var a = fn();
console.log(a);

// 规则4:
function fn() {
    // return;
}
var a = fn();
console.log(a);
  function fn(a, b) {
            //return 把函数运行的结果 返回给函数调用
            return a + b;
        }
        var res = fn(2, 5) + 3;
        console.log(res);

     // 1.如果函数没有return 默认返回undefined 
        // 2.函数体里面只有return return后边没有值 返回undefined
        // 函数体里面return后面的代码不执行
        // 4.有return并且后边有值 就是把return后边的值返回给函数调用
        function fn(a,b) {
            return a+b;
        }
        var res=(a+b);
        console.log(res);

# 函数的优点

  • 函数就是对一段代码的封装,在我们想调用的时候调用
  • 函数的几个优点
    1. 封装代码,使代码更加简洁
    2. 复用,在重复功能的时候直接调用就好
    3. 代码执行时机,随时可以在我们想要执行的时候执行

# 小结

  • 函数:把一些复用代码 封装 起来,在未来 调用
  • 需求:函数里面的功能不能写成固定代码;变活;
  • 参数:
    • 形参:函数内部的变量,只能在函数内部玩耍;函数的外面不能使用;即使外面的变量和内部的变量同名,也没有任何关系;
    • 实参:实际参与运算的数据,把实参的数据,赋值(复制)了一份给形参;
  • 返回:如何函数里面加工完结果,外面需要,设置返回值 return 数据;
  • 核心:函数把代码分成 里面 和 外面;里面和外面没有任何关系;
    • 两座桥:
      • 外面的数据 怎么 进入函数内部?参数;
      • 函数内部的数据怎么 给到函数的外面?返回值;
        // 让用户输入任意两个数的和
        // 函数声明的时候 小括号里面的是形参 形式上的参数
        // 函数调用的时候,小括号里面的是实参
        // 实参传值给形参 相当于给形参赋值
        function getSum(a, b) {
            var sum = 0;
            for (i = a; i <= b; i++) {
                sum += i;

            }
            console.log(sum);
        }
        getSum(1, 100);

# 习题

// 封装一个函数 比价a,b,c的大小
        // function fn(a, b, c) {
        //     if (a > b && a > c) {
        //         return alert(a);
        //     } else if (b > a && b > c) {
        //         return alert(b);
        //     } else if (c > b && c > a) {
        //         return alert(c);
        //     }

        // }
        // fn(8, 4, 5)
  // 封装一个函数 求n-m的和 比如用户输入了10 输入了100 求10-100的和
        function sum(n, m) {
            var sum = 0;
            for (var i = n; i <= m; i++) {
                sum += i;
            }
            return sum;
        }
        console.log(sum(10, 100));
        var res = sum(10, 100);

        // 封装一个冒泡排序的函数 输出排序之后的结果
        function sort(arr1) {
            for (var i = 0; i < arr1.length - 1; i++) {
                for (var j = 0; j < arr1.length - 1 - i; j++) {
                    if (arr1[j] > arr1[j + 1]) {
                        var temp = arr1[j];
                        arr1[j] = arr[j + 1];
                        arr[j + 1] = temp;

                    }

                }
            }
            return arr1;
        }
        var arr = [3, 3, 6, 2, 8, 3];
        var res = sort(arr);
        console.log(res);

   // 封装判读一个数是否是质数的函数
        var num = Number(prompt('请输入一个数字'));
        function isZhiShu(a) {
            for (var i = 2; i < a; i++) {
                if (a % i == 0) {
                    return alert('不是质数');
                }
            }
            return alert('质数');
        }
        isZhiShu(num)

# arguments 伪数组

        // 封装一个函数 实现求任意个数的最大值
        function getMax() {
            // arguments伪数组 是把实参元素放到一个数组里面  方便
            // console.log(arguments.length0);
            // for(var i=0;i<arguments.length;i++){
            //     console.log(arguments[i]);
            // }

            var max = arguments[0];
            for (var i = 1; i < arguments.length; i++) {
                if (max < arguments[i]) {
                    max = arguments[i];
                }
            }
            return max;
        }
        var res = getMax(12, 3, 5, 6, 365, 6555, 23);
        console.log(res);
  • 解决:多个参数的问题;

  • 目标:无论输入多少个参数,都可以参加运算;

  • 语法:arguments,获取所有实参的伪数组,函数内部的变量(不是我们声明的,也不需要我们声明)

function fn(){
  console.log(arguments);
}
fn(1); // 输出 [1]
fn(1,2) // 输出 [1,2]
fn(1,2,3,4,5) // 输出 [1,2,3,4,5]
  • arguments 这个东西看起来样子像数组,但是其实不是一个数组,我们管它叫 伪数组。它具有数组的长度和顺序等特征。本质为对象,
  • arguments 伪数组可以循环遍历
function getSum(){
  var sum = 0;
  for(var i = 0; i < arguments.length ; i++){
    sum += arguments[i];
  }
  return sum;
}

getSum(1,2,3);// 输出 6
getSum(1,2,3,4,5); // 输出15
  • 应用场景:当我们不知道我们的参数个数的时候;
// 函数表达式 声明函数
        var 函数名=function(){
            函数体
        }
        var getSum=function(a,b){
            console.log(a+b);
        }
        getSum(3,2);

# 函数表达式

  • js中声明函数的方式不只有一种,还有一种方式叫函数表达式
  • 声明变量,赋值为函数;
// 
var 函数名 = function (参数){
   //函数体
}

var getSum = function(a,b){
  return a + b;
}
getSum(10,20);

# 匿名函数

  • 匿名函数:没有名字的函数,但是在js的语法中,是不允许匿名函数单独存在的,要配合其它语法使用:

    如:

function (参数){
  函数体
}

var fn = function(a,b){
  return a + b;
}
  • 自调用函数(自执行函数):匿名函数的另外一种使用方法;很多时候,我们需要加载页面后,自动执行一个函数;
// 定义之后,立刻调用,输出10
(function(){  
  console.log(10);  
})();
//函数名里面存储的是函数的代码
//自调用函数(自执行函数) 自己调用自己  立即执行
           // (匿名函数)();
            (function(){
                console.log(20);
            })();

# 函数类型

function fn(){}
console.log(typeof fn);  // 输出字符串的function
  • 在js中,只要是一种数据类型的,都可以作为函数的参数
function f1(a,b){
  return a + b;
}
f1(10,20); // 数字作为参数
f1('abc','def') // 字符串作为参数

# 回调函数(了解)

  • 函数有数据类型,也可以作为别的函数的参数传入;
// fn 只不过在函数内部是一个形参,内部变量;
function f1(a,fn){
  console.log(a);
  // 函数的调用,在函数名的后面加括号;
  // 内部的函数对外面的函数叫回调函数;
  fn(); 
}

function f2(){
  console.log('f2函数执行了');
}
f1(10,f2);// 输出 10 和 'f2函数执行了'
  • 像这种作为函数的参数,并在之内调用的函数,我们称为 回调函数

# 作用域

  • 全局:
    • 全局作用域规则:全局的变量,能在JS部分的任何位置都可以访问;
    • 全局变量:在全局作用哉下声明的变量;
  • 局部:
    • 局部作用域:只能在局部的作用域范围进行访问;
    • 局部变量:在局部作用域下声明的变量;
var a = 10;
function f1(){
  console.log(a);
}
f1();// 变量a在函数外定义,可以在函数内使用


function f2(){
  var b = 20;
}
// 变量b在函数内定义,在函数外无法访问,报错: b is not defined
console.log(b); 
  // 作用域  生效的范围
        // 全局作用域 在整个js代码都生效
        // 全局变量 在函数外面用var声明的变量就是全局变量
        // 局部作用域 在函数体里边生效
        // 局部变量 在函数体里边用bar声明的变量
        // 特殊情况  在函数体里边不用var 变量=赋值 是全局变量
        // 特殊情况  函数形参是局部变量

# 作用域链

作用域链 这个变量当前作用域没有会去上一级找, 找到为止

# 预解析

// 预解析 就是js代码执行之前, 提升变量声明和函数声明 提升到当前作用域的最顶端
        // 函数声明在最上边  变量声明次之

        function fn() {
            console.log(22);
        }
        var a;
        console.log(a);
        a = 20;
        fu();


 // console.log(a);
        // var a = 20;
        // fu();
        // function fn() {
        //     console.log(22);
        // }

# 利用函数完成数组冒泡从大到小排序 去重

 // 使用函数完成数组冒泡排序和数组去重
        function fn(arr1) {
            for (i = 0; i < arr1.length - 1; i++) {
                for (j = 0; j < arr1.length - 1 - i; j++) {
                    if (arr1[j] < arr1[j + 1]) {
                        var temp = arr1[j];
                        arr1[j] = arr1[j + 1];
                        arr1[j + 1] = temp;
                    }
                }
            }
            return arr1;
        }
        var arr2 = [12, 52, 12, 16, 52, 100, 100]
        var res = fn(arr2);
        console.log(res);


        function fn2(a) {
            var newArr = []
            for (i = 0; i < a.length - 1; i++) {
                flag = true;
                for (j = 0; j < a.length - 1 - i; j++) {
                    if (a[i] == newArr[j]) {
                        flag = false;
                        break;
                    }
                }
                if (flag) {
                    newArr[newArr.length] = a[i];
                }

            }
            return newArr;
        }
        var tt = fn2(res);
        console.log(tt);

# 案例小娜

# 字符串转数组的方法

 var str = '来点字|哈哈哈|大傻瓜';
        // 字符串转数组的方法
        var arr = str.split('|');
        console.log(arr);

//求和
    var str = '1|2|3';
        // 字符串转数组的方法
        var arr = str.split('|');
        var sum = 0;
        for (i = 0; i < arr.length; i++) {
            sum += Number(arr[i]);
        }
        console.log(sum);
        // console.log(arr);

# 随机数

 var joke = ['笑话1', '大傻瓜2', '笑话3'];
        // joke[]
        // Math是一个数学计算的对象
        // 返回一个随机数 范围[0,1) 包含0不包含1
        var a = Math.random();
        a = a * joke.length;
        a = Math.floor(a);
        alert(joke[a]);
  // function getSum() {
        //     var num = prompt('请输入1-2-3格式的数字');
        //     var arr = num.split('-');
        //     var sum = 0;
        //     for (var i = 0; i < arr.length; i++) {
        //         sum += Number(arr[i]);
        //     }
        //     alert(`求和的结果是${sum}`);
        // }

        // function getTime() {
        //     var time = new Date();
        //     var year = time.getFullYear();
        //     var month = time.getMonth() + 1;
        //     var day = time.getDate();
        //     var h = time.getHours();
        //     var f = time.getMinutes();
        //     var m = time.getSeconds();
        //     alert(`${year} 年 ${month} 月 ${day} 日 ${h} 时 ${f} 分 ${m} 秒`);
        // }

        // function getJoke() {
        //     var joke = ['笑话1哈哈哈', '笑话2大傻瓜', '笑话3喝多了', '笑话4吐一脸'];
        //     var i = Math.floor(Math.random() * joke.length);
        //     alert(joke[i]);
        // }
var xiaoNa = {
            getSum: function () {
                var num = prompt('请输入1-2-3格式的数字');
                var arr = num.split('-');
                var sum = 0;
                for (var i = 0; i < arr.length; i++) {
                    sum += Number(arr[i]);
                }
                alert(`求和的结果是${sum}`);
            },
            getTime:function () {
                var time = new Date();
                var year = time.getFullYear();
                var month = time.getMonth() + 1;
                var day = time.getDate();
                var h = time.getHours();
                var f = time.getMinutes();
                var m = time.getSeconds();
                alert(`${year}${month}${day}${h}${f}${m}`);
            },
            getJoke:function() {
            var joke = ['笑话1哈哈哈', '笑话2大傻瓜', '笑话3喝多了', '笑话4吐一脸'];
            var i = Math.floor(Math.random() * joke.length);
            alert(joke[i]);
        }
        }
        var flag = true;
        while (flag) {
            var mes = prompt('您好,我是小娜,请选择操作的功能\n1.求和\n2.系统时间\n3.笑话\n4.退出');
            switch (mes) {
                case '1':
                    // getSum();
                    xiaoNa.getSum();
                    break;
                case '2':
                    // getTime();
                    xiaoNa.getTime();
                    break;
                case '3':
                    // getJoke();
                    xiaoNa.getJoke();
                    break;
                case '4':
                    alert('你不爱小娜了吗')
                    flag = false;
                    break;
                default:
                    alert('请输入1或2或3或4');
                    break;
            }
        }

# 对象

  • JS核心概念:万物皆对象,我们在编程中,使用对象来描述万事万物。
  • 对象:使用属性描述事物的特征,使用方法来描述功能, 就是对象这种语法。
  • 对象**:属性和方法的集合体**;
  • 数组:数据集合体;
  • 对象 描述 扳手 :
    • 属性(特征):名称 金属、银白色,
    • 方法:能拧螺丝、防身等;

# 创建对象

# 字面量创建对象

 // 对象是属性和方法的几何体
        // 字面量创建对象
        var dog = {};
        // 对象添加属性 对象.属性=值
        dog.name = '旺财';
        dog.age = 6;
        // 对象添加方法 对象名.函数表达式
        dog.height = 50;
        dog.eat = function () {
            console.log('吃骨头');
        }

        dog.cell = function () {
            console.log('汪汪叫');
        }
        // 调用对象的属性 对象名.属性
        console.log(dog.name);
        // 调用对象的方法 对象名。方法名()
        dog.eat();

# 通过字面量初始化对象时,初始化属性

  // 2.字面量初始化对象;
        var cat = {
            // 添加属性  属性:值
            // 键名 值  键值对
            name: 'tom',
            height: 30,
            color: 'orange',
            // 添加方法 方法名:匿名函数
            eat: function () {
                console.log('吃鱼肉');
            },
            play: function () {
                console.log('玩球');
            }
        }
        console.log(cat.name);
        console.log(cat.height);
        cat.eat();

# 使用键的方法添加属性和方法

    // 使用键的方法添加属性和方法
        var pig = {};
        // 添加属性 对象名['属性']=值
        pig['name'] = '佩奇';
        pig.height = 172;
        pig.weight = 172;
        pig['age'] = 26;
        // 添加方法  对象名['方法名']=匿名函数
        pig['demo'] = function () {
            console.log('敲代码');
        }
        console.log(pig['age']);
        console.log(pig.name);
        // 调用方法 对象名['方法名']()
        pig['demo0']();

# 利用构造函数创建对象

  • 构造函数

    • 构造函数:是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 运算符一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面。

    • 构造函数的封装格式:

      function 构造函数名(形参1,形参2,形参3) {
           this.属性名1 = 参数1;
           this.属性名2 = 参数2;
           this.属性名3 = 参数3;
           this.方法名 = 函数体;
      }
      
    • 构造函数的调用格式

      var obj = new 构造函数名(实参1,实参2,实参3)
      
      

      以上代码中,obj即接收到构造函数创建出来的对象。

     //通过构造函数创建数组
            // var arr = new Array();
            // 构造函数 定义一类对象的属性和方法
            // 1. 在构造函数代码开始执行之前,创建一个空对象;
            // 2. 修改this的指向,把this指向创建出来的空对象;
            // 3. 执行函数的代码
            // 4. 在函数完成之后,返回this---即创建出来的对象
    // 通过构造函数创建对象
            // 构造函数 定义一类对象的属性和方法
            function SuperStar(a, b, c) {
                // this.属性=形参接收过来的实参的值
                this.name = a;
                this.age = b;
                this.height = c;
                this.sing = function (song) {
                    console.log('经典老歌' + song);
                }
            }
            // 通过构造函数SuperStar这个构造函数创建ldh的对象
            var ldh = new SuperStar('刘德华', '59', 172, '冰雨');
            console.log(ldh);
            // 通过构造函数SuperStar这个构造函数创建gfc的对象
            var gfc = new SuperStar('郭富城', '56', 172, '哈哈哈');
            console.log(gfc);
            console.log(gfc.name);
            gfc.sing('爱不完');
    
    • 注意事项

      1. 构造函数约定首字母大写
      2. 函数内的属性和方法前面需要添加 this ,表示当前对象的属性和方法。
      3. 构造函数中不需要 return 返回结果
      4. 当我们创建对象的时候,必须用 new 来调用构造函数
    • 其他

      构造函数,如 Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类(class)
      创建对象,如 new Stars(),特指某一个,通过 new 关键字创建对象的过程我们也称为对象实例化

  • new关键字的作用

    1. 在构造函数代码开始执行之前,创建一个空对象;
    2. 修改this的指向,把this指向创建出来的空对象;
    3. 执行函数的代码
    4. 在函数完成之后,返回this---即创建出来的对象
  • js 给我们内置了一个 Object 构造函数

  • 这个构造函数就是用来创造对象的

  • 当 构造函数 和 new 关键字连用的时候,就可以为我们创造出一个对象

  • 因为 js 是一个动态的语言,那么我们就可以动态的向对象中添加成员了

# object创建对象

// 就能得到一个空对象
var o1 = new Object() 

// 正常操作对象
o1.name = 'Jack'
o1.age = 18
o1.gender = '男'

# 对象使用for...in遍历

 var ldh = {
            name: '刘德华',
            age: 59,
            ['height']: 172,
            sing: function () {
                console.log('冰雨');
            },
            ['film']: function () {
                console.log('赌神');
            }
        }
        ldh['film']();
        console.log(ldh);
        // 遍历对象
        //for (var key in obj) {

       // }
        for (var key in ldh) {
            // 遍历键名
            console.log(key);
            // 遍历值
            console.log(ldh[key]);
        }

# 内置对象

//内置对象的学习方法
        // 有没有实参
        // 功能
        // 返回值
        // 圆周率
        // console.log(Math.PI);
        // 没有参数  返回一个[0,1)的随机浮点数(小数) 包含0 不包含1
        var a = Math.random();
        console.log(a);
        // 返回一个0-10的随机整数
        var b = parseInt(Math.random() * 11);
        var arr = ['狗', '猫', '猴', '老虎'];
        // 0-3的随机数
        var c = parseInt(Math.random() * 4);
        alert(arr[c]);

# es6模拟字符串

 var a = 39, b = 28, c = 10;
        // ${变量名} 其他的该怎么写怎么写
        console.log(`a的大小是,${a}b的大小是,${b}c的大小是,${c}`);
   document.write('<div style="width:100px; height:20px; background-color:skyblue"></div>');
   // 随机数实现多线条
var h = parseInt(Math.random() * 31);
        for (var i = 0; i <= h; i++) {
            var x = parseInt(Math.random() * 256);
            var y = parseInt(Math.random() * 256);
            var z = parseInt(Math.random() * 256);
            document.write(`<div style="height:40px;   background-color:rgb(${x},${y},${z})"></div>`);

        }

# 内置对象

# Math

  • Math.random();这个方法的作用是生成一个 [0,1) 之间的随机浮点数
 //没有参数 返回一个[0, 1)的随机浮点数(小数) 包含0,不包含1
    // var a = Math.random();
    // // console.log(a);
    // // 返回一个0-10的随机整数
    //   var b  = parseInt(Math.random()*11)     //  0 -  10.99999999
    // //   console.log(b);
  • Math.floor(x) 地板函数:把一个浮点数进行向下取整
console.log(Math.floor(3.1));  // 3
console.log(Math.floor(3.9));  // 3
console.log(Math.floor(-3.1)); // -4
console.log(Math.floor(-3.9)); // -4
  • 案例:刷新页面,页面改变颜色;
  function getRandom() {
    return Math.floor(Math.random() * (255 + 1));
  }

  function getRandomColor() {
    var r = getRandom();
    var g = getRandom();
    var b = getRandom();
    var color = 'rgb(' + r + ',' + g + ',' + b + ')';
    return color;
  }

document.write(`<div style='background:${getRandomColor()}'></div>`)
  • Math.round(x) 把一个浮点数进行四舍五入取整
console.log(Math.round(3.1));  // 3
console.log(Math.round(3.9));  // 4
console.log(Math.round(-3.1)); // -3
console.log(Math.round(-3.9)); // -4
  • Math.ceil(x) :天花板函数 把一个浮点数进行向上取整,向比数据大的方向取整;
console.log(Math.ceil(3.1));  // 4
console.log(Math.ceil(3.9));  // 4
console.log(Math.ceil(-3.1)); // -3
console.log(Math.ceil(-3.9)); // -3
  • Math.abs(x) :求一个数的绝对值 正数
console.log(Math.abs(3));  // 3
console.log(Math.abs(-3)); // 3
  • Math.max(x,y...) 求多个数字中的最大值,同理 Math.min(x,y...);
console.log(Math.max(10,20));  // 20
console.log(Math.max(8,4,5,7,3)); // 8

console.log(Math.min(10,20));  // 10
console.log(Math.min(8,4,5,7,3)); // 3

# Date


        var time = new Date();
        // 获取系统年份
        // console.log(time);
        var year = time.getFullYear();
        // console.log(year);
        // 获取当前月份 月是从0-11 所以记得加一
        var month = time.getMonth() + 1;
        // console.log(m);
        // 获得当前几号
        var day = time.getDate();
        // console.log(day);
        // 获取周几
        var week = time.getDay();
        // console.log(week);
        // 获取时
        var h = time.getHours();
        // console.log(h);
        // 获取分
        var f = time.getMinutes();
        // console.log(f);
        // 获取秒
        var m = time.getSeconds();
        var now = `${year}${month}${day}${h}${f}${m}`;
        console.log(now);

创建指定的时间对象

// 创建指定的时间对象
        var time = new Date('2015-10-10 15:30:20');
        var h = time.getHours();
        // console.log(h);
        console.log(time);
        var time = new Date(2015, 9, 10, 15, 12, 23);
        console.log(time);

# 时间戳


        // 时间戳
        // var time=new Date();
        // console.log(time.valueOf());
        // console.log(time.getTime());
        // console.log(1*time);
        // console.log(Date.now());
        // h5新增加的时间戳的写法 某一个时间点据世界时间(1970年1月1日)的总毫秒数
        // var time=+new Date();
        // console.log(time);
        // 倒计时
        // 距现在的时间戳
        var now = + new Date();
        // console.log(now);
        // 距将来19点的时间戳
        var fut = +new Date('2020-12-10 19:00:00');
        // 将来总毫秒-现在的总毫秒数
        var time = fut - now;
        var miao = Math.floor(time / 1000 % 60);
        var fen = Math.floor(time / 1000 / 60 % 60);
        var xiaoshi = Math.floor(time / 1000 / 60 / 60 % 24);
        console.log(`${xiaoshi}${fen}${miao}`);

# 简单类型和复杂类型

# 规则

  • JS 数据都是存在内存上的,内存上分为两个地方: 栈 堆;只要var 变量,就要在 栈上开个格子;
  • 简单类型 存储在内存的栈空间
  • 复杂类型 存储在内存的堆空间

# 简单类型的储存

 // 简单数据类型
 function fn(b) {
    // 局部变量b 
    b = 2;
 }

 var a = 1;
 fn(a)
// b = a;
 console.log(a);  // ?

1573804596171

# 复杂类型的储存

  // 复制数据类型
  function f2(o) {
    o.name = '翠花';
  }
  var a = {
    name: '狗蛋'
  }
  f2(a);
  // 最终a的name属性是多少?翠花
  console.log(a.name);

1573805492480

  • 练习:
var obj_a = {};
var obj_b = obj_a;

// true 同类型,比值:同一个地址
console.log(obj_b == obj_a);


// false 同类型,比值:不同的地址;
var obj_a = {};
var obj_b = {};
console.log({} == {});

# 变量 属性 函数 方法的区别

1.变量和属性的相同点 他们都是用来存储数据的

  • 变量 单独声明并赋值 使用的时候直接写变量名 单独存在的
  • 属性 在对象里面的不需要声明的 使用的时候必须是对象.属性 2.函数和方法 的相同点 都是实现某种功能 做某种事
  • 函数是单独声明 并且调用的 函数名() 单独存在的
  • 方法 在对象里面 调用的时候对象.方法

# 内置对象

# Array数组

# 数组首末位置的增删

        /*     内置对象的学习方法
            有没有参数
            功能
            返回值 */
        var arr = [1, 2, 3];
        // 数组名.push[参数1, 参数2, 参数3]; 有参数 个数不固定 功能在数组的末尾添加元素 返回数组的长度
        var a = arr.push(4, 5, 6);
        console.log(a);
        // 数组名.unshift(参数1, 参数2, ...参数n) 有参数 个数不固定 功能 在数组的起始处添加元素 返回数组长度
        var b = arr.unshift(7, 8, 9);
        console.log(b);
        // 数组名.pop() 无参 功能 删除数组的最后一个元素  返回被删除的元素
        var c = arr.pop();
        console.log(c);
        // 数组名.shift() 无参 功能 删除数组的第一个元素 返回的是被删除的元素
        var d = arr.shift();
        console.log(d);

# splice:可进行数组任何位置的增删改

// 数组的splice方法用于从数组的指定位置移除、添加、替换元素
var arr = ['a','b','c','d','e'];
  // arr.splice(a,b,c...n) 有参  第一个参是索引 功能第2个参是索引开始删除的个数,第三个参开始 从索引的前边开始添加元素 返回的是数组 如果有删除的元素,数组里面是删除元素

// 对原数组操作
// 作用:从索引3开始移除,总共移除1个元素 ,
// 返回:被移除元素的数组
arr.splice(3,1); 
console.log(arr);


// 在c的后面添加7和8两个元素
// 作用:从索引3开始添加,移除0个元素,把7,8加入;
// 返回:一个空数组
// 操作原数组;
arr.splice(3,0,7,8); 



// 作用:从索引1开始替换,总共替换1个,用0替换 ;
// 返回:被替换元素的数组
arr.splice(1,1,0);
console.log(arr); 

# 拼接与截取

  • concat 拼接数组,不改变原数组,创建新数组返回
  // concat 
  // 作用:数组的拼接
  // 参数:要拼接的数据(单个数据、多个数据、单个数组,多个数组)
  // 返回:拼接后的 新 数组;

  // var arr1 = [1, 2, 3];
  // var arr2 = [4, 5, 6];
  // var arr3 = [7, 8, 9];
  // var res = arr1.concat(arr2, arr3);
  // console.log(arr1, res);
  • slice 截取数组:不对原数组操作,返回的是截取出来新的数组;
  // slice:
  // 作用:截取数组
  // 参数:
  // 返回:被截取的新数组;
  var arr = ['a', 'b', 'c', 'd', 'e'];
  // 参数:2个参数。第一个参数从哪个下标开始(包括),截取到哪个下标结束(不包括),
  // var res = arr.slice(1, 4);
  // console.log(arr, res);


  // 参数:1个参数,从哪个下标开始,一直到结尾都要截取
  // var arr_1 = arr.slice(1);
  // console.log(arr_1);

  // 参数:没有参数,全部截取,复制数组;
  // var res = arr.slice();

# 与字符串互转

  • join 用于将数组中的多元素以指定分隔符连接成一个字符串
  // 数组名.join() 有参(可以无参) 功能数组转字符串 参数是分隔符 返回的是转换之后的字符串
var arr = ['刘备','关羽','张飞'];
var str = arr.join('|'); 
console.log(str);  //  刘备|关羽|张飞
  • split 字符串的方法:转数字,后面为分隔的字符
// 字符串.split() 有参(可以无参) 功能是字符串转数组 参数是分隔符 返回转换之后的数组
// 这个方法用于将一个字符串以指定的符号分割成数组
var str = '刘备|关羽|张飞';
var arr = str.split('|');
console.log(arr);

# 查找元素

  • indexOf:根据元素查找索引,如果这个元素在数组中,返回索引,否则返回-1,找元素在不在数组内部
  // indexOf  【!!!】
  // 参数:被查找的元素
  // 返回:下标(没有找到返回-1)

  // 场景:查找数组中有没有我们需要的数据;
  // var arr = [1, 10, 20];
  // var index = arr.indexOf("a");
  // console.log(index);

// 数组名.indexOf() 有参 功能 查找 正向查找参数是不是数组的元素 如果是 返回的第一个查找的元素索引值
        var arr1 = ['a', 'd', 'c', 'd', 'e'];
        var index = arr1.indexOf('d');
        console.log(index);
        // 数组名.lastIndexOf() 有参 功能 查找 反向查找参数是不是数组的元素 如果是 返回的第一个查找的元素索引值
        var arr1 = ['a', 'd', 'c', 'd', 'e'];
        var index = arr1.lastIndexOf('d');
        console.log(index);
  • findIndex方法用于查找满足条件的第一个元素的索引,如果没有,则返回-1 了解;
  // findIndex
  // 语法:
  // 参数:函数(被传入的函数,回调函数)
  //      格式要求:
  //          item  回调函数,代表每一次遍历的数据
  //          return 判断条件(自己写)
  // 返回:满足条件的第一个元素的下标,若没有,返回-1;
  // var index = arr.findIndex(function(item) {
  //   return item === 20;
  // });
  // console.log(index);
// 数组名.findIndex(匿名函数) 有参 参是匿名函数 功能正向查找 满足条件的元素 返回的是正向第一个满足条件的元素的索引值
        var arr = [10, 20, 30, 40, 50];
        var res = arr.findIndex(function (item) {
            return item > 20;
        });
        console.log(res);

# 遍历数组

  • for循环:JS基础语法;【!!!】
  • forEach:遍历数组;
  // 如何学习?关注参数?返回是什么?
  // 不关注什么?内部如何实现不用关注。3年后可以看内部如何实现;

  // forEach:  
  // 作用:遍历数组
  // 参数:函数(函数函数)格式要求:
  //      函数函数参数:item,index,arr
  //      item:每个数据
  //      index:下标;
  //      arr:当前遍历的数组;

  // var max = arr[1];
  // arr.forEach(function(item, index, arr) {
  //   // console.log(item, index, arr);
  //   if (item > max) {
  //     max = item;
  //   }
  // });
  // console.log(max);

        // 数组名.forEach(function (item, index, arr){
        //     item 是数组的每一项元素
        //     index 索引
        //     arr 当前遍历的数组
        // })
        var arr = [10, 20, 30, 40, 50];
        var sum = 0;
        arr.forEach(function (item, index, arr) {
            sum += item;
        })
        console.log(sum);
  • filter 筛选出数组中满足条件的数组,返回是一个新的数组;
  // filter  
  // 作用:对当前数组一定的过滤;
  // 参数:函数(函数函数)格式要求:
  //      函数函数参数:item,index,arr
  //      item:每个数据
  //      index:下标;
  //      arr:当前遍历的数组;
  //      return 过滤条件; 返回是true,把当前满足条件的item 放入新的数组中
  // 返回:返回过滤后的新数组;

  var arr_1 = arr.filter(function(item, index, arr) {
    // 过滤条件; 返回是true,把当前满足条件的item 放入新的数组中
    return item == 10;
  });
  console.log(arr, arr_1);
     // 数组名.filter(function(item,index,arr){
        //     /* return 条件
        //     item 当前数组的每一项
        //     index 索引
        //     arr 当前组 
        //     参数是匿名函数  功能筛选条件 返回满足条件的数组 数组里面是满足条件的元素  如果不满足条件 返回的是空数组
        //     */
        // }
        // )
        var abc = [10, 20, 30, 40, 50];
        var res = abc.filter(function (item, index, arr) {
            return item > 10;
        })
        console.log(res);

# 数组去重

 var arr = [12, 2, 2, 12, 3, 6, 2, 8, 2];
        newArr = [];
        // 思路: 用原数组中的每一项去新数组中查询 如果不存在 添加到新数组
        for (var i = 0; i < arr.length; i++) {
            // 用老数组中每一项去新数组中查询 返回-1说明老数组这一项 在新数组中不存在
            if (newArr.indexOf(arr[i]) == -1) {
                // 老数组中的这一项添加到新数组
                newArr.push(arr[i]);
            }
        }
        console.log(newArr);

# 冒泡排序

  var arr = [15, 6, 8, 45]
        var res = arr.sort(function (a, b) {
            return a - b;
        })
        console.log(res);

# 字符串

# String

# 不可变

  • 特性:不可变性;

  • 旧的字符串赋值在一个变量上,给变量重新赋值新的字符串(完全新的字符串,或者拼接后字符串),旧的字符串不是被覆盖;在内存的游离状态;

  • 所以尽量避免大量使用字符串的拼接;这个算前端性能优化的一点;

    • 提升前端性能:

# 查找

  • indexOf 字符串中是否存在指定字符 存在就返回找到的下标,没有就-1;
// 这个方法用于查找某个字符串是否包含于另一个字符串
var str = '我爱中华人民共和国';
console.log(str.indexOf('中华'));
  • lastIndexOf 用法和indexOf一样,只不过是从后面开始找,【了解】;
  • charAt:【了解】
// 这个方法用于获取字符串中位于指定位置的字符
var str = '我爱中华人民共和国';
console.log(str.charAt(2));
  • charCodeAt :【了解】
// 这个方法用于获取字符串中位于指定位置的字符的ASCII码
var str = 'abcdef'
console.log(str.charCodeAt(0));

# 转为数组

  • split 字符串转数组,后面的分隔的字符
// 这个方法用于将一个字符串以指定的符号分割成数组
var str = '刘备|关羽|张飞';
var arr = str.split('|');
console.log(arr);
  • 案例:解析地址b.com?id=1&name=2中的参数;

# 拼接与截取

  • +隐式转化;
  • concat 拼接
    • 两者的区别:https://www.cnblogs.com/zheting/p/7643458.html
// 这个方法用于连接多个字符串;
var res = "abc".concat('def','ghi');
console.log(res);
  • substring 截取字符串,不操作原字符串;返回截取出来的字符串;
// 这个方法用于获取字符串中的部分字符
var str = '我爱中华人民共和国';

// 从索引2开始,到索引4结束,得到之间的字符,不包含索引4的字符
var res = str.substring(2,4);
console.log(res);
  • slice
// 这个方法用于获取字符串中的部分字符
var str = '我爱中华人民共和国';
var res = str.slice(2,4);// 从索引2开始,到索引4结束,得到之间的字符,不包含索引4的字符
console.log(res);

// 看起来和substring 没有啥区别,
// 但是 slice()可以设置参数为负数,slice()方法在遇到负的参数的时候,会将这个负值与字符串的长度相加。
console.log(str.slice(-6,7));
console.log(str.slice(2,-5));
console.log(str.slice(-9,-7));
  • substr
// 这个方法用于获取字符串中的部分字符
        // 字符串.substr(索引, 截取的个数) 有参(最少一个) 功能 截取字符串从索引开始   第2个参  截取的个数
var str = '我爱中华人民共和国';
var res = str.substr(2,2);// 索引2开始,总共获取2个字符,第二个参数为个数

# 索引

 // 字符串方法
        var str = '西红柿土豆西瓜'
        // 字符串的长度 字符串.length
        console.log(str.length);
        for (i = 0; i < str.length; i++) {
            console.log(str[i]);
        }
        // 字符串.indexOf(参) 有参 功能正向查找  返回正向查找存在该字符 返回第一个的索引值 如果查找不到 返回-1
        var a = str.indexOf('西');
        console.log(a);
        // 字符串.indexOf(参) 有参 功能反向查找  返回反向查找存在该字符 返回第一个的索引值 如果查找不到 返回-1
        var b = str.lastIndexOf('西');
        console.log(b);

  // 字符串.charAt(参) 功能参数是索引值 根据索引找字符 返回  索引位置对应的字符
        // var str = '西红柿土豆西瓜';
        // console.log(str.charAt(2));
        var str = '西红柿土豆西瓜';
        for (var i = 0; i < str.length; i++) {
            console.log(str.charAt(i));
        }
        // 字符串.charCodeAt(索引值) 有参 功能 根据索引找到字符 返回的是ascll编码
         var str = 'a西红柿土豆西瓜';
         var b = str.charCodeAt(0);
         console.log(b);

# 字符串分割小案例

        // b.com?id=1&name=2  实现的功能 var obj = { id:1, name: 2 }
        var str = 'b.com?id=1&name=2';
        var obj = {};
        // ["b.com", "id=1&name=2"]
        var arr1 = str.split('?');
        // console.log(arr1);
        // ["id=1", "name=2"]
        var arr2 = arr1[1].split('&');
        // console.log(arr2);
        for (i = 0; i < arr2.length; i++) {
            var arr3 = arr2[i].split('=');
            var key = arr3[0];
            obj[key] = arr3[1];
        }
        console.log(obj);

# 字符串的拼接截取

    // 字符串.concat(字符串1,字符串2...) 有参 ,功能 拼接字符串  返回的是拼接之后的字符串
        var str = '哈哈哈';
        var str1 = '土豆';
        var str2 = '西红柿';
        var b = str.concat(str1, str2);
        console.log(b);
        var str = '我爱中华人民共和国';
        //字符串 .substring (索引值 ,索引值)有参 (最少一个) 功能 截取字符串[索引值,索引值) 返回的是截取的字符串
        var b = str.substring(3, 6);
        console.log(b);
        var str = '我爱中华人民共和国';
        var a = str.slice(2, 5);
        // 特殊情况 如果索引值出现负值  开始的长度(索引+字符串.length)
        var a = str.slice(-10, 5);
        console.log(a);

# 字符串出现的次数案例


        var str = 'abccccccaaabbdet'
        var obj = {
            // 'a': 1,
        }
        for (var i = 0; i < str.length; i++) {
            var chars = str.charAt(i);
            // 判断对象中有没有chars属性
            if (obj[chars]) {
                
                obj[chars]++;
            } else {
                // 给对象添加属性和值
                obj[chars] = 1;
            }
        }
        var max = 0;
        for (var key in obj) {
            if (max < obj[key]) {
                max = obj[key];
                var zf = key;
            }
        }
        console.log(max, zf);

let var cos

//     let: 每次循环生成一个独立的块作用域 {i = 0}
  //  var 声明的变量,只要是函数外边,是全局变量,let 和 const 生效范围是块级作用域
        // var 声明的变量可以重复声明,let 和 const 不可以 const 多次赋值都不行
        // var 和 let 只声明,不赋值, undefined  const 必须赋值,不赋值,会报错
        // var 声明的在window有映射,let 和 const没有
        // var 声明的变量会预解析提升,let 和 const 不会
        // es6 函数里边和函数外边  块级作用域 {}

# 文档