javascript (1) -基础操作

251 阅读18分钟

1. 案例入门

想象一下,你填完一个注册表单,点击提交按钮,然后等待30秒,最终服务器返回消息说有一个必填字段没有填写...

概念: JavaScript诞生于1995年,是甲骨文公司的注册商标,当时它的主要目的就是处理以前由服务器语言负责的一些输入验证,在当时,绝大多数的网民都使用速度仅为28.8Kb/s的调制解调(猫)上网,而网页的大小和复杂性却不断增加,能够在客户端完成一些基本的验证任务,绝对是令人兴奋的,到如今,JS的用途已经不再局限于简单的数据验证,而是具备了与浏览器及其内容等几乎所有方面的交互能力,JS已经成为了一门功能全面的编程语言,成为了Web的一个重要的组成部分:

  • 历史:European Computer Manufactures Association,欧洲计算机制造联合会是1961年成立的组织,旨在建立统一的电脑操作格式标准,组织的目标是评估,开发和认可电信以及计算机标准:
    • 在1995年时,由NetScape公司的 Brendan Eich 在网景导航者浏览器上首次设计实现而成。
    • JS原名 LiveScript,但因NetScape与Sun合作,且当时Java语言很火,于是临更名为JavaScript。
    • ECMA创建了ECMA-262标准,即ECMAScript,并收纳了JS和微软推出的JScript,两者都是ECMAScript的实现。
  • 特点:JS可以直接嵌入HTML页面,但写成单独的JS文件有利于结构和行为的分离:
    • 脚本语言:JS是一种解释型的脚本语言,在程序的运行过程中逐行进行解释,不需要编译。
    • 基于对象:JS是一种基于对象的脚本语言,它不仅可以创建对象,也能使用现有的对象。
    • 弱类型:JS是一种弱类型的脚本语言,拥有数据类型但不需要强调。
    • 动态性:JS是一种采用事件驱动的脚本语言,可以直接对用户的操作做出实时的响应。
    • 跨平台性:JS不依赖于操作系统,仅需要浏览器的支持,且兼容性好。
  • 结构:一个完整的JS实现由三部分组成:
    • ECMA:JS的核心部分,负责将代码解释给浏览器,几乎兼容所有现代浏览器。
    • DOM:Document Object Model,文档对象模型,赋予了JS操作DOM树节点的能力,例如得到元素,删除元素等操作都属于DOM操作,部分兼容所有现代浏览器,关键字:document
    • BOM:Browser Object Model,浏览器对象模型,赋予了JS操作浏览器的能力,例如弹窗关窗,复制剪切板等操作都属于BOM操作,完全不兼容所有现代浏览器,关键字:window, 一般情况下可以省略。

2. 案例-HelloWorld

需求: 编一个JS版的HelloWorld程序,要求在HTML中使用 <script></script> 开辟一块专门编写JS代码的区域,位置随意,建议写在 <body> 中的最后位置:

  • 注释:JS中建议使用 /* */ 的格式来使用注释。
  • 加载函数:加载函数中的代码会在页面全部元素(DOM、图片、视频等)加载完毕后再执行:
    • ES5写法:window.onload = function(){};window 关键字可以省略。
    • ES6写法:window.onload = () => {};window 关键字可以省略。
    • 如果存在多个加载函数,则后面的加载函数会覆盖之前的加载函数。
  • 输出语句:console.log() 是JS中的输出语句:
    • 输出的内容可以在浏览器端右键检查,选择 console 选项卡来查看。
    • 输出 window.navigator.userAgent 可以查看当前浏览器的版本信息。
  • 建议将JS代码单独写在一个外部.js文件中,然后在HTML中使用 <script> 中的 src 属性进行引入,达到内容和行为的分离解耦。

如果你的IDE不支持ECMAScript6的箭头函数,可以尝试 File - Settings - Languages & Frameworks - JavaScript,然后将 JavaScript language version 选项调整成 ECMAScript6

布局:

<script type="text/javascript">
    /*JS使用多行注释的格式*/
    window.onload = () => {
        console.log(window.navigator.userAgent + ":hello-001!!");
    };
    onload = () => {
        console.log(navigator.userAgent + ":hello-002!!");
    };
    window.onload = function () {
        console.log(navigator.userAgent + ":hello-003!!");
    };
    onload = function () {
        console.log(navigator.userAgent + ":hello-004!!");
    }
</script>
<script type="text/javascript" src="../script/external-test.js"></script>

脚本

window.onload = () => {
    console.log(navigator.userAgent + ":hello-005!!");
};

3. 案例-BOM新建窗口

概念:

  • window.open(url, target):开启一个新的窗口并返回:
    • param1:开启的新的窗口的url地址,开启空白页面使用 about:blank
    • param2:新窗口的开启方式,如 _blank_top 等。
  • document.querySelector(selector):从DOM树中抓取节点元素并返回,如果抓取失败,返回 null
    • param:CSS3风格的选择器,字符串格式。
  • 元素.onclick = () => {};:为元素挂载点击事件,值是一个函数。
  • document.write():在页面上生成HTML代码
    • param:在页面端生成的HTML代码内容,当然也可以是纯文本。

需求: 通过点击一个按钮,开启一个新的空白窗口,并且在新窗口的页面中写上 "abc"。

布局:

<button id="openWindow" type="button">开窗</button>
<script type="text/javascript" src="../script/开窗按钮写法-test.js"></script>

脚本

window.onload = () =>{
  let kaichuang =  document.querySelector(`#openWindow`)
    kaichuang.onclick = () =>{
     let newWindow =  open("about:blank",`_blank`)
        newWindow.document.write(`abc`)
    }
};

4. 案例-BOM关闭窗口

概念: window.close():关闭当前窗口:

  • 若关闭的是浏览器剩下的最后一个窗口,则浏览器也会退出。
  • 在子窗口中关闭父窗口,需要使用 window.top.close()

