javascript

1.JavaScript的介绍和基本类型

.什么是JS

JS是JavaScript的简称
JavaScript是什么?
作用区分:
HTML: 用于呈现网页的内容
CSS: 用于设置网页u样式
Javascript: 设置页面特效
JS的作用:
1.用于校验用户输入的表单数据
2.用于与用户进行交互式体验
3.Ajax 异部加载技术
4.实现瀑布流 无刷新加载数据

.如何在HTML中使用JS

1.直接在head标签中定义Script标签定义JS
2.可以在HTML标签中直接使用JS事件属性设置JS
3.可以使用script标签引入外部后缀为.js的文件
<script src="xxx.js"></script>
4.在超连接href属性中使用javascript标识定义符

.JS的内容

JS:
客户端浏览器的JS
1.ECMAScript的核心语法结构(如何使用js, 如何定义js的变量
2.包含DCM的对象
3.包含BCM的对象
变量: 储存值的容器 声名一个变量 后续方便的使用和计算

###HTML中使用JS的方法:
            1.直接在head标签中定义script标签来定义JS
            2.可以在HTML标签中直接使用JS事件属性设置
            3.可以使用script标签引入外部后缀名为.js的文件
            4.在超链接href属性中使用javascript标识定义符
JS中声名一个变量
声名变量uname, 给变量uname的值进行赋值, 值为孙悟空
var uname = '孙悟空';
//打印变量   --- 在控制台打印变量uname
console.log(name); 
//J弹出警告框
alert("弹出一个警告框");  

1.0变量的类型

    显式变量类型
    Number 数值类型
    Boolean 布尔类型
    String      字符串类型
    function 函数类型
    Object     对象类型
    Undefined   未定义
    简短记忆缩写: bsofun(be so fun 如此有趣)

变量的命名规则:

首字符必须是英文字母 下划线 $
后面跟任意长度的数字 字母 下划线 $
严格区分大小写
不允许使用系统的关键字和保留字
    关键字: js已经使用的名字
    保留字: 系统打算去用 但目前还没有用
命名尽量有意义 要见名思意
推荐使用驼峰命名法
    变量名如果由多个单词组成 第一个单词的首字母小写,其他单词的首字母大写

弱类型语言

     变量的类型是随着值的变换而变化的

1.1 变量类型转换

      强项类型转换: 
              调用特定的函数转为类型
              Number()/parseInt()/parseFolat  数值类型
              Boolean()   布尔类型
              function()   函数
              string()         字符串
              Object()       对象
              Undefined 未定义

1.2 自动类型转换:

               根据程序执行的环境发生自动类型转换 某个瞬间充当了某种类型 但是自身的变量类型是没有发生改变的

1.3 强制类型转换

其他类型转为数值类型
使用Number()函数将其他数值变量转为强制类型
1.数值类型以原样输出
2.布尔值
true 转为1
false 转为0
3.字符串类型
空格字符串空字符串转为数值类型 0
字符串时符合结构的数值返回对应的数值
只要有非数字字符转为NaN
4.未定义类型转为NaN
5.函数 对象都转为NaN

var num = 100;
var bool = true;
var bool = false;
var res = Number(bool); 
//定义字符串类型
var str = "nduoa";   //NaN
var str = '123';           //123
var str = " ";                // 0 
var str = "123.jioefhji"  //NaN
var str = '123.5';           //123.5
var res = Number(str); 
//undefined 类型
var a =  undefined;
var res = Number(a);  //NaN 
//对象或者函数
var obj = new Object();
var res = Number(obj);
function abc(){}
var res =  Number(abc);
console.log(res);

1.4 parseInt() 将其他类型的变量尝试转为数值类型的整数

1.数值类型:
整数 原样不变
小数 去除小数 保留整数
2.布尔值类型全部转为NaN类型
3.字符串类型
首字母是否为数值类型
不是 直接转换为NaN
是 只识别对应有效的整数

  1. undefind 转为NaN
var num = 123;      //123
var num = 123.5;  //123 取整数
var res = parseInt(num);

var bool = true;  //NaN
var bool = false; //NaN
var res = parseInt(bool);

var str = '123';     //123
var str = '123.5'   //123
var str = '123abc'   //123
var str = 'a123abc'   //NaN
var str = '  '   //NaN
var str = ""    //NaN
var res = parseInt(str);
console.log(res);

1.5 parseFloat() 尝试将其他类型的变量转为数值类型的小数

  1. 数值类型直接原样输出
    2.布尔类型为NaN
    3.字符串类型
    首字母是否为数值
    是 进行有效的识别为有效小数
    不是 直接转换为NaN
    4.未定义类型 直接转换为NaN
var bool = true;
var bool = false;
var res = parseFloat(bool);

var str = '123';        //123
var str = '123.5.6';  //123.5
var str = 'a123.5';   //NaN
var res = parseFloat(str);

var res = parseFloat(undefined); //NaN
console.log(res);

1.6 其他类型变量转为布尔值为假的情况:

1.布尔值类型的假
2.数值类型的假
0/0.0/NaN
3.为定义类型 Undefined
4.字符串类型的 空字符串为假 剩下的为真

var num = 1;       //true
var num = -1;      //true
var num = 0;       //false
var num = 0.0;   //false
var num = NaN; //false
var res = Boolean(num);
var u = undefined;
var res = Boolean(u);
var str = 'abc';     //true
var str = '0';          //true
var str = ' ';            //true
var str = '';             //false
var res = Boolean; 
console.log(res);

1.7 流程控制的单分支解构

if(条件表达式 --一定充当的是一个布尔值){
//流程体
}
执行规则 当表达式为真时 执行流程体 为假时什么都不发生

var a = 10;  //number
//a是数值类型  if条件表达式中充当了布尔类型, 自动转为布尔类型的true, 本身a变量类型没有变化
if(a){
    console.log('杨思涵有一个绿帽子');
}
//打印变量a的变量类型
console.log(typeof a);  //number


二.JavaScript运算符

2.1 逻辑运算符: 最终返回的条件 一般都是布尔值

逻辑或    ||
  只要有一边的表达式为true 都能返回true 
  两侧同时为假时 返回假
  逻辑断点: 当左侧表达式为true时 最终结果注定为true 右侧表达式不再执行
  左侧为真 返回左侧值 左侧为假 返回右侧值
逻辑与    &&
  逻辑与左右两侧都有表达式 当左右两侧都为布尔值true时 最终返回true
  逻辑断点: 左侧为假时 结果已经注定 右侧表达式不再执行
  左侧为真 返回右侧数据 左侧为假 返回左侧数据
逻辑非    !
  取反  真变成假  假变成真 
var a = 3;
var b = 4;
// 逻辑与 && 两边同时为true 才返回true 否则不返回
if (a > 4 && b < 5 ){
    console.log('两个条件都满足');
}

2.2 运算符划分:

作用: 算术 比较 赋值 逻辑判断 连接 
参与运算的变量数量: 
    一元运算符: 参与运算的变量有一个
                            a++ a-- !a
    二元运算符: 参与运算的变量有两个
                            + - * / % ....
    三元运算符(三木运算符):
                            表达式?真区间:假区间
                            执行规则: 表达式为真, 走真区间 否则走假区间
var a = 3;
var b = 4;
//三元运算符
var c = true?a:b;
console.log(c);
//判断男女性别 1表示男 0表示女
var sex = 0;
var res = sex ==1?'男':'女'; 
console.log(res);


三.流程控制

分支结构:
倾向于范围值的判断

3.1 if分支

3.11 单分支 if

格式:
            if(表达式){
                流程体.
            }
            规则: 表达式为真 执行流程体 否则不执行
3.12 双分支 if .... else
格式:
            if(表达式){
                真流程体
            }else{
                假流程体
            }
            规则: 表达式为真 执行真流行体 否则执行假流行
3.13 多分支 if ... else ... if
格式:
            if(表达式1){
                表达式1为真 进行执行
            }else if(表达式2){
                表达式2为真 执行
            }else if(表达式3){
                表达式u3为真 执行
            }
            ......
            else{
                当以上流程都不满足条件时执行的流程
            }
var age = 88;
 if (age <= 10){
     console.log('黄口之年')
 }else if ((age>=10) && (age<=20)){
    console.log('舞象之年')
 }else if ((age>=20) && (age<=30)){
    console.log('弱冠之年')
 }else if ((age>=30) && (age<=40)){
    console.log('而立之年')
 }else if ((age>=40) && (age<=50)){
    console.log('不惑之年')
}else if ((age>=50) && (age<=60)){
    console.log('知命之年')
}else if ((age>=60) && (age<=70)){
    console.log('耳顺之年')
}else if ((age>=70) && (age<=80)){
    console.log('古稀之年')
}else if ((age>=80) && (age<=90)){
    console.log('杖朝之年')
}else if ((age>=90) && (age<=100)){
    console.log('鲐背之年')
}else if (age>=100){
    console.log('奇迹')
}else{
    console.log('奇葩年纪 重新输入')
}

switch 多分支结构

更多的倾向于固定值(标量)的判断

var sex = '男';
//switch  选择 开关
switch(sex){
    //case表示某种情况
    case '男';
        //流程
        console.log('去女厕所犯法 ');
        break;  //表示流程的终止
    case '女';
        //流程
        console.log('去男厕所不犯法');
        break;//终止流程
    //设置默认情况
    default:
            console.log('上哪儿 自己看着办...');
            break;
}

3.2三大循环结构

循环结构:
固定结构+执行规则

3.21 while循环
while(条件表达式){
        循环体
    } 
执行规则:
        当表达式为真 执行循环体
        循环体执行完毕 会自动再次判断条件表达式
        满足条件再次执行循环体
        不满足条件跳出循环
//定义变量
var i = 1;
//输出1-100的书
 //console.log(1);  在控制台输出
//在页面中输出使用 document.write()
// document.write(i);
//定义初始变量sum 接受进行累加
var sum = 0;
while(i <= 100){
//     document.write(i)
//     document.write('<br>');  //输出换行符
//每一次将i的值累加到sum上
sum = sum + i;
i++; //改变i的值
//进行变量与字符串的拼接
document.write(i + '<br>');
document.write( 'i的值是: ' + i + '<br>');
} 
document.write('1到100的累加和是' + sum);

document.write('<hr>');
3.22 do...while循环
    do{
        循环体
    }while(条件表达式)

执行规则:
先执行循环体 再次判断条件表达式
满足条件继续执行循环体
不满足条件跳出循环
do...while 和 while的区别:
功能上没有区别
执行规则的区别:
while 先判断条件在执行
do..while 先执行在判断条件

//使用do..while结构计算1-100的累计和
var i = 1;
//sum接受累加和
var sum = 0 ;
do{
    //sum = sum + i ;
    //累加
    sum += i;
    //改变i的值
    i++;
}while(i <= 100);
console.log('i的值是:' + i);
console.log('1-100的累加是: ' + sum);
3.23for循环
//使用for循环计算1-100的累加和
var sum = 0;     //接收累加和
for (var i = 101; i <= 100; i++){
    //累加
    sum += i;
}
console.log('i的值是:' + i);
console.log('1-100的累加是: ' + sum);

3.24四个方向的九九乘法表

左下角的九九乘法表
document.write("<h3 align='center'>左下角的九九乘法表</h3>")
//定义表格
document.write('<table width="600px" align=center border="1 solid red" height="300px"cellspacing="0" cellpadding="3">');
    
    //定义行数
   for (var hang=1; hang<=9; hang++){
    document.write('<tr>');
    //定义列数 每一行里面的列数不能超过行数
    for (var lie=1; lie<=hang; lie++){
        document.write('<td>');
            document.write(hang + "x" + lie + "=" + hang*lie);
        document.write('</td>');
    }
    document.write('</tr>');
   }
document.write('</table>');
document.write('<hr>');
左下角乘法表.png

左上角的九九乘法表

document.write("<h3 align='center'>左上角的九九乘法表</h3>")
//定义表格
document.write('<table width="600px" align=center border="1 solid red" height="300px"cellspacing="0" cellpadding="3">');
    
    //定义行数
        for(hang=1; hang<=9; hang++){
            document.write('<tr>');
                //定义列数
                for(lie=9; lie>=hang; lie--){
                    document.write('<td>');
                        document.write(lie + 'x' + hang + '=' + hang*lie);
                    document.write('</td>');    
                }
               
            document.write('</tr>');
        }
document.write('</table>');
document.write('<hr>');
左上角乘法表.png

右上角的九九乘法表

document.write("<h3 align='center'>右上角的九九乘法表</h3>")
//定义表格
document.write('<table width="600px" align=center border="1 solid red" height="300px"cellspacing="0" cellpadding="3">');
    //定义行数
    for(hang=1; hang<=9; hang++){
        document.write('<tr>');
        //引入第三个变量 控制空白格子的输出
        for(var k=0; k<(9-hang); k++){
            document.write('<td ></td>');
        } 
        //定义列数 列数从最大值像最小值变化
        for(lie=hang; lie>=1; lie--){ 
            document.write('<td>');
                document.write(lie + 'x' + hang + '=' + lie*hang);
             document.write('</td>');
        }
        document.write('</tr>'); 
    }
document.write('<table>');
document.write('<hr>');
右下角乘法表.png

右上角的九九乘法表

document.write("<h3 align='center'>右上角的九九乘法表</h3>")
//定义表格
document.write('<table width="600px" align=center border="1 solid red" height="300px"cellspacing="0" cellpadding="3">');
    //定义行数
    for(hang=9; hang>=1; hang--){
        document.write('<tr>');
        //引入第三个变量 控制空白格子的输出
        for(var k=0; k<(9-hang); k++){
            document.write('<td ></td>');
        } 
        //定义列数 不超过当前的行数 同时列数从最大值向最小值变化
        for(lie=hang; lie>=1; lie--){ 
            document.write('<td>');
                document.write(lie + 'x' + hang + '=' + lie*hang);
             document.write('</td>');
        }
        document.write('</tr>'); 
    }
document.write('<table>');
右上角乘法表.png

四.JavaScript函数

概念:
函数是一段完成指定任务的已命名代码块
作用:
将重复的功能进行封装 进行独立 在需要的位置进行复用
一次声明 多次调用
便于后期维护和更新
函数的组成: 函数名+函数体
函数的结构:
function 函数名(){
//函数体
}
函数的参数:
形参: 函数定义时小括号里面的参数叫形式上的参数
实参: 函数调用时小括号里面的参数叫实际上的参数
函数作用域:
局部作用域: 函数的内部
全局作用域: 函数的外部
局部变量: 在函数的内部使用var关键字定义的变量
全局变量: 在函数的外部使用var关键字定义的变量
特点:
1.局部变量是无法直接影响全局变量的
2.在局部作用域的变量中可以使用全局作用域的变量
当函数内部的变量不存在时 会向函数的外部 父级以及先辈作用域进行变量查找
作用域链:
函数内部变量在进行查询时 遵守的规则
1.首先从函数自身所在的作用域进行查找
2.如果没有 向父级或者先辈作用域进行查找
3.如果还没有 最终的值就是undefined
局部变量影响全局变量的方式:
1.在函数的内部不使用var关键字定义变量
2.使用return关键字将局部变量的值返回到函数的外部 使用对应的变量进行接受
注意: 程序遇见return关键字后将不在继续执行

4.10函数的定义方式

4.11使用function关键字定义函数
        函数一旦申明 它允许在任何位置调用(函数定义前 函数定义后 函数的内部)  只使用于function 关键字的函数
function table (){
    //实现定义表格的函数
    document.write('<table width="600" height="300" cellspacing="0" cellpadding="3" align="center" border="1" >');
        //7行
        for (var i=0; i<7; i++){
            //隔行换色
            var bgColor= i % 2 == 0 ? 'red': 'green';
            document.write('<tr bgcolor="'  + bgColor + '">');
                //输出8列
                for(var j=0; j<8; j++){
                    document.write('<td></td>');
                }
            document.write('</tr>');
        }
    document.write('</table>');
}
table();
document.write('<hr>');
4.12使用new Function构造函数定义函数
        new Function() 调用中最末尾的参数是函数体 其他前面的都是参数
//使用new Function构造函数定义函数
var hello = new Function ('uname', 'alert("Hello, " + uname)');
document.write(typeof hello + '<br>');
document.write( hello + '<br>');
hello('尊敬的主人');
4.13可以使用函数表达式的形式定义函数
            将匿名函数赋值给变量
            var abc = function (){
                console.log('匿名函数赋值给变量')
            }
            使用函数表达式 new Function构造函数定义的函数 不能在函数定义前使用
4.14函数的调用:
函数名();
4.15函数名的命名规范: 和变量的命名规范一致
1. 首字符必须是字母 下划线或者$
2. 后跟任意长度的数字 字母 下划线 $
3. 严格区分大小写
4. 不能使用系统的关键字和保留字
5. 名字尽量有意义
6.推荐使用驼峰命名法

4.20函数类型

按照函数格式(形式)的不同 进行划分:
1.有参数的函数 无参数的函数
2.匿名函数 回调函数 立即执行函数
3.闭包函数 递归函数

/**
 * 定义实现表格的函数Table()
 * @param number row 表格的行数
 * @param number col 表格的列数
*/
/默认实现7行8列的表格
unction table (row=7, col=8){
    /*
        设置函数参数的默认值
            1.直接在函数定义的位置的小括号中进行赋值
            2.低版本默认值的处理   //当参数无默认值时 默认值是undefined
                row = row != undefined ? row :7;
                col = col != undefined ? col : 8;
    */ 
   //输出表格的固定格式
   document.write('<table border="1" width="600" height="300" cellspacing="0" align="center" cellpaddin
    //输出行数
    for (var i=0; i<row; i++){
        document.write('<tr>');
            //列数
            for(var j=0; j<col; j++){
                document.write('<td>');
                document.write('</td>');
            } 
        document.write('</tr>');
    }
   document.write('</table>');
able();  //7行8列
ocument.write('<hr>');
able(10,10);  //10行10列
/实现单击#red元素 将元素变为圆形 背景颜色改成红色
/1.获取元素  --使用ID的方式获取元素
/如果元素存在 返回对应的对象 不存在返回null(空对象)
ar red = document.getElementById('red') ; 
//document: 文档   get:获取    Element: 元素   By: 通过..方式
console.log(red);
//2.设置元素单击事件 onclick 当单击的时候 触发函数处理操作
red.onclick = function(){
    //alert('别瞎点');
    //当前元素设置样式
    //关键字 this 表示对象本身
    //console.log(this);
    //原生JS中 设置元素的样式属性,如果该属性名是以横线进行分割 使用驼峰命名发设置属性
    //使用.style设置元素的样式时 样式是以内联的形式生效的
    this.style.borderRadius='50%';
    this.style.background='red';
}
/*
    回调函数:
        如果一个函数A的参数是一个函数B 将函数B称为函数A的回调函数
*/
//1. 系统函数的调用  setInterval()  周期性的定时器 每隔多长时间触发函数操作
//  setInterval() 第二个参数是周期时间 以ms毫秒为单位
setInterval(function(){
    console.log('我每隔一秒执行一次');
}, 1000);
//2. 自定义函数的调用
/*
    实现过滤输出数字的功能;
    1.现在有一系列的数字
    2.根据用户调用函数的需求 输出符合条件的函数
*/
function filter(con){
    //输出1-100之间的数
    for (var i=1; i<=100; i++){
        //将变量i传如con中 经过检测判断是否符合条件 符合条件输出
        if(con(i)){ 
            console.log(i);
        }
    }
}
//定义函数 two
function two (i){
    //只负责判断是否是2的倍数 如果是返回真 不是返回假
   /* if(i%2==0){
        return true;
    }else{
        return false;
    }
    */
    //简化写法
    return i%2==0;  //比较表达式 满足条件返回true 不满足返回false
}
//定义函数five 过滤5的倍数
function five (a){
    if (a%5==0){
        return true;
    }else{
        return false;
    }
}
 //调用函数
 filter(two);  //当前的two是一个函数 是一个实参 我们称two是filter的回调函数
 filter(five);
 /*
    函数执行规律:
        主程序遇见函数 进入到函数的内部进行执行 执行完毕 将返回值返回到函数调用的位置  继续向下执行 
 */
 //立即执行参数 函数声明后立即被调用
 (function (name){
     console.log('我声明后立即被调用',(name));
 })('孙悟空');

4.3闭包函数和递归函数

闭包函数:
闭包函数的返回值是一个函数 返回的函数保留了函数定义时的作用域

//定义变量
var a = 100;
//举个例子
function abc (){
    //定义变量
    var a = 100;
    //定义函数
    function hello(){
        console.log(a);     //hello内部无变量a 向他的父级进行查询 a=100
    }
    //将申明的函数hello返回到函数的外部
    return hello;
}
var test = abc();   //调用abc 把abc的函数返回值赋值给test
console.log(test);
//调用text
test();
console.log('<hr>');

递归函数:
函数在自身的内部又调用了自身
应用的场景:
1. 计算累加 阶乘
2. 数组单元的计算等场景

//递归函数  jc只是格式上属于递归函数 但是没有实际的意义
function jc(){
    //输出变量
    console.log(100);
    //调用自身函数
    jc();
}
//调用函数 就是将函数内部的代码执行一遍
//jc();
//使用递归计算1-n的累加和
function sum (n){
    //如果n是1 不在需要计算
    if(n==1){
        return 1;
    }
    /*
        n的累加值是多少  
        1         1
        2         1+2  =  2+1的累加和 = 2+sum(2-1) = 2+sum(1)
        3         3+2+1 = 3+sum(2)
        n         n+(n-1)+(n-2)+(n-3)...+1 = n+sum(n-1) 
    */
   var res = n + sum(n-1);
   //返回结果
   return res;
}
/*
    函数执行规则:
        主程序遇见函数 先进入函数内部进行执行(原有的程序等函数执行完毕) 
        函数执行完毕之后 返回值返回到函数调用的位置 主程序继续下执行
*/
//获取1-1的累加和
var res = sum(1054);
/*
    sum(5)函数执行过程
    sum(5)
        var res = 5 + sum(5-1)
                                sum(4)
                                    var res = 4 + sum(4-1);
                                    return res;  //此刻不执行 等sum(3) 执行完毕 知道sum为1位置
        return res;     //此位置的return res不会立即执行 等sum(4)执行完毕
*/
console.log(res);
/*
    使用递归函数计算阶乘
        3! = 3x2x1
        4! = 4x3x2x1
        5! = 5x4x3x2x1
        n! = nx(n-1)x(n-2)....x1
*/
function jiecheng(n){
    //判断n ==1  一般情况下 递归都是要有终止条件的!
    if(n==1){
        return 1;
    }
    //n!= n*(n-1)
    var ji = n* jiecheng(n-1);
    //返回结果
    return ji;
}
//调用函数
var ji = jiecheng(19);
console.log(ji);
function  A (n){
    document.write(n + ' ');
    if(n>0){
        A(n-1);
    }else{
        document.write("<--------->");
    }
    document.write(n + ' ');
}
A(10);


五JavaScript对象数组的概念

对象是一个有特性(属性)和功能(方法)的集合体 万事万物都是一个对象
对象的属性可以是任意类型
对象的属性名可以是字符串 也可以是数字
对象属性和方法的操作
操作对象时: . 和 [ ]
. 后面直接跟属性名
[ ] 里面如果是字符串类型 在里面写入'属性名' 如['name']
如果是数值类型 必须使用[] 在里面输入属性的下标
如果是变量名 直接在[]里面写入变量名就行 如 [i]
删除对象的属性 delete 关键字
this 执行的上下文环境 指拥有该方法 该属性的对象

定义对象方式

5.1使用系统的 new Object()方式定义对象

//1.使用系统的new object()方式定义对象
var person = new Object();
// console.log(typeof person);    //Object
// console.log(person);
//给对象设置属性和方法   . 点操作符是对象的专用
person.name = '李海鹏';
person.agn = 17;
person.sex = '神';
//定义方法
person.fly = function(){
    console.log('我是你得不到的爸爸');
}
console.log(person);
//操作对象: 操作属性和方法
//输出属性
console.log(person.name);
console.log(person.age);
console.log(person.sex);
console.log(person.fly);
//使用方法
person.fly();

5.2使用花括号{}语法糖结构定义对象

//2.使用花括号语法糖结构定义对象
var jincheng = {
    //左侧是属性名: 右侧是属性值  多个属性之间使用,进行分割
    name: '小锦程',
    age: 17,
    sex: '神',
    love: function(){
        console.log('人丑话还多');
    }
}
console.log(jincheng)
//调用方法
jincheng.love();

5.3使用自定义的构造函数声明多个类型特点一致的对象

   //3.使用自定义的构造函数声明多个类型特点一致的对象
 /*
     构造函数: 专门用于生成对象的函数  和普通函数的区别二就是首字母大写 同事使用this关键字
 */
function Jincheng(name,age,sex,aihao){{
    //使用this关键字 this指向的就是自身
    console.log(this);
    this.name = name;  //将形参name的值赋值给this对象的name属性
    this.name = name;
    this.age = age;
    this.sex  = sex;
    this.love = aihao;      //爱好是一一个方法
    //定义自我介绍的方法
    this.intro = function(){
        //我的名字 this指向的是当前方法的所有者
        console.log ('我是' + this.name);
    }
}
//调用函数 new 关键字 专门用来实例化对象的
var sheng = new Jincheng('锦程', 20, '男', function(){
    console.log('我充满了力量');
}); 
/*
jincheng.intro = function (){
    console.log('my name is jincheng'); 
} */
var haipeng = new Jincheng('海鹏', 17, '神', function(){
    console.log('人类用沙,想捏出梦里通天塔, 为贪念不惜代价');
})
//两个对象都是由一个构造函数实例化生成的 具有相同的特点
console.log(jincheng);
console.log(haipeng);
//自我介绍
sheng.intro();
haipeng.intro();
//删除对象的属性  delete \
delete this.name;
console.log(this7); 

5.4讲this

this 到底是谁
this 执行的上下文环境 指拥有该方法 该属性的对象
JS中没有数组类型! JS中的数组是以内置对象的形式存在.
数组: 存储多个值(数组单元)的集和(仓库)
数组在进行定义时 每一个单元都有一个编号 ---索引
JS中数组的索引 从0开始 一次递增 一定是数值类型

//在最外层定义的变量 函数 对象都是挂载在顶层的window对象上
test();
var obj = {
    name: '张三',
    intro: function(){
        //this 所有看
        console.log(this.name);
    }
}
obj.intro();
//定义变量
var uname = '我是全局变量 window.uname';
//改变this指向
function printName(hello){
    console.log(this.uname + ',' + hello);
    console.log(this);
}
//调用函数
printName('你好');
//定义对象
var objA = {
    uname: '我是objA.uname'
}
/*
    apply和call方法都延长了函数的作用域环境 改变执行上下文环境
    apply()   第一个参数是对象 后面的参数以及数组的形式进行传参
        apply(objA,[参数一,参数二,...])  
    call() 
        call(objA,参数一,参数二,..)
*/
printName.call(objA,'你好');  //我是objA.uname
//printName.apply(objA,'你好');   //我是objA.uname 

5.5数组的声明方式以及数组的遍历

5.51使用new Array()构造函数定义数组
var abc = new Array('昊天斗罗','啸天斗罗','饕餮斗罗','龙神斗罗','龙皇斗罗');
console.log(typeof abc);     //object对象
console.log(abc);
//对象abc设置属性
//abc.name = '李四';    // 此刻不在是数组 而是存萃的对象
//console.log(abc);
//new Array()
var arr = new Array();       //空数组
var arr = new Array(10);         //只有一个参数   而且是数字 表明申明一个长度为10的数组
//如果有两个或者多个参数 表明数组的单元
var arr = new Array(10,1);
console.log(arr);
//数组的取值  使用[]访问数组 数组名[索引]
console.log(arr[0]);    
5.52使用[]字面量的方式定义数组
var arr = ['昊天斗罗','啸天斗罗','饕餮斗罗','龙神斗罗','龙皇斗罗'];
console.log(arr);
//获取数组长度 有几个数组单元
var chang = arr.length;
console.log(chang);
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
console.log(arr[3]);
console.log(arr[4]);
var i = 0;
console.log(arr[i]);
5.53使用循环遍历数组

for(var i = 0; i < arr.length; i++){
console.log(arr[i] + '------' + i);
}
-使用forEach()遍历数组

/*
    forEach(function(value, index, arrSelf){
        value 指向当前元素值 
        index 指向当前元素的索引
        arrSelf 指向当前数组本身
    })
    自动将数组单元一一取出放到回调函数中
*/
arr.forEach(function (value, index, arrSelf){
    console.log(value + '----' + index); 
})

-使用for ...in 遍历对象 数组

var obj = {
    uname: '孙悟空',
    age: 1000,
    sex: '男'
}
//i 自动获取Obj的属性名
for (var i in obj){
    console.log(i + '----' + obj[i]);
}
//遍历数组
for (var i in arr){
    console.log(i + '-----' + arr[i]);
}

5.6 获取HTML的方式

JS特效:
1:获取元素
2.设置元素的操作
获取元素的方式:
1.使用ID方式获取元素 documentById(ID名); 返回具体对象
2.使用class类名的方式获取元素 document.getElementsByClassName('类名') 返回类数组对象
关键字:
onmouseover 鼠标移入时
onmouseout 鼠标移除时
3.使用tagName标签名的方式获取元素 返回类数组的对象
document.getElementsByTagName('标签名')
4.使用name名字的方式获取元素 返回类数组对象
document.getElementsByName('name值')
length 长度

//document: 文档 get: 获取     Element:元素    By: 通过...方式 
var red = document.getElementById('red');
console.log(red);
//设置单击 设置元素的样式
red.onclick = function(){    //相当于给red元素的onclick属性 赋值匿名函数
    //red表示自身元素
    //red.style.background = 'yellow';
    this.style.background = 'green';
}
//对于类名为abc的元素设置鼠标悬浮时改变背景颜色
var abcs = document.getElementsByClassName('abc');
console.log(abcs); 
//第一个元素   onmouseover 鼠标移入时
for (var i=0; i<abcs.length; i++){
    //给abc下的每一个对象都设置鼠标移入事件
    abcs[i].onmouseover = function(){
    this.style.background = 'yellow';
}
    //鼠标移除 回复为红色
    abcs[i].onmouseout = function(){
        this.style.background = 'red';
    }
}
//获取所有的div元素
var divs = document.getElementsByTagName('div');
console.log(divs);
//设置所有div单击事件
for(var i=0; i<divs.length; i++){
    divs[i].onclick = function(){
        console.log('我这个元素被单击了')
    }
}
//获取pre元素
var pre = document.getElementsByTagName('pre');
console.log(pre);
//设置元素的单击事件
pre[0].onclick = function(){
    this.style.color = 'red';
}
//通过指定的name获取元素
var haha = document.getElementsByName('haha');
console.log(haha);

5.7获取元素的索引(闭包 立即执行函数)

/*
鼠标单击时 输出当前元素的索引
*/
//获取元素
var kuang = document.getElementsByClassName('kuang');
console.log(kuang);
/*
//设置单击事件
for(var i=0; i<kuang.length; i++){
    //单击事件 先绑定, 后触发
    kuang[i].onclick = function(){
        //i此刻的值是6 而不是对应元素单击时的索引
        console.log('w我被单击' + i);  //此刻i找的是一个全局变量6
    }
}
*/
/*
    1.JS执行,for循环执行 , i申明的是全局的变量, 执行完毕之后for循环后i值变为6
*/
/ console.log(i);           //6
/使用闭包函数和立即执行函数来解决问题   
for (var i=0; i<kuang.length; i++){
    /*
        1.申明并调用了立即执行函数
        2.立即执行函数返回的 return function 赋值给了onclick
    */
    kuang[i].onclick = (function(i){    //a是声明函数的新参 就是一个局部变量
        //返回一个函数
       
        return function(){
            //console.log(i);
            console.log('你好' + i);
        }
    })(i);  //立即执行函数调用是传入实参a的值
}

京东网轮播图

轮播图特效原理分析:
1.页面布局
容器 相对定位
图片 绝对定位
左右箭头 绝对定位
圆点列表 绝对定位
2.轮播图的逻辑运行原理
轮播图: 轮着显示 有一张进行显示 其他的都是隐藏的
约定: li身上有类名active的 进行显示
将active类名移动到指定元素上 那么当前元素就会显示
将active类名从某个元素上移除 该元素就会隐藏
.children 元素查找的方式 找该元素的所有子元素 返回的是一个类数组
.length 获取元素的长度
.removeAttribute 移除属性 .removeAttribute('属性名')
.setAttribute 添加属性 .setAttribute('要设置的属性名', '添加值')
圆点列表跟随图片一起运动
鼠标移入和移除事件:
第一组:
特点: 阻止冒泡
onmouseenter 鼠标移入
onmouseleave 鼠标移除
第二组:
特点: 有冒泡
onmouseover 鼠标移入
onmouseout 鼠标移除
冒泡事件: 子类元素触发某个类型的事件后, 该元素的父级以及先辈元素触发同类型的事件
--html文档--

<!-- 定义轮播图的容器lun -->
<div id="lun">
    <!-- 图片列表 -->
    <ul>
        <li class="active"><img src="./img/1.webp" alt=""></li>
        <li class=""><img src="./img/2.jpg" alt=""></li>
        <li class=""><img src="./img/3.jpg" alt=""></li>
        <li class=""><img src="./img/4.webp" alt=""></li>
    </ul>
    <!-- 定义底部的原点列表 -->
    <div id="circle-list">
        <ul>
            <li class="active-list"></li>
            <li></li>
            <li></li>
            <li></li>
        </ul>
    </div>
    <!-- 定义左右两侧的箭头 -->
    <div id="left" class="arrow"> < </div>
    <div id="right" class="arrow"> > </div>
</div>           

--css文档--

*{
    margin: 0;
    padding: 0;
}
#lun{ 
    /* 容器的大小等于轮播图图片的大小 */
    width: 520px;
    height: 280px; 
    border: 1px solid red;
    margin: 0 auto; 
    position: relative;
    
    /* 设置鼠标样式 */
    cursor: pointer;
}
#lun>ul>li{
    list-style: none;
    position: absolute;
    /* 隐藏所有元素 */
    display: none;
}
#lun>ul>li.active{
    display:  block;
}
img{
    /* 设置图片以块状元素存在 解决3pxbug问题 */
    display: block;
}
#circle-list{
    width: 100px;
    height: 20px;
    background: rgba(255, 255, 255, 0.1);
    /* background: red; */
    position: absolute;
    bottom: 20px;
    left: 50%;
    /* 让元素自身向左平移-50%(自身宽度的50%) 元素恰好居中 */
    margin-left: -50px;
    /* 边框圆角处理 */
    border-radius: 10px;
}
#circle-list>ul{
    width: 100%;
    height: 100%;
    /* 弹性盒子 */
    display: flex;
    /* 垂直方向居中 */
    align-items: center;
    /* 水平风向元素平均分布 */
    justify-content: space-around;
}
#circle-list>ul>li{
    list-style: none;
    width: 12px;
    height: 12px;
    background: #fff; 
    border-radius: 8px;
}
#circle-list>ul>.active-list{
    background: red;
}
#lun>.arrow{
    width: 25px;
    height: 50px;
    background: rgba(0, 0, 0, 0.1);
    position: absolute;
    top: 50%;
    margin-top: -25px;
    font-size: 25px;
    font-family: 宋体;
    color: #fff;
    text-align: center;
    line-height: 50px;
    /* 禁止用户选中的文字 */
    user-select:none;
}
#lun>.arrow:hover{
    background: rgba(148, 141, 141,0.8);
}
#lun>#left{
    left: 0px;
}
#lun>#right{
    right: 0px; 
}