若火狐浏览器提示 脚本不得关闭非脚本打开的窗口,则需要调整其配置:在地址栏输入 about:config 找到 dom.allow_scripts_to_close_windows 并改为 true

布局:

<button id="closeWindow" type="button">关闭窗口</button>
<button id="closeDad" type="button" >关闭父窗口</button>
<script src="../script/关闭按钮写法-test.js" type="text/javascript"></script>

脚本

onload = ()=>{
 let closeWindowBtn = document.querySelector("#closeWindow")
   closeWindowBtn.onclick = () => close();
}

onload = () => {
    let closeDadBtn = document.querySelector("#closeDad")
    closeDadBtn.onclick = () => top.close();

}

5. 案例-BOM跳转窗口

概念: window.location.href = url:用于跳转窗口,效果类似于 <a>

  • href 可以省略,但是兼容性会略低于 location.href 的写法。

布局:

<button type="button" id="one" > 点我跳转</button>
<script src="../script/跳转页面写法-test.js" type="text/javascript"></script>

脚本

onload = () => {
    let one = document.querySelector("#one")
    one.onclick = () => {
        location.href = "https://www.baidu.com/"
    };
}

6. 案例-BOM页内弹窗

这次我们使用HTML内嵌 onclick 的方式来做,只是体验一下,实际开发中,不建议这样使用,HTML和JS的耦合度越低越好。

概念:

  • window.alert(content):普通弹窗:
    • param1:弹窗的提示字符串。
  • window.confrim(content):带取消按钮的弹窗:
    • param1:弹窗的提示字符串。
    • return:当用户点击确定,返回 true,点击取消,返回 false
  • window.prompt(content, default):带输入框的弹窗:
    • param1:弹窗的提示字符串。

    • param2:弹窗中输入框的默认值。

    • return:当用户点击确定,返回用户在输入框中输入的值,点击取消,返回空串。

布局:

<button type="button" onclick="myAlert();">alert</button>
<button type="button" onclick="myConfirm();">confirm</button>
<button type="button" onclick="myPrompt();">prompt</button>
<script src="../script/弹窗案例-test.js" type="text/javascript"></script>

脚本

function myAlert() {
        alert("你好");
    }
    function myConfirm() {
        let result = confirm("你好");
        console.log(result);
    }
    function myPrompt() {
        let result = prompt("请输入阅读密码", "123");
        console.log(result);
    }

7. 案例-DOM鼠标经过

概念:

  • JS中可以使用 元素.属性 或者 元素["属性"] 的格式来获取某个元素对应的属性值,更建议的写法是第二种。

  • 元素.onmouseover = () => {}:为元素挂载鼠标经过事件,值是一个匿名函数。

  • 元素.onmouseout = () => {}:为元素挂载鼠标移除事件,值是一个匿名函数。

布局:

    <style type="text/css">#remember-pwd-msg {display: none;} </style>
<section>
    <label>
        <span>账号:</span>
        <input type="text"/>
    </label>
    <label>
        <span>密码:</span>
        <input type="password"/>
    </label>
    <label>
        <input id="remember-pwd-cbx" type="checkbox"/>
        <span>记住密码</span>
    </label>
    <span id="remember-pwd-msg">请不要在公共场合勾选此项!</span>
</section>

脚本

    /*需求:当鼠标经过 [记住密码] 的多选框时,提示"请不要再公共场合勾选此项!",
    当鼠标移出 [记住密码] 的多选框时,提示取消。*/
    onload = () => {
        let rememberPwdCbx = document.querySelector("#remember-pwd-cbx");
        let rememberPwdMsg = document.querySelector("#remember-pwd-msg");
        rememberPwdCbx.onmouseover = () => {
            rememberPwdMsg["style"]["display"] = "inline";
        };
        rememberPwdCbx.onmouseout = () => {
            rememberPwdMsg["style"]["display"] = "none";
        }
    };
</script>

8. 案例-DOM鼠标高亮

概念: querySelectorAll(selector):根据CSS选择器获取多个DOM节点元素的集合。

布局:

<section>
    <ul id="item-list">
        <li>在我心上用力的开一枪</li>
        <li>让一切归零在这声巨响</li>
        <li>如果爱是说什么都不能忘</li>
        <li>我不挣扎</li>
        <li>也许我也没差</li>
        <li>在我心上用力的开一枪</li>
        <li>让一切归零在这声巨响</li>
        <li>如果爱是说什么都不能忘</li>
        <li>我不挣扎</li>
        <li>也许我也没差</li>
    </ul>

脚本

<script type="text/javascript">
    /*需求:当鼠标经过某一行内容的时候,文本可以高亮显示,当鼠标开某一行内容的时候,高亮取消。*/
    onload = () => {
        let itemList = document.querySelector("#item-list");
        let lis = itemList.querySelectorAll("li");

        for (let i = 0, j = lis.length; i < j; i++) {
            lis[i].onmouseover = () => {
                lis[i]["style"]["backgroundColor"] = "red";
            };

            lis[i].onmouseout = () => {
                lis[i]["style"]["backgroundColor"] = "";
            };
        }
    };
</script>

9. 案例-DOM全选反选

概念: JS代码中将多选按钮的 checked 属性改为 true 则可以动态将其选中。

布局:

<section>
    <label><input id="all-check-cbx" type="checkbox"/> 全选</label>
    <label><input id="re-check-cbx" type="checkbox"/> 反选</label>
    <hr/>
    <label><input name="users" type="checkbox"/> 赵四</label>
    <label><input name="users" type="checkbox"/> 刘能</label>
    <label><input name="users" type="checkbox"/> 广坤</label>
    <label><input name="users" type="checkbox"/> 大脚</label>
    <label><input name="users" type="checkbox"/> 飞机</label>
</section>

脚本

<script type="text/javascript">
    /*需求:
    点击全选多选框,可以将所有内容选中,再次点击可以取消全选。
    点击反选多选框,可以将所有内容反选,再次点击再次反选。
    */
    onload = () => {
        let users = document.querySelectorAll("input[name='users']");
        let allCheckCbx = document.querySelector("#all-check-cbx");
        let reCheckCbx = document.querySelector("#re-check-cbx");

        allCheckCbx.onclick = () => {
            for (let i = 0, j = users.length; i < j; i++) {
                users[i]["checked"] = allCheckCbx["checked"];}};
                
        reCheckCbx.onclick = () => {
            for (let i = 0, j = users.length; i < j; i++) {
                users[i]["checked"] = !users[i]["checked"]; }}};
</script>

10. 案例-DOM批量删除

概念: return关键字可以直接结束其所在的函数,阻止继续向下运行。

布局:

<section>
    <button id="delete-btn" type="button">批量删除</button>
    <hr/>
    <label><input name="user" type="checkbox"/> 赵四</label>
    <label><input name="user" type="checkbox"/> 刘能</label>
    <label><input name="user" type="checkbox"/> 广坤</label>
    <label><input name="user" type="checkbox"/> 大脚</label>
    <label><input name="user" type="checkbox"/> 飞机</label>
</section>

脚本


<script type="text/javascript">
    /*利用多选框选择要删除的内容,点击删除按钮,可以将选择的内容删除,
    如果没有选中任何内容,则提示"至少选择一项!"*/
    onload = () => {
        let deleteBtn = document.querySelector("#delete-btn");
        deleteBtn.onclick = () => {
            let users = document.querySelectorAll("input[name=user]:checked");
            let len = users.length;
            if (len <= 0) {
                alert("您至少要选择一项!");
                return;
            }
            let result = confirm("您将要删除" + len + "个用户,确认吗?");
            if (result) {
                alert("删除成功!");}} }
</script>

11 案例-DOM空值校验

概念:

  • 元素.focus():让一个元素获取焦点。
  • 表单元素.submit():手动提交表单。
  • 表单元素.onsubmit = () => {}:当表单提交时触发的事件。
  • return false; :阻止所在事件的效果。

布局:

<section>
    <form id="login-form" method="get" action="#">
        <label>
            <span>账号:</span>
            <input id="username-ipt" type="text" name="username"/>
        </label>
        <label>
            <span>密码:</span>
            <input id="password-ipt" type="password" name="password"/>
        </label>
        <button id="login-btn" type="button">登录</button>
    </form>
</section>

<script type="text/javascript">
    /*需求:提交表单前,对表单的账号密码进行空值校验,登录按钮为提交按钮。*/
    onload = () => {
        /*抓取账号框*/
        let usernameIpt = document.querySelector("#username-ipt");

        /*让账号框自动获取焦点*/
        usernameIpt.focus();

        /*抓取登录按钮*/
        let loginBtn = document.querySelector("#login-btn");
        loginBtn.onclick = () => {

            /*账号为空直接返回,账号框重设焦点*/
            if ("" === usernameIpt["value"] || null === usernameIpt["value"]) {
                alert("账号不能为空!");
                usernameIpt.focus();
                return;
            }

            /*密码为空直接返回,密码框重设焦点*/
            let passwordIpt = document.querySelector("#password-ipt");
            if ("" === passwordIpt["value"] || null === passwordIpt["value"]) {
                alert("密码不能为空!");
                passwordIpt.focus();
                return;
            }

            /*验证通过,提交表单*/
         document.querySelector("#login-form").submit();
        }
    }
</script>

<section>
    <form id="login-form">
        <label>
            <span>账号:</span>
            <input id="username-ipt" type="text" name="username"/>
        </label>
        <label>
            <span>密码:</span>
            <input id="password-ipt" type="password" name="password"/>
        </label>
        <button type="submit">登录</button>
    </form>
</section>

<script type="text/javascript">
    /*需求:提交表单前,对表单的账号密码进行空值校验,登录按钮为提交按钮。*/
    onload = () => {
        /*抓取账号框*/
        let usernameIpt = document.querySelector("#username-ipt");

        /*让账号框自动获取焦点*/
        usernameIpt.focus();

        /*抓取登录表单*/
        let loginForm = document.querySelector("#login-form");
        loginForm["method"] = "get";
        loginForm["action"] = "#";
        loginForm.onsubmit = () => {

            /*账号为空直接返回,账号框重设焦点*/
            if ("" === usernameIpt["value"] || null === usernameIpt["value"]) {
                alert("账号不能为空!");
                usernameIpt.focus();
                return false;
            }

            /*密码为空直接返回,密码框重设焦点*/
            let passwordIpt = document.querySelector("#password-ipt");
            if ("" === passwordIpt["value"] || null === passwordIpt["value"]) {
                alert("密码不能为空!");
                passwordIpt.focus();
                return false;
            }
        }
    }
</script>

1. 常量

概念: JS中的常量包括字面常量和 const 定义的变量:

  • const 声明的常量不能被更改。
  • const 的声明和赋值必须在同一行。

布局:


<script type="text/javascript">
    /*Err:const声明中缺少初始化程序*/
    /*
    const numA;
    numA = 1;
    */

    /*Err:分配给常数.*/
    /*
    const numB = 1;
    numB = 2;
    */

    /*正确写法*/
    const numC = 1;
    console.log(numC);
</script>

2. 变量

概念: JS中的变量可以使用 varlet 来定义,建议使用 let

  • var 声明的变量具有默认值 undefined,所以声明不赋值亦可使用。
  • var 声明的变量会被预解析:
    • 声明部分被提升至所在函数(非所在代码块)首行。
    • 赋值部分保持原位置不变。
  • var 允许变量名重复,也是因为 var 会发生预解析现象。
  • let 声明的变量不会被预解析,不允许重复定义变量,作用域只属于它所在的代码块:
    • let 是ES6规范(于2015年发布,故也叫ES2015)中 var 的替代关键字。

函数的内置参数,函数内的另一个函数声明和 var 变量都会被预解析,优先级从高到低。

布局:

<button id="default-value-btn" type="button">var变量具有默认值</button>
<br/>
<button id="pre-analysis-btn" type="button">var变量会被预解析</button>
<br/>
<button id="duplicate-name-btn" type="button">var变量允许重复命名</button>
<br/>
<button id="let-btn" type="button">let变量更加严谨</button>
<br/>
 window.onload = () => {
		 //var变量具有默认值
        document.querySelector("#default-value-btn").onclick = () => {
            var money;
            console.log(money);
        };
		//var变量会被预解析
        document.querySelector("#pre-analysis-btn").onclick = () => {
            console.log(money);
            {
                var money = 100;
            }
            /*after pre analysis:*/
            /*
            var money;
            console.log(money);
            {
                money = 100;
            }
            */
        };
		//var变量允许重复命名
        document.querySelector("#duplicate-name-btn").onclick = () => {
            var money = 100;
            var money = 200;
            console.log(money);

            /*after pre analysis:*/
            /*
            var money;
            money = 100;
            money = 200;
            console.log(money);
            */
        };
		//let变量更加严谨
        document.querySelector("#let-btn").onclick = () => {
            /*Err:money is not defined*/
            console.log(money);
            {
                let money = 100;

                /*Err:Identifier 'money' has already been declared*/
                /*let money = 200;*/
            }
        };
    };

3. 数据类型

概念: JS是弱类型语言,但不代表没有类型,可以使用 typeof 函数测得:

  • 基本数据类型:同个变量可以在使用过程中分别存放不同类型的值,但不建议,以免混乱:
    • number:数字类型,包括整数和浮点数。
    • string:字符串类型,包括单个字符,HTML中通过value获取的值都是string类型。
    • boolean:布尔类型,JS中除 false0""nullundefined 外都可以视为真值。
    • function:函数类型,包括ES5中的function函数和ES6中的箭头函数。
    • object:对象类型,如抓取到的DOM节点元素。
    • undefined:未定义类型,表示变量声明但未被赋值。
  • 类型显示转换:
    • window.parseInt(num):从前向后逐字符转换成整数,遇到非数字停止。
    • window.parseFloat(num):从前向后边截取边转换成浮点数,遇到非数字停止。
    • num.toFixed(2):使num保留两位小数。
    • NaN 表示值不是一个数字,可以用 isNaN(num) 函数测得,NaN 不一定等于 NaN
  • 类型隐式转换:
    • == 会将类型都转为同一类型然后再进行比较,如不想转换,使用 === 替代。
    • 字符串相减,会先把类型都转成数字,然后再进行数学的减法计算。

布局:

<button id="data-type-btn" type="button">基本数据类型</button>
<br/>
<button id="true-false-btn" type="button">布尔真假规范</button>
<br/>
<button id="type-conversion-btn" type="button">类型显示转换</button>
<br/>
<button id="nan-btn" type="button">isNaN函数</button>
<br/>
<button id="equal-btn" type="button">全等比较</button>
<br/>
<button id="string-subtraction-btn" type="button">字符串相减</button>
<br/>

 window.onload = () => {
		//基本数据类型
        document.querySelector("#data-type-btn").onclick = () => {
            let result;
            console.log(typeof result);

            result = 1;
            console.log(typeof result);

            result = "abc";
            console.log(typeof result);

            result = true;
            console.log(typeof result);

            result = function () {
            };
            console.log(typeof result);

            result = () => {
            };
            console.log(typeof result);

            result = document.querySelector("#data-type-btn");
            console.log(typeof result);
        };
		//布尔真假规范
        document.querySelector("#true-false-btn").onclick = () => {
            let money = 0;
            let name = "";
            console.log(money ? "money true..." : "money false...");
            console.log(name ? "name true..." : "name false...");
        };
		//类型显示转换
        document.querySelector("#type-conversion-btn").onclick = () => {
            let num;

            num = "12abc34";
            console.log(window.parseInt(num));

            num = "abc34";
            console.log(window.parseFloat(num));
        };
		//isNaN函数
        document.querySelector("#nan-btn").onclick = () => {
            let num;

            num = "1234";
            console.log(isNaN(num));

            num = "1234a";
            console.log(isNaN(num));
        };
		//全等比较
        document.querySelector("#equal-btn").onclick = () => {
            let numA = 1234;
            let numB = "1234";

            console.log(numA == numB);
            console.log(numA === numB);
        };
		//字符串相减
        document.querySelector("#string-subtraction-btn").onclick = () => {
            let numA = "100";
            let numB = "1";
            console.log(numA - numB);
        };
    }

4. 函数

概念: JS的函数可以发生嵌套,组成父子函数,子函数可以使用父函数定义的变量,此效果被称为闭包:

  • ES5的function函数:function 函数名(形参列表){}
    • 返回值:若不使用 return 来指定返回值,则返回 undefined
    • 形参列表:JS的形参列表不允许写类型,包括 varlet
  • ES6的箭头函数:let 函数名 = (形参列表) => {函数体}
    • 函数无参时 () 不能省略。
    • 函数单参时:let 函数名 = (参数) => {},且 () 可以省略。
    • 函数多参时:let 函数名 = (形参列表) => {},且 () 不能省略。
    • 函数体中只有一行代码时,{} 可以省略,若该行代码中有 return,则 return 也必须省略。

布局:


<button id="closure-btn" type="button">闭包测试</button>
<br/>
<button id="es5-function-btn" type="button">ES5函数定义</button>
<br/>
<button id="es6-function-btn" type="button">ES6函数定义</button>
<br/>

		//闭包测试
 document.querySelector("#closure-btn").onclick = () => {
        let outer = "outer";

        function inner() {
            let inner = "inner";
            console.log(outer);
        }

        inner();

        console.log(inner);
    };
		
        //ES5函数定义
    document.querySelector("#es5-function-btn").onclick = () => {
        console.log(es5FunctionA());
        console.log(es5FunctionB());
        console.log(es5FunctionC(1, 2));
        console.log(es5FunctionD(3, 4));
    };
    
     /*no param, no return*/
    function es5FunctionA() {
        console.log("es5FunctionA");
    }

    /*no param*/
    function es5FunctionB() {
        console.log("es5FunctionB");
        return "es5FunctionB";
    }

    /*no return*/
    function es5FunctionC(numA, numB) {
        console.log(numA, numB);
    }

    /*complete*/
    function es5FunctionD(numA, numB) {
        return numA + numB;
    }
    
		//ES6函数定义
    document.querySelector("#es6-function-btn").onclick = () => {
        console.log(es6FunctionA());
        console.log(es6FunctionB());
        console.log(es6FunctionC("hello"));
        console.log(es6FunctionD(5, 6));
        console.log(es6FunctionE("hello"));
        console.log(es6FunctionF());
        console.log(es6FunctionG(7, 8));
    };

    /*no param, no return*/
    let es6FunctionA = () => {
        console.log("es6FunctionA");
    };

    /*no param*/
    let es6FunctionB = () => {
        console.log("es6FunctionB");
        return "es6FunctionB";
    };

    /*no return*/
    let es6FunctionC = (num) => {
        console.log(num);
    };

    /*complete*/
    let es6FunctionD = (numA, numB) => {
        return numA + numB;
    };

    /*Omit "()": when only one param*/
    let es6FunctionE = num => {
        console.log(num);
    };

    /*Omit "{}": when only one-line code in "{}"*/
    let es6FunctionF = () => console.log("es6FunctionF");

    /*Omit "return": when only one-line code in "{}" and has "return"*/
    let es6FunctionG = (numA, numB) => numA + numB;

4.1 函数关键字this

概念: this 是函数中的一个内置的关键字:

  • ES5函数中,this 指向该函数的调用者,是变化的。
  • ES6函数中,this 指向 window 对象,是不变的。

布局:


<section id="this-in-es5">
    <ul>
        <li>在我心上用力的开一枪</li>
        <li>让一切归零在这声巨响</li>
        <li>如果爱是说什么都不能放</li>
        <li>我不挣扎</li>
    </ul>
</section>

<section id="this-in-es6">
    <ul>
        <li>在我心上用力的开一枪</li>
        <li>让一切归零在这声巨响</li>
        <li>如果爱是说什么都不能放</li>
        <li>我不挣扎</li>
    </ul>
</section>
 window.onload = () => {
        let thisInEs5Sec = document.querySelector("#this-in-es5");
        let lisInEs5Sec = thisInEs5Sec.querySelectorAll("li");
        for (let i = 0, j = lisInEs5Sec.length; i < j; i++) {
            lisInEs5Sec[i].onmouseover = function () {
                console.log("es5: ", this);
                this["style"]["backgroundColor"] = "red";
            };
            lisInEs5Sec[i].onmouseout = function () {
                this["style"]["backgroundColor"] = "";
            }
        }

        let thisInEs6Sec = document.querySelector("#this-in-es6");
        let lisInEs6Sec = thisInEs6Sec.querySelectorAll("li");
        for (let i = 0, j = lisInEs6Sec.length; i < j; i++) {
            lisInEs6Sec[i].onmouseover = () => {
                console.log("es6: ", this);
                lisInEs6Sec[i]["style"]["backgroundColor"] = "red";
            };
            lisInEs6Sec[i].onmouseout = () => {
                lisInEs6Sec[i]["style"]["backgroundColor"] = "";
            }
        }
    }

4.2 函数不定长参数

概念:

  • ES5函数中,内置的参数 arguments 指向函数的参数列表数组:
    • arguments.length:获取参数个数。
    • arguments[0]:返回参数列表中的第一个参数。
  • ES6函数中,在 () 中使用 (...params) 来指向函数的参数列表数组:
    • params 表示参数列表数组的名字,可以随意更改。
    • params.length:获取参数个数。
    • params[0]:返回参数列表中的第一个参数。

布局:

<button id="es5-function-args-btn" type="button">ES5的不定长参数</button>
<br/>
<button id="es6-function-args-btn" type="button">ES6的不定长参数</button>
<br/>

  window.onload = () => {

        document.querySelector("#es5-function-args-btn").onclick = () => {
            console.log(es5add(1, 2, 3, 4, 5));
        };

        document.querySelector("#es6-function-args-btn").onclick = () => {
            console.log(es6add(1, 2, 3, 4, 5));
        };

    };

    function es5add() {
        let result = 0;
        for (let i = 0, j = arguments.length; i < j; i++) {
            result += arguments[i];
        }
        return result;
    }

    let es6add = (...params) => {
        let result = 0;
        for (let i = 0, j = params.length; i < j; i++) {
            result += params[i];
        }
        return result;
    }

4.3 参数默认值

概念: 函数的参数在设计阶段可以直接对其添加默认值:

  • 使用常量作为默认值:add(numA, numB = 3)
  • 使用变量作为默认值:add(numA, numB = a)
  • 使用表达式作为默认值:add(numA, numB = numA + 5)
  • 使用函数调用作为默认值:add(numA, numB = getValue())
  • 此特性对箭头函数同样适用。

布局:

<button id="const-btn" type="button">使用常量作为默认值</button>
<br/>
<button id="variable-btn" type="button">使用变量作为默认值</button>
<br/>
<button id="expression-btn" type="button">使用表达式作为默认值</button>
<br/>
<button id="function-btn" type="button">使用函数调用作为默认值</button>
<br/>


    window.onload = () => {
		//使用常量作为默认值
        document.querySelector("#const-btn").onclick = () => {
            constTest(1, 2);
            constTest(1);
        };
        
    function constTest(numA, numB = 3) {
        console.log(numA + numB);
    }
		//使用变量作为默认值
        document.querySelector("#variable-btn").onclick = () => {
            variableTest(1, 2);
            variableTest(1);
        };
        
    function variableTest(numA, numB = numA) {
        console.log(numA + numB);
    }
		//使用表达式作为默认值
        document.querySelector("#expression-btn").onclick = () => {
            expressionTest(1, 2);
            expressionTest(1);
        };
        
    function expressionTest(numA, numB = numA + 100) {
        console.log(numA + numB);
    }
		//使用函数调用作为默认值
        document.querySelector("#function-btn").onclick = () => {
            functionTest(1, 2);
            functionTest(1);
        };
        
    function functionTest(numA, numB = fn()) {
        console.log(numA + numB);
    }

    function fn() {
        return 100;
    }
    };