--JS文档--

// 获取元素
var lun = document.getElementById('lun');
var circleList = document.getElementById('circle-list');
//获取左右箭头
var left = document.getElementById('left');
var right = document.getElementById('right');
//.children 元素查找的方式 找该元素的所有子元素 返回的是一个类数组
var lis = lun.children[0].children;
//获取圆点列表
var Clis = circleList.children[0].children;
//获取li的长度
var len = lis.length;
console.log(Clis);
//控制元素类名active添加和移除
//lis[0].removeAttribute('class');
//添加属性
//lis[1].setAttribute('class', 'active');
//设置标志index,标志那个Li是显示 index的值对应li的索引
var index = 0;
//定义轮播图标志
var run;
//将轮播图封装成一个函数
function autoRun (){ 
//轮播图每2s轮显一次  使用周期性定时器setInterval()
run =setInterval(function(){
    //让当前显示的元素隐藏
    lis[index].removeAttribute('class');
    //当前圆点列表样式取消
    Clis[index].removeAttribute('class');
    index++;
    //index的值临界点判断  最大值
    if(index==lis.length){
        //切换到第一张
        index = 0;
    }
    //让下一张显示
    lis[index].setAttribute('class', 'active');
    //下一个圆点列表样式添加
    Clis[index].setAttribute('class', 'active-list');
}, 2000) 
    //页面进入时调用
    autoRun();
    //设置容器的鼠标移入移除事件
    lun.onmouseenter = function(){
        //console.log('鼠标进来了');
        //鼠标移入终止轮播 停止定时器
        clearInterval(run);
    }
    lun.onmouseleave = function(){
        //console.log('鼠标出去了');
        //轮播图再次启动
        autoRun();
    }  
    //鼠标移入圆点列表时 切换对应的图片显示
    for (var i=0; i<Clis.length; i++){
        Clis[i].onmouseover = (function(i){
            //切换显示  我是第几个元素
            return function(){
               // console.log('我是..' + i)
               //之前显示的隐藏  --index
               lis[index].removeAttribute('class');
               Clis[index].removeAttribute('class');
               //当前的显示
               index = i;
               //显示
               lis[i].setAttribute('class', 'active');
               Clis[i].setAttribute('class', 'active-list');
            }
        })(i)
    }
    //左键头单击事件
    left.onclick = function(){
        //当前显示的元素隐藏
        lis[index].removeAttribute('class');
        // 上一张显示
        Clis[index].removeAttribute('class');
        //索引-1
        index--;
        //最小值的判断
        if(index<0){
            //最后一张的索引
            index = lis.length-1;
        }
        //上一张显示
        lis[index].setAttribute('class', 'active');
        Clis[index].setAttribute('class', 'active-list')
    }
    //右键头单击事件
    right.onclick = function(){
        //当前显示的元素隐藏 
        lis[index].removeAttribute('class');
        Clis[index].removeAttribute('class');
        //索引+1
        index++;
        //最大值判断
        if(index==lis.length){
            index = 0;
        }
        //下一张显示
        lis[index].setAttribute('class', 'active');
        Clis[index].setAttribute('class', 'active-list')
    }

六.JavaScript数组和基本类型值

6.1定义数组的方式:

1). 使用 new Array() 方式定义数组
2). 使用字面量 [] 的方式定义数组