4.4 函数自执行

概念: ES5中的JS的函数支持自执行,即自己执行自己:

  1. 在函数的 {} 后添加一个 () 代表调用。
  2. () 里面添加调用时的入参。
  3. 接收函数返回值,否则自执行也会失效。

布局:

<script type="text/javascript">
    window.onload = () => {
        let result = function add(numA, numB) {
            return numA + numB;
        }(1, 2);
        console.log(result);
    }
</script>

5. 数组

概念: JS中的数组长度可变,且允许存储不同类型的元素(不建议):

  • 声明赋值:
    • let arr = new Array(值列表)
    • let arr = [值列表]
  • 遍历方式:除了for循环角标的方式外,JS还提供了两种方式可以遍历数组:
    • for(let i in arr)i 是角标。
    • arr.forEach(fn()):利用数组的API方法快捷遍历数组,没有返回值。
  • 常用方法:
    • Array.isArray(arr):判断arr是不是数组,返回布尔值。
    • arr.toString():将arr转化为字符串,元素之间自动拼接 ,
    • arr.unshift(es):头部添加元素列表es,作用于原数组,返回添加后的数组长度。
    • arr.shift():头部删除元素,作用于原数组,返回被删除的元素。
    • arr.push(es):尾部添加元素列表es,作用于原数组,返回添加后的数组长度。
    • arr.pop():尾部删除元素,作用于原数组,返回被删除的元素。
    • arr.splice(pos, len, [元素列表]):从pos位置(包括)开始,删除len个元素,并添加元素列表(可选),返回被删除的数组,如果没有删除任何元素,则返回空数组。
    • arr.concat(arrB):将arrB连接到arr后,返回结果数组,不作用于原数组。
    • arr.join(c):将arr的每一个元素用连接符c连接到一起,返回结果数组,不作用于原数组。
    • arr.sort([fn]):arr升序排序,可以指定排序规则函数(返回正数为倒序),作用于原数组。
    • arr.indexOf(e)/lastIndexOf(e):在arr中正/反方向查找e的位置,不存在返回-1。
    • arr.map(fn):将arr中的每个元素都调用一次fn函数。
    • arr.filter(fn):对arr中的每个元素进行fn函数判断,将满足条件的元素作为一个新的数组返回。
    • arr.every(fn):对arr中的每个元素进行fn函数判断,若所有元素都满足才返回 true,否则返回 false
    • arr.some(fn):对arr中的每个元素进行fn函数判断,只要有一个元素满足就返回 true,否则返回 false
    • arr.reduce(fn)/reduceRight(fn):从左到右/从右到左为arr中的每一个元素依次执行fn函数,每次都会将返回值赋值给fn函数的第一个参数,最终返回累计处理的结果。

布局:

<button id="declaration-btn" type="button">数组声明</button>
<script type="text/javascript">
 document.querySelector("#declaration-btn").onclick = () => {
            let arrA = new Array(1, 2, 3, "a", "b", "c");
            let arrB = [1, 2, 3, "a", "b", "c"];
            console.log(arrA);
            console.log(arrB);
        };
</script>

<button id="for-btn" type="button">for遍历</button>
<script type="text/javascript">
        document.querySelector("#for-btn").onclick = () => {
            let arr = [3, 2, 1, 6, 5, 4];
            for (let i = 0, j = arr.length; i < j; i++) {
                console.log(arr[i]);
            }
        };
</script>


// `i` 是角标。
<button id="for-in-btn" type="button">for-in遍历</button>
<script type="text/javascript">
        document.querySelector("#for-in-btn").onclick = () => {
            let arr = [3, 2, 1, 6, 5, 4];
            for (let i in arr) {
                console.log(arr[i]);
            }
        };
</script>


//利用数组的API方法快捷遍历数组,没有返回值。
<button id="foreach-btn" type="button">forEach()遍历</button>
<script type="text/javascript">
        document.querySelector("#foreach-btn").onclick = () => {
            let arr = [3, 2, 1, 6, 5, 4];
            arr.forEach(e => console.log(e));
        };
</script>


//判断arr是不是数组,返回布尔值
<button id="isArray-btn" type="button">isArray()函数</button>
<script type="text/javascript">
        document.querySelector("#isArray-btn").onclick = () => {
            let a = 123;
            let b = [1, 2, 3];
            console.log(Array.isArray(a));
            console.log(Array.isArray(b));
        };
</script>


//将arr转化为字符串,元素之间自动拼接 `,`。
<button id="toString-btn" type="button">toString()函数</button>
<script type="text/javascript">
        document.querySelector("#toString-btn").onclick = () => {
            let arr = [1, 2, 3];
            console.log(arr.toString());
        };
</script>


//头部添加元素列表es,作用于原数组,返回添加后的数组长度。
<button id="unshift-btn" type="button">unshift()函数</button>
<script type="text/javascript">
        document.querySelector("#unshift-btn").onclick = () => {
            let arr = [1, 2, 3];
            let result = arr.unshift(100, 111);
            console.log(arr);
            console.log(result);
        };
</script>


//头部删除元素,作用于原数组,返回被删除的元素。
<button id="shift-btn" type="button">shift()函数</button>
<script type="text/javascript">
        document.querySelector("#shift-btn").onclick = () => {
            let arr = [1, 2, 3];
            let result = arr.shift();
            console.log(arr);
            console.log(result);
        };
</script>


//尾部添加元素列表es,作用于原数组,返回添加后的数组长度。
<button id="push-btn" type="button">push()函数</button>
<script type="text/javascript">
        document.querySelector("#push-btn").onclick = () => {
            let arr = [1, 2, 3];
            let result = arr.push(100, 111);
            console.log(arr);
            console.log(result);
        };