6.2查询数组的方式:

1). indexOf() 正向查询数组单元 有查询的结果返回第一个对应的索引 不存在返回-1

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];
//indexOf() 正向查询数组单元 有查询的结果返回第一个对应的索引 不存在返回-1
var res = arr.indexOf('啸天斗罗');
console.log(res);

2). lastIndexOf() 倒叙查找数组单元 有查询的结果返回第一个匹配的元素索引 不存在返回-1

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗']; 
//lastIndexOf() 倒叙查找数组单元 有查询的结果返回第一个匹配的元素索引 
var res = arr.lastIndexOf('饕餮斗罗');        //5
var res = arr.lastIndexOf('饕餮斗罗2');     //-1
console.log(res);

3). concat 拼接数组 返回一个新数组

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];  
//concat.log() 拼接数组 返回一个新数组
var arr = [1, 2, 3];
var brr = [4, 5, 6];
var newArr = arr.concat(brr);
var newArr = arr.concat(brr, [4, 5, 6]);  //拼接数组
console.log(newArr);

4). join() 将数组的单元进行链接 默认返回使用逗号连接的字符串 可指定连接的字符

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];   
//join()  将数组的单元进行链接 默认返回使用逗号连接的字符串 指定连接的字符
var arr = ['李白', '白居易', '宋江', '孙悟空'];
var newStr = arr.join();          //李白,白居易,宋江,孙悟空
var newStr = arr.join('@');   //李白@白居易@宋江@孙悟空
var newStr = arr.join('');      //李白白居易宋江孙悟空
console.log(newStr);

5). reverse() 反转数组单元

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];    
//reverse()  反转数组单元
var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];
var newArr = arr.reverse();
console.log(newArr);      //["饕餮斗罗", "龙皇斗罗", "龙神斗罗", "饕餮斗罗", "啸天斗罗", "昊天斗罗"]

6). pop() 弹出数组尾部的单元 影响了原数组

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];     
//数组单元的添加 删除
//pop() 弹出数组尾部的单元 影响了原数组
var res = arr.pop();
console.log(res);

7). shift() 弹出数组的第一个单元 影响了原数组

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];      
//shift() 弹出数组的第一个单元 影响了原数组
var res = arr.shift();
console.log(res);

8). push() 从数组的尾部压入 影响了原数组 返回新数组

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];       
//push() 从数组的尾部压入 影响了原数组 返回新数组
var arr = ['鬼斗罗', '菊斗罗', '毒斗罗'];
var res = arr.push('天使斗罗');
console.log(res);  //返回数组单元
console.log(arr);

9). unshift() 从数组的前面插入 影响了原数组 返回新数组

var arr = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗',  '饕餮斗罗'];    
//unshift() 从数组的前面插入 影响了原数组 返回新数组
var res = arr.unshift('千手修罗');
console.log(res);
console.log(arr);

10). Array.isArray() 判断变量是否是数组 如果是返回true 否则返回false

//Array.isArray() 判断变量是否是数组 如果是返回true 否则返回false
var num = 10;
var res = Array.isArray(num);       //false
console.log(res);     
//定义数组
var arr = [];
var res = Array.isArray(arr);             //ture
console.log(res); 

数据存储结构:

数据在内存中的存储方式
栈:
    数据存储类似于子弹压入弹夹
    先进后出 后进先出
队列:
    类似于过桥洞
    先进先出 后进后出

数组元素的截取:
slice() 从数组中取出 不影响原数组

6.3 ES5和ES6中新提出的数组新方法:

filter() 过滤数组单元 将满足条件的元素进行过滤
当数组调用filter方法时 自动将数组的每一个单元从左到右依次放入回调函数中进行处判断处理 如果返回
true 但当前的数组单元会被返回到新数组中 否则无任何操作

//filter() 过滤数组单元 将满足条件的元素进行过滤
//定义数组
var arr = ['香蕉','萝卜','茄子','丝瓜','大西瓜'];
//选取arr中字符串的长度为3个或者3个以上的元素
var newArr = arr.filter(function(value, index){
    //作为筛选的条件 返回true的元素会被返回到新数组
    //形参value接收的是每一个数组单元的值 形参index接收的是每一个数组单元的索引
    //console.log(value,index);
    //字符串的长度 .length
    console.log(value.length);
    if (value.length>=3){
    return true;
    }
});
console.log(newArr);

map() 对数组单元进行回调函数的处理 结果返回到新数组
自动将数组单元从左到右放入到回调函数中进行处理

//当前数组包含很多个用户对象信息
var users = [
{
        uname:'刘备',
        sex: '男',
        age: '35',
    },
    {
        uname:'张飞',
        sex: '男',
        age: '32',
    },
    {
        uname:'妲己',
        sex: '女',
        age: '165',
    },
    {
        uname:'马超',
        sex: '男',
        age: '28',
    },
    {
        uname:'王昭君',
        sex: '女',
        age: '24',
    }
];
//取出所有的男性
var newUsers = users.filter(function (user){
    console.log(user);
    if(user.sex=='男'){
        return true;
    }
})
console.log(newUsers);
//map() 对数组单元进行回调函数的处理 结果返回到新数组
var arr = [1,2,3,4,5,6,7];
//获取所有数组元素的立方
var newArr = arr.map(function(value){
    //返回结果
    return value*value*value;
})
console.log(newArr); 