</script>


//尾部删除元素,作用于原数组,返回被删除的元素。
<button id="pop-btn" type="button">pop()函数</button>
<script type="text/javascript">
        document.querySelector("#pop-btn").onclick = () => {
            let arr = [1, 2, 3];
            let result = arr.pop();
            console.log(arr);
            console.log(result);
        };
</script>


//从pos位置(包括)开始,删除len个元素,并添加元素列表(可选),返回被删除的数组,
如果没有删除任何元素,则返回空数组。
<button id="splice-delete-btn" type="button">splice()删除函数</button>
<script type="text/javascript">
        document.querySelector("#splice-delete-btn").onclick = () => {
            let arr = [1, 2, 3, 4, 5];
            let result = arr.splice(1, 3);
            console.log(arr);
            console.log(result);
        };
</script>

<button id="splice-insert-btn" type="button">splice()添加函数</button>
<script type="text/javascript">
        document.querySelector("#splice-insert-btn").onclick = () => {
            let arr = [1, 2, 5];
            let result = arr.splice(2, 0, 3, 4);
            console.log(arr);
            console.log(result);
        };
</script>

<button id="splice-update-btn" type="button">splice()修改函数</button>
<script type="text/javascript">
        document.querySelector("#splice-update-btn").onclick = () => {
            let arr = [1, 2, 4, 4, 4, 6];
            let result = arr.splice(2, 3, 3, 4, 5);
            console.log(arr);
            console.log(result);
        };
</script>


//将arrB连接到arr后,返回结果数组,不作用于原数组
<button id="concat-btn" type="button">concat()函数</button>
<script type="text/javascript">
        document.querySelector("#concat-btn").onclick = () => {
            let arrA = [1, 2, 3];
            let arrB = [3, 4, 5];
            let result = arrA.concat(arrB);
            console.log(arrA);
            console.log(arrB);
            console.log(result);
        };
</script>


//将arr的每一个元素用连接符c连接到一起,返回结果数组,不作用于原数组
<button id="join-btn" type="button">join()函数</button>
<script type="text/javascript">
        document.querySelector("#join-btn").onclick = () => {
            let arr = [1, 2, 3];
            let result = arr.join("--");
            console.log(arr);
            console.log(result);
        };
</script>


//arr升序排序,可以指定排序规则函数(返回正数为倒序),作用于原数组。
<button id="sort-btn" type="button">sort()函数</button>
<script type="text/javascript">
        document.querySelector("#sort-btn").onclick = () => {
            let arr = [3, 1, 5, 4, 2];
            let resultA = arr.sort();
            console.log(arr);
            console.log(resultA);

            let resultB = arr.sort((left, right) => right - left);
            console.log(arr);
            console.log(resultB);
        };
</script>

//在arr中正/反方向查找e的位置,不存在返回-1。
<button id="indexOf-btn" type="button">indexOf()函数</button>
<script type="text/javascript">
        document.querySelector("#indexOf-btn").onclick = () => {
            let arr = [1, 2, 3, 2, 1];
            console.log(arr.indexOf(2));
            console.log(arr.indexOf(4));
        };
</script>

<button id="lastIndexOf-btn" type="button">lastIndexOf()函数</button>
<script type="text/javascript">
        document.querySelector("#lastIndexOf-btn").onclick = () => {
            let arr = [1, 2, 3, 2, 1];
            console.log(arr.lastIndexOf(2));
            console.log(arr.lastIndexOf(4));
        };
</script>


//将arr中的每个元素都调用一次fn函数。
<button id="map-btn" type="button">map()函数</button>
<script type="text/javascript">
        document.querySelector("#map-btn").onclick = () => {
            let arr = [1, 2, 3, 4, 5];
            let result = arr.map(e => e * 2);
            console.log(arr);
            console.log(result);
        };
</script>


//对arr中的每个元素进行fn函数判断,将满足条件的元素作为一个新的数组返回。
<button id="filter-btn" type="button">filter()函数</button>
<script type="text/javascript">
        document.querySelector("#filter-btn").onclick = () => {
            let arr = [1, 2, 3, 4, 5];
            let result = arr.filter(e => e >= 3);
            console.log(arr);
            console.log(result);
        };
</script>


//对arr中的每个元素进行fn函数判断,若所有元素都满足才返回 `true`,否则返回 `false` 。
<button id="every-btn" type="button">every()函数</button>
<script type="text/javascript">
        document.querySelector("#every-btn").onclick = () => {
            let arr = [1, 2, 3, 4, 5];
            console.log(arr.every(e => e >= 3));
            console.log(arr.every(e => e >= 0));
        };
</script>


//对arr中的每个元素进行fn函数判断,只要有一个元素满足就返回 `true`,否则返回 `false`。
<button id="some-btn" type="button">some()函数</button>
<script type="text/javascript">
        document.querySelector("#some-btn").onclick = () => {
            let arr = [1, 2, 3, 4, 5];
            console.log(arr.some(e => e >= 5));
            console.log(arr.some(e => e >= 6));
        };
</script>


//从左到右/从右到左为arr中的每一个元素依次执行fn函数,每次都会将返回值赋值给fn函数的第一个参数
,最终返回累计处理的结果。
<button id="reduce-btn" type="button">reduce()函数</button>
<script type="text/javascript">
        document.querySelector("#reduce-btn").onclick = () => {
            let arr = [1, 2, 3, 4, 5];
            console.log(arr.reduce((left, right) => {
                console.log(left, right);
                return left + right;
            }));
        }; 
</script>


<button id="reduceRight-btn" type="button">reduce()函数</button>
<script type="text/javascript">
  document.querySelector("#reduceRight-btn").onclick = () => {
            let arr = [1, 2, 3, 4, 5];
            console.log(arr.reduceRight((left, right) => {
                console.log(left, right);
                return left + right;
            }));
        };
    }
 </script>

6. JSON结构