some() 数组中只要有一个元素满足即可, 满足条件返回true 否则返回false
some对数组单元从左到右依次检测 满足条件即返回true 终止遍历

// some() 数组中只要有一个元素满足即可,   满足条件返回true 否则返回false
var users = [
    {
        uname: '猴子',
        sex: '男'
    },
    {
        uname: '母猴',
        sex: '女'
    },
    {
        uname: '猴女友',
        sex: '女'
    },
];
//只要有男性 就满足
var  res  = users.some(function(user){
    console.log(user);
    if (user.sex == '男'){
        return true;
    }
});
console.log(res);

every() 数组中每一个元素都要满足 满足条件返回true 否则返回false
every 将数组单元进行一一遍历 如果有一个不满足条件 立刻返回false 终止遍历

//every() 数组中每一个元素都要满足 满足条件返回true 否则返回false
//必须都是男性才满足条件
var res = users.every(function(user){
    console.log(user);
    if(user.sex=='男'){
        return true;
    }
});
console.log(res);

reduceRight() 从右侧开始 向左一一执行
reduce( ) 将数组的元素从左到右依次操作

//reduce( ) 将数组的元素从左到右依次操作
//利用reduce方法进行数组单元的累加操作
var arr = [1,2,3,4,5,6,7];
//累加数组单元
var sum = 0;
arr.forEach(function(value){
    sum += value; 
});
console.log(sum);
/* 
    prevValue   上一个值
    nowValue    当前的值
    index             当前单元的索引
    arrSelf          当前数组本身
    回调函数的4个参数:
        prevValue 自动获取数组第一个单元的值, 回调函数返回的值会自动收到prevValue中
    reduce() 方法的第二个参数 可以设置prevValue的初始值
*/
var newSum = arr.reduce(function(prevValue, nowValue, index, arrSelf){
    //console.log(prevValue,nowValue,index, arrSelf);
    console.log(prevValue);
    return prevValue + nowValue;
}, 2);
//打印结果
console.log(newSum);     //28
//reduceRight() 从右侧开始 向左一一执行

6.4数组函数

toString() 将对象(包含数组)转化为字符串格式

//toString()  将对象(包含数组)转化为字符串格式
var obj = {
        uname: '孙悟空',
        age:1000
    };
var objStr = obj.toString();        // [object Object]
console.log(objStr);
//数组元素的toString()
var arr = [1, 2, 3,4 ,5 , 6];
var newStr = arr.toString();          //1,2,3,4,5,6
console.log(newStr);`

sort() 设置数组的单元以升序的进行排列
系统函数 进行数组单元的排序
需要做的就是传入一个进行比较的回调函数 具体的比较的算法是sort()自身完成 不需要管
自定义数组排序函数 --冒泡排序
每次在比较时选取当前数组中最大元素 放到数组的末尾
将相邻两个位置的值进行比较 如果前面的值>后面位置的值 交换两个值的位置
加入数组单元有六个元素
那么需要进行筛选5次
里面每次筛选是 需要执行比较次数为
1 --->5次
2 --->4次
3 --->3次
4 --->2 次
n --->6-n次

//需要对数组的元素进行排序
var arr = [100, 90, 30, 80, 50, 60, 70];
//设置数组的单元以升序的进行排列
/*
    var res = arr.sort(function(a, b){
    console.log(a,b);
    /*
        相邻两个位置进行比较 根据情况返回正数 0 负数
        正数表明 a>b
     
    //正序
    if (a>b){
        return 1;
    }else if(a<b){
        return -1;
    }else{
        return 0;
    }
});
*/

定义冒泡排序数组的方法 maopao()
@param array arr 需要进行数组排序的方法
调用函数 影响原数组或者返回新数组

function maopao(arr){
    for (var i = 0; i<arr.length; i++){
    //每次比较几次?
    for (var j=0; j<arr.length; j++){
        //比较相邻的两个数
        if(arr[j]>arr[j +1]){
            //交换两个位置
            var tmp = arr[j+1];
            arr[j+1]=arr[j];
            arr[j]=tmp;
        }
    }
}
}
//调用冒泡方法
maopao(arr);
console.log(arr);  //[30, 50, 60, 70, 80, 90, 100]

定义数组去重复的函数 arr_unique()
@param array arr 要进行数组去重复的数组
return array newArr 返回的包含所有不重复单元的数组

//自定义数组方法实现特定的要求
//数组去重复
var arr = [1,2,3,4,7,5,6,2,3,2,1,2,5]; 
function arr_unique(arr){
    //定义数组newArr 接受不重复的数组单元
    var newArr = [];
    //1.获取所有的数组元素
    arr.forEach(function(value){
        //2.将不重复的数组单元压入到newArr中  判断当前元素是否在newArr中存在 如果不存在 返回-1 将元素
        if(newArr.indexOf(value)==-1){
            newArr.push(value);
        }
    })
    //3.最后一步 将结果返回
    return newArr;
}
//调用函数
var newArr = arr_unique(arr);
console.log(newArr);

定义反转数组单元的方法 arr_reverse()
@param array arr 要进行数组单元反转的数组

var arr = ['香蕉', '菠萝', '苹果', '西瓜'];
function arr_reverse(arr){
    //定义数组 接收反转数组的单元
    var newArr = [];
    //1.取出所有的数组单元
    arr.forEach(function(value){
        console.log(value);
        //2.将取出的数组单元从newArr的前面插入
        newArr.unshift(value);
    })
    //3.返回newArr
    return newArr;
}
var arr = ['香蕉', '菠萝', '苹果', '西瓜'];
//调用函数
var newArr = arr_reverse(arr);
console.log(newArr);
//计算数组单元的个数
var arr = ['香蕉', '菠萝', '苹果', '西瓜',['荔枝','葡萄']]; //6个
//数组单元的个数
var len = arr.length;
console.log(len);
var arr = ['香蕉', '菠萝', '苹果', '西瓜',['荔枝','葡萄']]; //6个

自定义统计数组单元个数的函数 arr_rount()
@param array arr 用于计算数组单元个数的数组
return number num 最终的arr的单元个数

function arr_count(arr){
    //用于接收统计数量的变量
    var num = 0;
    //1.获取所有的数组单元进行统计
    arr.forEach(function(value){
        //2.判断当前value是否是一个数组 如果不是直接统计一次 如果是 进入到数组内部进行统计 统计的结果
        if(Array.isArray(value)){
            //如果是 对当前的数组value再次调用统计数组单元个数的函数 arr_count
            num += arr_count(value);   //此次函数调用了自身 称之为递归函数 
        }else{
            num++;
        }
        
    })
    //3.返回结果
    return num;
}
var newNum = arr_count(arr);
console.log(newNum);
//计算数组的最大值的函数
var arr = [100, 90, 200, 201, [1000,50]];
function arr_max(arr){
    //设置最大值的标志
    var max;
    //比较 设置一个存储最大值的标志
    arr.forEach(function(value){
        //如果你是一个数组 针对当前的数组获取数组的最大值 将当前的max与数组返回的最大值进行比较
        if(Array.isArray(value)){
            //针对该数组调用获取最大值的函数 判断max是否存在
            if(max==undefined){
                max = arr_max(value);
            }else{
                if(arr_max(value)>max){
                    max = arr_max(value);
                }
            }
        }else{
            //如果max是undefined 将第一个数直接赋值给max
            if(max == undefined){
                max = value;
            }else{
                if (value>max){
                    //将value的值赋值给max max一直存储的就是最大值
                    max = value;
                }
            }
        }
    })
    //返回结果
    return max;
}
var max = arr_max(arr);
console.log(max);

七.JavaScript获取方式

7.1)Math.random() 获取0-1之间的随机数 能取到0不能取到1

Math.floor() 去除小数部分

//获取0-1之间的随机整数
//0.? 舍去小数 获取的就是0    1.? 舍去小数 获取的就是1
var num = Math.floor(Math.random() * 2);
console.log(num);
//获取1-3之间的随机整数 相当于获取0-2之间的随机整数在加1
var  num = Math.floor(Math.random()* 3) + 1;
console.log(num);
//获取2-5之间的随机整数 相当于获取0-3之间的随机整数在+1
var  num = Math.floor(Math.random()* 4) +2;
console.log(num);

7.2) 定义获取m,n之间的随机整数 rand()

@param number m 表示随机数的起始值
@param number n 表示随机数的结束值
return number num 最终获取的随机数

function rand (m, n){
    //计算的方式 相当于获取0-(m-n)之间的随机整数 +m
    var num = Math.floor(Math.random()*(n-m+1))+m;
    //返回值
    return num;
}
//获取0,1之间的随机数
var num = rand(0,1);
console.log(num);
//验证定义的函数在获取随机数时的概率是否一致
//随机1-5之间的数 随机2000次 每一个数取到的次数
//定义统计数量的变量
var num_1 = 0;
var num_2 = 0;
var num_3 = 0;
var num_4 = 0;
var num_5 = 0;
for(var i = 0;i<2000; i++){
    var num = rand(1,5);
    //使用swith结构匹配结果
    switch(num){
        case 1:
        num_1++;
        break;
        case 2:
        num_2++;
        break;
        case 3:
        num_3++;
        break;
        case 4:
        num_4++;
        break;
        case 5:
        num_5++;
        break;
    }
}
console.log('2000次随机获取 1出现的次数' + num_1 + ', 所占的比例' +(num_1 * 100/2000) + '%');
console.log('2000次随机获取 2出现的次数' + num_2 + ', 所占的比例' +(num_2 * 100/2000) + '%');
console.log('2000次随机获取 3出现的次数' + num_3 + ', 所占的比例' +(num_3 * 100/2000) + '%');
console.log('2000次随机获取 4出现的次数' + num_4 + ', 所占的比例' +(num_4 * 100/2000) + '%');
console.log('2000次随机获取 5出现的次数' + num_5 + ', 所占的比例' +(num_5 * 100/2000) + '%');

7.3) 随机数和定时器

//随机数部分
//获取元素
var btn = document.getElementById('btn');
var uname = document.getElementById('uname');
//判断元素是否被获取成功
console.log(btn , uname);
//单击btn按钮 改变uname的值
//innerHTML 获取 设置元素的HTML的内容
//获取
//console.log(btn.innerHTML);
//设置
//uname.innerHTML = '昊天斗罗';
//定义包含所有的用户名的数组
var users = ['昊天斗罗', '啸天斗罗', '饕餮斗罗', '龙神斗罗', '龙皇斗罗', '
//解决定时器叠加  --定义定时器的标志
var rum;
//btn的单击事件
btn.onclick = function(){
    //用户单击按钮到底是开启还是要停止
    console.log(this.innerHTML);
    // console.log(rum);
    
    if(this.innerHTML == '开始'){
        if (rum){
        //终止程序的运行
        return;
    }
    //启动周期性的定时器 不听的修改名称
    rum = setInterval(function(){
        //定时器每次调用时 index的值改变
        var index = rand(0, users.length-1);   //索引取值范围
        //如何动态的获取用户的名称
    uname.innerHTML = users[index]; 
    },18)
    //元素自身的内容变成停止
    this.innerHTML = '停止';
    }else{
        //清除定时器
        clearInterval(rum);
        //清除定时器的标记
        rum = undefined;
        //自身变开始
        this.innerHTML = '开始';
    }
}

7.4)math数学对象

获取Math的相关信息
console.log(Math);
常量
Math.PI π

 var PI = Math.PI;
 console.log(PI);
 //e
 console.log(Math.E);

abs() 绝对值

 var a = -1;
 var newA = Math.abs(a);
 console.log(newA);

Math.random() 获取一个0-1之间的随机数, [0,1) 能获取0 但是获取不到1

 var rand = Math.random();
 console.log(rand);

Math.ceil() 进一取整 向上走一位

 //定义变量
 var a = 12.045;   //13
//var a = -1.2;   //-1
//Math.ceil() 进一取整 向上走一位
var newA = Math.ceil(a);
console.log(newA);
//Math.floor() 舍去取整 去一取整 向下走一位
var newA = Math.floor(a);        //-2
console.log(newA);
//Math.round() 四舍五入
var a = 2.499999999999999999999999999999;
var newA = Math.round(a);
console.log(newA);          //2

弦度2π 和 度360 ===>2π = 360
Math.sin() 求正弦值 需要的是弧度
Math.cos() 求余弦值 需要的是弧度

//计算90°的正弦值  --将90°转为弧度
var value = Math.sin(90 * 2 * Math.PI / 360);      //1
var value = Math.sin(0 * Math.PI / 180);                //0
var value = Math.sin(30 * Math.PI / 180);             //趋向于1/2
console.log(value);
//0的余弦值
var value = Math.cos(0 * Math.PI /180);   //1
var value = Math.cos(100 * Math.PI /180);   //-1
console.log(value);
//正切值  Math.tan()
var value = Math.tan(0 * Math.PI /180);   //0
var value = Math.tan(90 * Math.PI /180)  
console.log(value);
//余切值 是正切值的倒数
var value = 1 / Math.tan(90 * Math.PI / 180);
console.log(value);
//27 开平方 乘方 乘立方 Math.pow(m,n) m的n次幂
var res= Math.pow(3, 2);      //9
var res = Math.pow(27, 1/3);        //   1/n  开n次方
var res= Math.pow(1024, -1/10);  //设置为负数 相当于1/m的n次幂
console.log(res);
/*通过目前学习的函数 定义获取m,n之间的随机整数的函数 rand()
         rand(m, n)
         rand(1, 3) 返回1-3之间的随机整数1 2 3 

7.5)时间对象以及获取的方式

Date 时间对象
存储的是和时间相关的信息
计时:
从1970年1月1日0时0分0秒开始存储获取的
0时区为参考点 --本初子午线
获取时间对象

var date = new Date(); 

将时间对象以及本地化的形式打印

console.log(date.toLocaleString()); 

时间对象以字符串的形式进行输出

console.log(date.toString());
//中国 北京所在的时区为参考点 东八区 每隔一个时区相差一个小时

getTime()

var time = date.getTime();
console.log(time);

获取年份

var year = date.getFullYear();
console.log(yea

获取月份 getMonth() 实际返回的值比实际的月份少1

var month = date.getMonth() +1;
console.log(month);

获取日 getDate()

var  day = date.getDate();
console.log(day);

获取小时 getHours()

var hours = date.getHours();
console.log(hours);

获取分钟 getMinutes()

var minutes = date.getMinutes();
console.log(minutes);

获取秒 getSeconds()

var seconds = date.getSeconds();
console.log(seconds);

获取毫秒 getMilliseconds()

var ms = date.getMilliseconds();
console.log(ms);

星期 getDay() 返回的是0-6之间的整数

var week = date.getDay();
console.log(week);

获取指定时间的时间对象的方式:
1.传入时间戳
2.传入合法可识别的时间格式字符串
3.按照年月日时分秒毫秒的顺序写入参数 定义指定的时间 注意: 月份会自动加10
获取1970年1月1日0时0分0秒的时间对象

var date = new Date(1000);
console.log(date.toLocaleString());

2017年11月11日11点11分11秒

var time = new Date('2017-11-11 11:11:11');
console.log(time.toLocaleString());

定义指定时间 --传入的月份会自动+1

var time = new Date(2017, 11, 27, 17, 00, 10, 100);
console.log(time.toLocaleString());

7.6)网站时间显示和倒计时

css代码:

*{
    margin: 0px;
    padding: 0px;
}
#show{
    width: 500px;
    height: 100px;
    border: 3px solid red;
    border-radius: 15px;
    margin: 0px auto;
    text-align: center;
    line-height: 100px;
    margin-top: 100px;
    font-size: 25px;
}
#show1{ 
    width: 600px;
    height: 80px;
    background: rgb(1, 37, 19);
    border-radius: 10px;
    margin: 0px auto; 
    /* 设置弹性盒子 */
    display: flex;
    /* 横轴 */
    justify-content: center;
    /* 纵轴 */
    align-items: center;
    margin-top: 100px;
}
.time{
    width: 36px;
    height: 36px;
    border-radius: 10px;
    background: #60a060;
    font-size: 20px; 
    color: #fff;
    text-align: center;
    line-height: 36px;
}
.maohao{
    font-size: 24px;
    padding: 0 3px;
    color: #fff;
}

html代码:

<!-- 计时器 -->
<div id="show">
    <!-- 2019年10月18日 8:58 星期五 -->
</div>
<!-- 网站抢购倒计时 -->
<div id="show1">
       <div class="time" id="hour">23</div>
       <div class="maohao">:</div>
       <div class="time" id="minute">59</div>
       <div class="maohao">:</div>
       <div class="time" id="second">59</div>
</div>

网站时间JavaScript代码:

//定义获取当前时间的函数setTime(){ 
function setTime(){ 
//Date 时间对象 
    //获取元素
var show = document.getElementById('show');
//获取年月日时分秒星期
var time = new Date();
//获取年份
var year = fillZero(time.getFullYear());
//获取月份
var month = fillZero(time.getMonth());
//获取日数
var day = fillZero(time.getDate());
//获取小时
var h = fillZero(time.getHours());
//获取分钟
var m = fillZero(time.getMinutes());
//获取秒数
var s =fillZero(time.getSeconds());
//获取星期几
//定义数组
var weeks = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六', ]
var week = weeks[time.getDay()] ;
// console.log(year, month, day, h, m, s, week);
//不满足10的数补充一个0
/*
    补充前导0的函数 dillZero()
    @param number i 需要判断是否要进行补充前导的变量
    return number i      返回最终处理后的结果
*/
function fillZero (i){
    //判断是否小于10 \
    if(i<10){
        //补充0
        i = '0' + i;
    }
    //返回结果
    return i;
}
//设置show元素中的内容
show.innerHTML = year + '年' + month + '月' + day + '日' + h + '时' + m + '分' + s + '秒' + week;
} 
//当用户进入页面的第一时间 手动调用一次设置网站时间
setTime();
//调用定时器
setInterval(function(){
    setTime();
},1000)

倒计时JavaScript代码

 //网站倒计时       --  当前时间  活动开始时间
 //定义补充0的函数  fillzero()
 function fillZero1(i){
     return i = i<10 ? '0'+i : i;
 }
 //获取对象
 var hour = document.getElementById('hour');
 var minute = document.getElementById('minute');
 var second = document.getElementById('second'); 
 //定义活动开始的时间
 var start = new Date(2019, 9, 18, 12, 00);
 //定义活动开始的差值
 var cha;  
 //定义设置倒计时的函数 setTime
 function setTime1(){
     //当前时间
 var now = new Date();
 //计算时间的差值 : 时间对象直接相减, 等效于 start.grtTime()  -  now.getTime()
 var cha = start - now;   //差值的单位是毫秒数
 // console.log(cha);
 /*
     1. 正常倒计时 活动开始
     2.进入页面 活动已经开始
 */
 //判断
     if(cha<=0){
         //说明活动开始
         //设置时间显示为00:00:00
         hour.innerHTML = fillZero1(0);
         minute.innerHTML =  fillZero1(0);
         second.innerHTML =  fillZero1(0);
         //程序终止
         return;
     }
 //将差值转换为对应的是多少个小时  多少分  多少秒
 var h = Math.floor(cha / 1000 / 60 / 60);
 console.log(h);
 //计算分钟
 cha = cha - h * 60 * 60 * 1000;
 var m = Math.floor(cha / 1000 / 60);
 console.log(m);
 //计算秒
 cha = cha - m * 60 * 1000;
 var s = Math.floor(cha / 1000);
 console.log(s);
 //设置小时 分钟 秒
 hour.innerHTML = fillZero1(h);
 minute.innerHTML =  fillZero1(m);
 second.innerHTML =  fillZero1(s);
 }
 //页面进入调用函数
 setTime1();
 //定时器 
 var run =setInterval(function(){
     //是否还在调用
     // console.log('是否在调用???');
     if(cha<=0){
         //停止定时器 
         clearInterval(run);
         //终止程序 
         return;
     }
     setTime1();
 }, 1000)

八.JavaScript字符串

8.1)字符串定义方式以及转义字符:

1.使用单引号定义
2.使用双引号定义
3.使用实例化构造函数定义字符串对象
4.使用反引号定义字符串 允许换行

如何在字符串中输出变量
所有字符串都不能直接解析变量 只能采用拼接变量的形式
在反引号定义的字符串中允许使用 ${} 形式输出变量 使用反斜线\输出特殊符号
特殊转义字符:
\n 换行
\t 制表
\b 退格
\r 回车
\f 进纸
\ 反斜线
` 转义反引号`
" 转义双引号"
\xnn 以十六进制码nn表示一个字符(其中n为0-F)
\unnnn 以十六进制码nnnn表示的一个Unicode(其中n为0-F)

//使用\xnn表示特殊的字符
    var str = '\xaF';                   //ASCII A65 a97
    console.log(str);

    //使用\unnnn4位十六进制表示Unicode字符
    var str = '\u1234';

    //中文在Unicode字符中的表示范围:
    var str = '\u4000';  //中文的起始位置
    var str = '\u9fa5';   //中文的结束位置
    console.log(str);

    //定义字符串
    var str = 'abcdefg中国';

    //定义反转字符串的函数 strRev
    function strRev(str){
        //定义空字符串
        var newStr = '';

        //将原先在末尾的字符串放到前面
       for( var i = str.length - 1; i>0; i--){
        // console.log(str[i]); 
        newStr += str[i];
       } 
       //输出字符串
       //console.log(newStr);
       return newStr;
    }

    //调用函数
    var newStr = strRev(str);
    console.log(newStr);

    //调用特定的函数反转字符串
    var str = 'a@b@c';

    //split() 使用特定的符号分割字符串返回一个数组
    var newArr = str.split('@');
    var newArr = str.split('');
    var newAnthorArr = newArr.reverse(); 
    var newStr = newAnthorArr.join('');
    console.log(newStr);

    //定义字符串
    var str = 'abcdef';
    var newStr = str.split('').reverse().join('');
    console.log(newStr);

计算机只识别二进制 字符如何使用二进制进行表示

计算机电子协会约定 如何表示字符   --ASCII  256个
每一个国家都有自己的符号    中国--GBK  GB2312
当符号不能被识别时就会乱码
W3C组织约定万国码 Unicode字符

8.2)字符串常用方式:

1.查找indexOf() 正序查找 存在返回索引 不存在返回-1
var str = '齐天大圣孙悟空';
var newRes = str.indexOf('孙');
console.log(newRes); 
2.lastIndexOf() 倒序查找 存在返回索引 不存在返回-1
var newRes = str.lastIndexOf('孙');
console.log(newRes);
3.charAt() 输出指定索引位置的字符
var newStr = str[0];
var newStr = str.charAt(0);
console.log(newStr);
4.charCodeAt() 返回指定索引位置的字符的unicode编码的值
var str = '我是中国人';
var value = str.charCodeAt(0);
console.log(value); //6211
//输出16进制的Unicode字符
console.log('\u6211');
5.字符串截取 slice()
var str = 'abcdef';
var newStr = str.slice(1);  //表示从1开始截取
var newStr = str.slice(1, 3);  //表示从1开始截取  到索引结束 要前不要后
var newStr = str.slice(-2);     //从倒数第二个开始截取 取到末尾
var newStr = str.slice(-2, -1);     
console.log(str);  //原字符串不变 
console.log(newStr);//截取新字符串
6.substr() 截取字符串 不影响原字符串
var str = '黄瓜茄子香蕉苹果';
var newStr = str.substr(1);   //从索引1开始
var newStr = str.substr(4, 1);    //从索引1开始  取出1个
var newStr = str.substr(-3, 2);    //从倒数第三个开始取值 取出2个
console.log(newStr);
console.log(str);
7.substring() 获取指定的索引之间的字符
var newStr = str.substring(4, 2);
console.log(newStr);
8.split() 使用指定的字符分割字符串 返回一个数组
9.trim() 去除首尾的空白字符
var str = '   zhangsan\r\n';
var newStr = str.trim();
console.log(newStr.length);
10.字符串转为大小写 toUpperCase()
var str = 'This is a test!';
console.log(str.toUpperCase());
11.字符串全部转为小写 toLowerCase()
console.log(str.toLowerCase());
12.match() 字符串中进行查找匹配的一个方法
var str = 'this is a test!'; 
var res = str.match('t');     //查找t是否存在 如果存在返回包含结果的数组 不存在返回null
console.log(res);
13.replace() 替换
var str = '赵日天迷药';
//var newSte = str.replace('日', '*');
var newStr = str.replace('迷药', '**');
console.log(newStr); 

8.3)测测你是王者荣耀的谁???

viewport 视图窗口
width = device-width 设置页面的宽度为设备的宽度
initial-scale 页面初始化的缩放比例
maximum-scale 页面允许的最大缩放比例
minimum-scale 页面允许的最小缩放比例
user-scalable 页面是否允许缩放
no/0 表示禁止用于缩放
yes/1 表示允许用户缩放

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <!-- 
        viewport 视图窗口
            width = device-width 设置页面的宽度为设备的宽度
            initial-scale 页面初始化的缩放比例
            maximum-scale 页面允许的最大缩放比例
            minimum-scale 页面允许的最小缩放比例
            user-scalable 页面是否允许缩放
                no/0 表示禁止用于缩放
                yes/1 表示允许用户缩放
     -->
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>看看你是王者荣耀的谁</title>
    <style>
        *{
            margin: 0px;
            padding: 0px;
        }
        #title{
            text-align: center;
            margin-top: 30px;
            color: rgb(21, 252, 0);
        }
        #show{
            border: 1px solid rgb(0, 255, 255);
        }
        #username{
            width: 80%;
            height: 30px;
            display: block;
            margin: 0px auto;
            margin-top: 20px;
            font-size: 20px;
        }
        #btn{
            width: 40%;
            height: 30px;
            font-size: 15px;
            display: block;
            margin: 0px auto;
            margin-top: 10px;
            border-radius: 10px;
        }
        #hero{
            display: none;
        }
        #heroName{
            margin-top: 20px;
            margin-left: 30px;
            font-size: 18px;
        }
        #heroName span{
            color: red;
            font-size: 22px;
        }
        #heroimg{
            width: 90%;
            display: block;
            margin: 0 auto;
        }
        #oneMore{
            width: 30%;
            height: 25px; 
            display: block;
            margin: 0px auto;
            margin-top: 10px;
            border-radius: 5px; 
            color: rgb(168, 9, 44);
        }
    </style>
</head>
<body>
    <!-- 
        测一测 算一算案例
            界面: 
                提供一个供用户输入名字的位置
                功能:
                    根据用户输入的名字 结合一定的算法 得出结果
                    用户输入相同的名字 得出的结果必须保持一致
     -->
     <!-- 
         移动端的页面
            视图viewport
            默认情况下 当一个PC端的页面在移动端打开时 会自动进行缩放
                PC端 默认视口宽度为980px 移动端iphone 6 实际宽度为375px
                浏览器为了保证将页面的数据都进行显示 --页面缩小

        为了解决上述的问题 设置视图窗口 设置页面的宽度 高度根据设备实际的宽度 高度
      --> 
      <h3 id="title">测一测,你是王者荣耀里面的哪位英雄.</h3>

      <!-- 定义容器 -->
      <!-- 定义初始化的页面 -->
      <div id="show">
        <div id="init">
             <!-- 提供一个输入名字的位置 -->
          <input type="text" id="username">
          <button id="btn">开启命运之旅</button> 
        </div>
          
          <!-- 显示英雄的样式 -->
          <div id="hero">
               <h3 id="heroName">吾之姓名:  <span>凯皇</span> </h3>
          <img id="heroimg" src="./img2/k.jpg" alt="">
          <button id="oneMore">再次鉴定</button>
          </div>
         
      </div>
</body>
<script>   
    //获取元素
    var username = document.getElementById('username');
    var btn = document.getElementById('btn');
    var show = document.getElementById('show');
    var oneMore = document.getElementById('oneMore');
    var hero = document.getElementById('hero');
    var init = document.getElementById('init');

    // console.log(username, btn)

    //定义获取m,n之间的随机整数的函数
    function rand (m, n){
        return Math.floor(Mach.random() * (n-m+1)) + m;
    }

    //准备一个包含所有结果的数组
    var heros = [
            //包含多个英雄 名字 图片
            {
                heroName: '凯皇',
                heroimg: './img2/k.jpg'
            },
            {
                heroName: '百里守约',
                heroimg: './img2/blsy.jpg'
            },
            {
                heroName: '白起',
                heroimg: './img2/bq.jpg'
            },
            {
                heroName: '狄仁杰',
                heroimg: './img2/drj.jpg'
            },
            {
                heroName: '李白',
                heroimg: './img2/lb.jpg'
            },
            {
                heroName: '芈月',
                heroimg: './img2/my.jpg'
            }, 
            {
                heroName: '诸葛亮',
                heroimg: './img2/zgl.jpg'
            },
            {
                heroName: '钟无艳',
                heroimg: './img2/zwy.jpg'
            },
            {
                heroName: '马可波罗',
                heroimg: './img2/mkbl.jpg'
            },
        ];
        //英雄的数量 
        console.log(heros.length);
    //设置btn的单击事件
    btn.onclick = function(){
        // console.log('别瞎点');

        //获取用户输入的名字 -- input输入框的value值就是用户输入的数据
        console.log(username.value); 
        //去除用户的首尾空白字符
        var uname = username.value.trim();
        //判断用户输入的数据是否为空 如果为空提醒用户输入
        if(uname==''){
            alert(' 请输入您的名字');

            //终止程序 不在向下执行
            return;
        }

        //如何根据名称显示结果  
        //获取用户输入的名字对应的Unicode值 将所有的Unicode值加起来
        var num = 0;
        for (var i = 0; i<uname.length; i++){
            num += uname.charCodeAt(i);
        }
        console.log(num);

        //将输出获取的num值 对英雄数组的长度进行求余 对应的结果相当于索引

        //任意取出一个
        // console.log(heros[0].heroName);
        //定义索引index 标记是那个英雄  index变化引起英雄变化
        // var index = rand(0, heros.length - 1);  //随机数虽然可以实现类似的效果 但是非常不完美
        var index = num % heros.length;    //对英雄数组长度求余

        //  结果又是什么样子
        /*
        show.innerHTML = `
        <h3 id="heroName">吾之姓名:  <span>${heros[index].heroName}</span> </h3>
          <img id="heroimg" src="${heros[index].heroimg}" alt="">
          <button id="oneMore">再次鉴定</button>`;
          */
          //设置hero显示
        hero.style.display = 'block';
        //设置HTML元素的内容
        heroName.innerHTML = '吾之姓名: <span>' + heros[index].heroName + '</span>';
        heroimg.src = heros[index].heroimg;

        //初始化的页面隐藏
        init.style.display = 'none';  
    }
     
    //设置再来一次的单击事件
    oneMore.onclick = function(){
        // console.log(111); 
        //让初始化页面显示 
        init.style.display = 'block';

        //让显示结果隐藏
        hero.style.display = 'none';

        //设置初始化时用户输入的数组为空
        username.value = '';
    } 
</script>
</html>

九.正则表达式

正则表达式对象 --JS的内置对象
正则表达式的组成:
正则表达式定义在//中
由原子 元字符 模式修正符组成
原子 表示你想要匹配的字符
元字符 用于描述位置 数量等信息
模式修正符 区分大小写 是否全局匹配等

  1. 使用new RegExp() 构造函数实例化获取对象
    text() 正则表达式的方法 用于执行一次正则表达式的匹配 存在返回true 否则返回false
//1. 使用new RegExp() 构造函数实例化获取对象 
var reg = new RegExp('ab');    //查找匹配字符ab 
console.log(reg);
//定义字符串
var str = 'this is a test!';
//执行正则表达式的匹配
//text() 正则表达式的方法 用于执行一次正则表达式的匹配 存在返回true 否则返回false
var res = reg.test(str);
console.log(res);

*/
var res = reg.exec(str);
console.log(res);
  1. 使用字面量//形式快速定义正则表达式
//2. 使用字面量//形式快速定义正则表达式
var reg = /a/;
console.log(reg);
//exec() 执行 对结果进行输出 存在就返回 否则返回null
/*
    返回的结果中:
0: "a"                                                             匹配的结果
groups: undefined                                   
index: 8                                                        结果字符串所在的索引位置
input: "this is a test!"                            输入的字符串
length: 1                                                      匹配结果的数量
__proto__: Array(0)​

元字符 修饰 描述原子的位置 数量等信息
匹配字符串 --aa 更多的a数量: 指定个数3个 至少3个 最多3个
{}描述原子的数量
{m} 描述原子恰好出现m次
{m,} 描述其前原子至少出现m次
{m,n} 描述其前原子至少出{}描述原子的数量
{m} 描述原子恰好出现m次
{m,} 描述其前原子至少出现m次
{m,n} 描述其前原子至少出现m次 最多n次

//定义字符串
var str = 'this is a 9 test!';
//1. 使用普通字符充当原子: A-Z a-z 0-9
//匹配字符串中是否包含数字  --0-9之间的数字任意出现一个就满足条件
var reg = /0/;            //单一的匹配字符0
console.log(reg);

匹配0-9之间的任意一个数字 - [] 元字符 原子列表: 匹配列表中的任意一个字符

var reg = /[0123456789]/;
var reg = /[0-9]/;    //等效于0123456789    
var res = reg.exec(str);
console.log(res);

匹配任意一个英文字母 数字

var reg = /[a-zA-Z0-9]/;
var res = reg.exec(str);
console.log(res);

2.使用特殊的转义字符充当原子

//[0-9] === \d 匹配0-09之间的任意一个数字
var reg = /\d/;
var res = reg.exec(str);
console.log(res);
// \D匹配除了0-9之间的数字之外的任意一个字符
var reg = /\D/;
//  ^ 抑扬符
var reg = /[^0-9]/;   //抑扬符 ^ 出现在原子列表[]头部 表示排除
var res = reg.exec(str);
console.log(res);
//匹配数字 字母 下划线 /[a-zA-Z0-9_]/  === \w
var reg =  /[a-zA-Z0-9_]/;
//w匹配数字 字母 下划线其中任意一个字符
var reg = /\w/;
var res = reg.exec(str);
console.log(res);
//匹配除了数字 字母 下划线以外任意的一个字符 \W
var reg = /\W/;        //等效于/[^a-zA-Z0-9_]/
var res = reg.exec(str);
console.log(res);
//匹配任意一个空白符\s= 回车符\r 换行符\n 制表符\t等
var str = '现在这个位置要\r\n\t换行';
var reg = /\s/;
var res = reg.exec(str);
console.log(res);
// \s匹配除了空白符以外的任意一个字符
var reg = /\s/;
var res = reg.exec(str);
console.log(res);
//匹配一个字符
var str = 'this is a . point';
//  . 元字符  匹配除了换行符以外的任意一个字符
var reg = /\./;
var res = reg.exec(str);
console.log(res);

{}描述原子的数量

/*
{}描述原子的数量
     {m}  描述原子恰好出现m次
     {m,}  描述其前原子至少出现m次
     {m,n}  描述其前原子至少出现m次 最多n次
*/
var reg = /a{2}/         //  /aa/
var reg = /a{2,}/        //至少出现两个a
var reg = /a{2,3}/;    //至少2个 最多3个
console.log(reg);
//定义字符串
var str = 'this is aaaaa test!';
//执行匹配
var res = reg.exec(str);
console.log(res);
//[] 原子列表: 匹配列表中的任一个字符
//[^] 非/排除, 除了原子列表以外的任意一个字符
var reg = /[abc]/;
var reg = /[^abc]/;
var str = 'bbcd';
var res = reg.exec(str);
console.log(res);
// ^ 字符串的起始位置
// $字符串的结束位置
var reg = /^a/;      //表示a必须是字符串的开始位置
var reg = /a$/;      //表示a必须是字符串的结束位置
var str = 'this is a test!a';
var res = reg.exec(str);
console.log(reg);
//账号注册: 由数字 字母 下划线组成 首字符不允许是数字 长度6-18位
var username = 'abcdef@';
//定义符合条件的正则表达式
var reg = /^[a-zA-z_][a-zA-Z0-9_]{5,17}$/;
//验证 
var res = reg.exec(username);
console.log(res);
//判断
if (reg.test(username)){
    console.log('用户格式合法');
}else{
    console.log('用户格式不合法');
}
//注意换行符的存在 默认情况下不影响
var str = 'bcdefg\nabc';
var reg = /^a/;
var res = reg.exec(str);
console.log(res);
//   .  特殊的元字符  匹配任意一个除了换行符以外的一个字符
var reg = /./;
var str = 'this is aw test!';
var res = reg.exec(str);
console.log(res);
//a后跟任意一个字符 /a./
var reg = /a./;
var res = reg.exec(str);
console.log(res)
//描述数量 * + ?
//*描述其前原子出现0次 1次或者多次
var reg = /a*/;    //匹配a出现0次 1次或者多次
var str = 'aaaathis is ab  aaaaaaa test!';
var res = reg.exec(str);
console.log(res);
var reg = /ab*/;
var reg = /a.*b/;  // .匹配除了换行符以外的任意一个字符    * 描述原子出现n次 
var str = 'this is abbbbbbbbbbbbbbbb test';
var res = reg.exec(str);
console.log(res);
// + 描述其前原子出现1次或者多次
 var str = 'this is ab test!';
 var reg = /ab+/;      //b至少要出现1次 ab abb abbbb abbbbb
 var reg = /a.+b/;     //a和b 之间至少要有一个字符 具有贪婪模式
 var res = reg.exec(str);
 console.log(res);
//描述其前原子出现0次或者1次
var reg = /ab?/; 
var reg = /a.?/;
var res = reg.exec(str);
console.log(res);
//() 模式单元 会看做是一个整体 将匹配的数据返回到结果数组中
//定义图片的字符串 获取图片的地址
var str = '<img height="500px" title="百度LOG" src="http://www.baidu.com/logp.png" alt" widt
//定义一个正则表达式 匹配该字符串
var reg = /<img.*src="(.*)".*>/;
/*
 贪婪模式:
     .+ 或者是.* 获取最多的符合条件的数据吧
 拒绝贪婪模式
     .+?或者.*?
*/
//执行匹配 
var res = reg.exec(str);
console.log(res);
console.log('图片的地址是: ' + res[1]);
//() 模式单元  ,.默认匹配结果进行存储 同时能够使用特定的方式进行调用
var str = '2019/10-20';
//在正则表达式中使用\1 \2 .. 指代第一个 第二个小括号内对应的内容
var reg = /\d{4}(.)\d{2}\1\d{2}/;
var res = reg.exec(str);
console.log(res);
//想使用模式单元 但是不想存储的结果 (?:) 表示当前的模式单元不进行存储
var reg = /\d{4}(?:.)\d{2}.\d{2}/;
var res = reg.exec(str);
console.log(res);
// | 或者的关系
var reg = /a|b|c/;
var str = 'thibs is a test';
var res = reg.exec(str);
console.log(res);
/*
 \b \B 描述字符出现的位置是否是单词的边界
     \b 表示是单词的边界 \B表示不是
*/
var str = 'this ias a island ddfeefd';
//英文中使用空隔来分割单词
//字母i是单词的左边界 同时d是单词的右边界
var reg = /\bid\b/;
var res = reg.exec(str);
console.log(res);

模式修正:
g 表示全局匹配
i 表示忽略大小写
m 表示将包含\n换行符在内的字符,视为多行

//g 全局匹配
// var reg = new RegExp('is', 'g');
var reg = /is/g;
console.log(reg);
//定义字符串
var str = 'this is a island';
//exec() 方法执行一次正则匹配
var res = reg.exec(str);
console.log(res);
//全局匹配 此次执行exec()匹配时 开始位置是上一次匹配结束的位置
var res = reg.exec(str);
console.log(res);
//如何获取全局中符合条件的所有的结果呢?
var str = `
<ul>
    <il>
        <img src="./img/i.jpg" alt="">
    </li>
    <il>
        <img src="./img/i.jpg" alt="">
    </li>
    <il>
        <img src="./img/i.jpg" alt="">
    </li>
    <il>
        <img src="./img/i.jpg" alt="">
    </li>
    <il>
        <img src="./img/i.jpg" alt="">
    </li>
    <il>
        <img src="./img/i.jpg" alt="">
    </li>