概念: JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,也是ECMAScript的一个子集,是目前最理想的数据交换语言:

  • JSON文件:JSON数据可以单独封装到 .json 文件中,该文件的编码必须为 UTF-8,且不支持添加任何注释。
  • 声明:JSON可以通过键值对存放不同类型的值:
    • let json = {"key1":value1,"key2":value2 ...}
  • 遍历:JSON因为没有角标的概念,所以只能使用 for-in 来进行遍历。
  • 操作:
    • json["key"] = value:增加或者修改元素。
    • delete json["key"]:删除元素。
  • 序列化:
    • JSON.stringify(json):将一个JSON或者数组转换为字符串,第二个参数可以指定序列化的属性列表,如果不指定默认全部属性序列化。
    • JSON.parse(str):将满足JSON格式的字符串解析成JSON数据,要求字符串中的 key 值必须带双引号。

布局:

<button id="declaration-btn" type="button">JSON声明</button>

<script type="text/javascript">
 document.querySelector("#declaration-btn").onclick = () => {
            let user = {
                "id": 9527,
                "name": "赵四",
                "gender": "男",
                "info": "亚洲舞王"
            };

            console.log(user);
            console.log(user.id);
            console.log(user.name);
            console.log(user["gender"]);
            console.log(user["info"]);
        };
</script>

<button id="for-in-btn" type="button">JSON遍历</button>

<script type="text/javascript">
 document.querySelector("#for-in-btn").onclick = () => {
            let user = {
                "id": 9527,
                "name": "赵四",
                "gender": "男",
                "info": "亚洲舞王"
            };

            for (let key in user) {
                console.log(key, ": ", user[key]);
            }
        };
</script>
   
<button id="dml-btn" type="button">JSON操作</button>

<script type="text/javascript">
 document.querySelector("#dml-btn").onclick = () => {

            let user = {
                "id": 9527,
                "name": "赵四",
                "gender": "男",
                "info": "亚洲舞王"
            };

            /*insert*/
            user["age"] = 50;
            console.log(user);

            /*update*/
            user["age"] = 52;
            console.log(user);

            /*delete*/
            delete user["age"];
            console.log(user);
        };

</script>
   
<button id="serialization-btn" type="button">JSON序列化</button>

<script type="text/javascript">
 document.querySelector("#serialization-btn").onclick = () => {

            /*all field*/
            let zhaosi = JSON.stringify({
                "name": "赵四",
                "gender": "男"
            });
            console.log(zhaosi);

            /*only name field*/
            let dajiao = JSON.stringify({
                "name": "大脚",
                "gender": "女",
                "age": 50
            }, ["name", "gender"]);
            console.log(dajiao);
        };

</script>
   
<button id="deserialization-btn" type="button">JSON反序列化</button>

<script type="text/javascript">
 document.querySelector("#deserialization-btn").onclick = () => {
            // JS中的字符串可以使用 `` 符号来避免频繁拼接。
            let zhaosiStr = `{"name":"赵四", "gender":"男"}`;
            let zhaosi = JSON.parse(zhaosiStr);
            console.log(zhaosi);
        };
</script>
   

7. ES6解构

概念: 在定义变量的同时直接从数组或JSON中取出一部分值的过程称为解构:

  • 数组按位置进行解构:let [a, b] = arr
    • 多余的变量会接收到 undefined
    • 变量支持设置默认值,如 let [a, b = 3] = arr
    • 中间位置接收可以使用空串占位,如 let [,,c] = arr
    • 支持多维数组解构,如 let [a, [b, c], d] = arr
    • 支持将剩余内容接受为不定长数组,如 let [a, ...b] = arr
  • JSON按key值进行解构:let {id, name:n} = json
    • key值允许使用 : 起别名,起别名后原名将不能再被使用。
    • 多余的key值会接收到 undefined
    • key值支持设置默认值,如 let {age = 50} = json

布局:

<button id="array-deconstruction-btn" type="button">数组解构</button>
<br/>
<script type="text/javascript">
    window.onload = () => {

        document.querySelector("#array-deconstruction-btn").onclick = () => {
            /*let arr = [1, 2, 3, 4];
            let a = arr[0];
            let b = arr[1];
            let c = arr[2];
            console.log(a, b, c);*/

            let arr = [1, 2, 3, 4];
            let [a, b, c] = arr;
            console.log(a, b, c);

            /*1, 2*/
            let [a1, b1] = [1, 2, 3];
            console.log(a1, b1);

            /*1, 2, undefined*/
            let [a2, b2, c2] = [1, 2];
            console.log(a2, b2, c2);

            /*1, 2*/
            let [a3, b3 = 3] = [1, 2];
            console.log(a3, b3);

            /*1, 3*/
            let [a4, b4 = 3] = [1];
            console.log(a4, b4);

            /*3*/
            let [, , c5] = [1, 2, 3];
            console.log(c5);

            /*1, 2, 3, 4*/
            let [a7, [b7, c7], d7] = [1, [2, 3], 4];
            console.log(a7, b7, c7, d7);

            /*1, [2, 3, 4, 5, 6]*/
            let [a6, ...b6] = [1, 2, 3, 4, 5, 6];
            console.log(a6, b6);
        };
</script>

<button id="json-deconstruction-btn" type="button">JSON解构</button>
<script type="text/javascript">
        document.querySelector("#json-deconstruction-btn").onclick = () => {
            /*let user = {
                "id": 12,
                "name": "赵四",
                "gender": "男",
                "info": "亚洲舞王"
            };

            let id = user["id"];
            let name = user["name"];
            let gender = user["gender"];
            console.log(id, name, gender);*/

            let user = {
                "id": 12,
                "name": "赵四",
                "gender": "男",
                "info": "亚洲舞王"
            };

            let {name: name01, id: id01, gender: gender01} = user;
            console.log(id01, name01, gender01);

            let {age: age02} = user;
            console.log(age02);

            let {name: name03 = "刘能", age: age03 = 50} = user;
            console.log(name03, age03);

        }
    }
 </script>