</ul>
`;
//获取str中所有图片的Url地址
var imgReg = /<img.*?src="(.*?)".*?>/g;
//exec()获取结果时 有结果返回一个包含结果的对象 没结果返回null
//执行一次匹配
// var res = imgReg.exec(str);
// console.log(res);
//定义存储图片地址的数组
var imgUrls = [];
while(res = imgReg.exec(str)){
    console.log(res[1]);
    //将地址亚茹到imgUrls
    imgUrls.push(res[1]);
}
//打印数组
console.log(imgUrls);
//i忽略大小写
var str = 'this is a isLAnd';
var reg = /a/i; //等效于 [aA]
var res = reg.exec(str);
console.log(res);
//m 允许将字符串视为多行
var str = '@ is start\nb is start';
var reg = /^[a-z]/im;
var res = reg.exec(str);
console.log(res);
//注: 模式修正符允许组和使用
//字符串中应用正则表达式的方法
//match() 根据正则表达式返回匹配的结果
var str = '现在我这里很多的水果,香蕉,苹果,李子,葡萄,西瓜等等';
//定义正则
var reg = /香蕉|葡萄/g;
//匹配
var res = str.match(reg);
console.log(res);
//search()搜索 根据条件查询 存在结果返回对应的索引 不存在返回-1
var res = str.search(/香a蕉/);
console.log(res);
//split() 根据条件进行分割
var str = 'HTML@MySQL#CSS*javaScript';
var res = str.split(/@|#|\*/);
console.log(res);
//replace() 替换 如何替换敏感词
var str = '菜逼, 垃圾, 枪支弹药, 我想打炮, 不要逼我, 强奸犯,真特么菜逼';
//将敏感词替换成*
//定义一个包含所有敏感词的数组
var dangerWords = ['强奸','菜逼','逼','垃圾','枪支', '弹药','特么','打炮'];
//遍历所有的敏感词汇 进行替换
dangerWords.forEach(function(dw){
    var reg = new RegExp(dw,'g');
    //console.log(reg);
    //替换
    //repeat() 重复指定的字符
    str = str.replace(reg,'*'.repeat(dw.length))
})
console.log(str);
/*
var dangerWords = /菜逼|垃圾|枪支|弹药|真特么/g;
var newStr = str.replace(dangerWords,'**');
console.log(newStr);
*/

匹配邮箱
QQ邮箱123456@qq.com
163邮箱: jinchweng@163.com
谷歌邮箱: jincheng@Gmail.com

//尝试写一个定义邮箱的正则
var emailReg = /^[a-z1-9-_]+?@[0-9a-z-]+?\.[a-z]+?$/i;
//定义邮箱
var email = 'jingcheng@Gmail.com';
var email = '发货哦啊好.com' //不满足条件
//验证
var res = emailReg.test(email);
console.log(res);
//验证中文 每一个中文都可以使用unicode字符表示
//中文Unicode取值范围:   \u4E00-\u9FA5
var str = 'this is you 中文dwahuo隧道杜绝暗送';
var reg = /[\u4E00-\u9FA5]+/g;
//中文的长度
var num = 0; 
while (res = reg.exec(str)){ 
console.log(res);
// console.log(res[0].length);
num += res[0].length;
};
console.log('字符串中中文的长度为' + num);
/*读正则表达式
    1.如果能够没有就不给
    2.先整体在局部
    ((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/;
    匹配的结果:
        200.200.200.250
        0.0.0.0
*/
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345