JavaScript入门到精通(十三)



本章节通过练习需要重点掌握轮播图和二级菜单的相关知识点,代码量稍稍多一些,还是需要先理清逻辑再多写几次
如果有问题欢迎及时讨论或留言

120. 修改div移动练习

解决第一次按下移动和第二次按下移动之间的间隔问题

开启定时器只控制移动,不控制速度

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box{
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
        }
    </style>
    <script>
        //w:87,s:83,a:65,d:68
        window.onload = function(){
            var box = document.getElementById("box");
            var speed = 10;
            var dir = 0;
            setInterval(function(){
                if(dir == 87){
                    box.style.top = box.offsetTop - speed + "px";
                }else if(dir == 83){
                    box.style.top = box.offsetTop + speed + "px";
                }else if(dir == 65){
                    box.style.left = box.offsetLeft - speed + "px";
                }else if(dir == 68){
                    box.style.left = box.offsetLeft + speed + "px";
                }
            },30);
            document.onkeydown = function(e){
                e = e || window.e;
                dir = e.keyCode;//给方向赋值
                if(e.shiftKey){
                    speed = 50;
                }else{
                    speed = 10;
                } 
            };
            document.onkeyup = function(){
                dir = 0;
            };
        }
    </script>
</head>
<body>
    <div id="box"></div>
</body>
</html>

在这里插入图片描述

121. 延时调用

延时调用:延时调用一个函数不马上执行,而是隔一段时间再执行且只执行一次

setTimeout( ),方法,返回Number数据类型,作为唯一标识可以停止延时调用

延时调用和定时调用实际上是可以互相代替的,在开发中可以根据需要选择

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        var num = 1;
        //定时调用
        // setInterval(function(){
            // console.log(num++);
        // },3000);

        //延时调用
        var timer = setTimeout(function(){
            alert(num++);
        },3000);
    </script>
</head>
<body>
    
</body>
</html>

在这里插入图片描述

122. 定时器的应用

为了不影响其它对象的执行,应该不同对象设置不同定时器,可以在执行动画对象obj中添加属性timer作为不同定时器的标识

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../fontawesome-free-6.2.0-web/css/all.css">
    <style>
        button{
            width: 100px;
            height: 50px;
            margin-left: 70px;
        }
        #dog{
            font-size: 50px;
            color: brown;
            margin-top: 250px;
            left: 0;
            display: inline-block;
            position:absolute;
        }
        #cat{
            font-size: 50px;
            color: orange;
            left: 0;
            position:absolute;
            top: 400px;
        }
        #flag{
            font-size: 40px;
            color: red;
            margin-left: 800px;
        }
        #des{
            font-size: 30px;
            color: red;
            margin-left: 800px;
        }
    </style>
    <script>
        window.onload = function(){
            var dog = document.getElementById("dog");
            var cat = document.getElementById("cat");
            var btn1 = document.getElementById("btn1");
            var btn2 = document.getElementById("btn2");
            var btn3 = document.getElementById("btn3");
            var btn4 = document.getElementById("btn4");
            btn1.onclick = function(){
                move(dog,"left",0,10);
            };
            btn2.onclick = function(){
                move(dog,"left",800,11);
            };
            btn3.onclick = function(){
                move(cat,"left",800,10);
            };
            btn4.onclick = function(){
                move(cat,"font-size",800,10,function(){
                    move(cat,"top",0,10,function(){
                        move(cat,"left",0,10,function(){
                            move(cat,"font-size",50,10,function(){
                                move(cat,"top",400,10);
                            });
                        });
                    });
                });
            };
        };
        // var timer;
        //move方法参数:obj执行动画对象,attr执行动画样式(如:left,top,width等),
        //target目标位置,speed速度,callback回调函数,在动画执行完毕后执行
        function move(obj, attr, target, speed, callback){
            clearInterval(obj.timer);
            var current = parseInt(getStyle(obj,attr));//获取box现在位置
            if(current > target){
                speed = - speed;
            }
            obj.timer = setInterval(function(){
                var oldvalue = parseInt(getStyle(obj,attr));//获取box原来left
                var newValue = oldvalue + speed;//在旧值基础上增加
                if((speed < 0 && newValue < target) || (speed >0 && newValue > target)){
                    newValue = target;
                }
                obj.style[attr] = newValue + "px";//将新值设置给box
                if(newValue == target){//元素移动到目标,停止动画
                    clearInterval(obj.timer);//关闭计时器
                    callback && callback();//动画执行完毕,有传回调函数则执行
                }
            },30);
        }
        function getStyle(obj,name){
        if(window.getComputedStyle){//注意window的使用,加和不加的区别
            return getComputedStyle(obj,null)[name];
        }
        else{
            return obj.currentStyle[name];
        }
    }

    </script>
</head>
<body>
    <button id="btn1">小狗向左移动</button>
    <button id="btn2">小狗向右移动</button>
    <button id="btn3">小猫向右移动</button>
    <button id="btn4">测试功能按钮</button>
    <!-- <div id="box" ></div> -->
    <i class="fas fa-dog" id="dog"></i>
    <!-- <div id="box1"></div> -->
    <i class="fas fa-cat" id="cat"></i>
    <h3 id="des">终点!!!</h1>
    <i class="fas fa-flag" id="flag"></i>
    <div style="width: 0; height: 1000px; border-left: 1px black solid; position: absolute ;left: 800px;top: 30px;"></div>
</body>
</html>

在这里插入图片描述

123. 轮播图

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <link rel="stylesheet" href="../resetstylesheet/reset.css">
    <style>
        #outer{
            width: 420px;
            height: 300px;
            margin: 50px auto;
            background-color: yellowgreen;
            padding: 10px 0;
            position: relative;
            overflow: hidden;
        }
        #imgList{
            list-style: none;
            width: 2100px;
            position: absolute;
            left: 0;
        }
        #imgList li{
            float: left;
            margin: 0 10px;
        }
        #navDiv{
            position: absolute;
            bottom: 15px;
            left: 147px;
        }
        #navDiv a{
            float: left;
            width: 15px;
            height: 15px;
            margin: 0 5px;
            background-color: red;
            opacity: 0.5; /* 设置透明效果 */
            filter: alpha(opacity=50);/* 兼容IE8透明效果 */
        }
        #navDiv a:hover{
            background-color: black;
        }
    </style>
    <script src="../tools/tools.js"></script>
    <script>
        window.onload = function(){
            var imgList = document.getElementById("imgList");
            var imgArr = document.getElementsByTagName("img");
            imgList.style.width = 420 * imgArr.length + "px";

            var outer = document.getElementById("outer");
            var navDiv = document.getElementById("navDiv");
            navDiv.style.left = (outer.offsetWidth - navDiv.offsetWidth)/2 + "px";

            var allA = document.getElementsByTagName("a");
            var index = 0;//默认显示图片的索引
            allA[index].style.backgroundColor = "black";

            for(var i=0;i<allA.length;i++){//先执行循环再执行点击事件,i已越界
                allA[i].num = i;//为每个超链接添加num属性来判断当前是那个超链接      
                allA[i].onclick = function(){
                    clearInterval(timer);//点击的时候停止自动播放
                    index = this.num;
                    // imgList.style.left = - 420 * index +"px";
                    move(imgList,"left",- 420 * index, 20,function(){
                        autoChange();//点击显示图片完毕开始自动切换
                    });
                    setA();
                };
            }

            autoChange();//自动切换图片

            //创建设置选中的a颜色的方法
            function setA(){
                if(index == imgArr.length - 1){//当最后一张时迅速回到第一张
                    index = 0;
                    imgList.style.left = 0;
                }

                for(var i=0;i<allA.length;i++){
                    allA[i].style.backgroundColor = "";//添加了内联样式,hover会失效,设置成空即默认样式
                }
                allA[index].style.backgroundColor = "black";
            };

            var timer;
            //创建自动切换图片的函数
            function autoChange(){
                timer = setInterval(function(){
                    index ++;
                    index %= imgArr.length; 
                    move(imgList,"left",- 420 * index, 20, function(){
                        setA();
                    })
                },3000);
            }
        };   
    </script>
</head>
<body>
    <div id="outer">
        <ul id="imgList">
            <li><img src="../img/1.gif"></li>
            <li><img src="../img/2.gif"></li>
            <li><img src="../img/3.gif"></li>
            <li><img src="../img/4.gif"></li>
            <li><img src="../img/5.gif"></li>
            <li><img src="../img/1.gif"></li>
        </ul>

        <div id="navDiv">
            <a href="javascript:;">1</a>
            <a href="javascript:;">2</a>
            <a href="javascript:;">3</a>
            <a href="javascript:;">4</a>
            <a href="javascript:;">5</a>
        </div>
    </div>  
</body>
</html>

在这里插入图片描述

124. 类的操作

通过style属性修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面
执行性能比较差,而且当要修改多个样式时,也不方便

可以对元素的class属性进行修改来简介改变元素的样式,这样只需修改一次即可同时修改多个样式,浏览器也只需重新渲染页面一次,使得性能提升且表现和行为进一步分离

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        .b1{
            width: 100px;
            height: 100px;
            background-color: red;
        }
        .b2{
            width: 200px;
            height: 200px;
            background-color: yellow;
        }
    </style>
    <script>
        window.onload = function(){
            var box = document.getElementById("box");
            var btn = document.getElementById("btn");
            btn.onclick = function(){
                // box.style.width = "200px";
                // box.style.height = "200px";
                // box.style.backgroundColor = "yellow";
                // box.className = "b2";
                addClass(box,"b2");
                alert(hasClass(box,"b2"));
                removeClass(box,"b2");
                toggleClass(box,"b2");
            };
        };

        //定义一个函数,用来向一个元素中添加指定的class属性值
        //参数:obj要添加class属性的元素,cn:要添加的class值
        function addClass(obj,cn){
            if(!hasClass(obj,cn)){
                obj.className += " " + cn;
            } 
        }

        //定义一个函数,用来判断一个元素中是否有指定的属性值
        //参数:obj,cn
        function hasClass(obj,cn){
            var reg = new RegExp("\\b"+cn+"\\b");
            return reg.test(obj.className);
        }

        //定义一个函数,用来删除一个元素中指定的class属性值gui
        function removeClass(obj,cn){
            var reg = new RegExp("\\b"+cn+"\\b");
            obj.className = obj.className.replace(reg,"");//属性值换成空串
        }

        //定义一个函数,用来切换class属性值,如果有则删除,没有则添加
        function toggleClass(obj,cn){
            if(hasClass(obj,cn)){
                removeClass(obj,cn);
            }else{
                addClass(obj,cn);
            }
        }
    </script>
</head>
<body>
    <button id="btn">改变div的样式</button>
    <br><br>
    <div id="box" class="b1"></div>
</body>
</html>

在这里插入图片描述

【注意】开发中能改类尽量改类,不能改类用style,使得JS和CSS足够分离

125. 二级菜单

每一个菜单都是div,当div具有collapsed这个类时,div就是折叠的状态,没有则展开

当给整个div绑定单击响应函数时,由于冒泡,点击超链接时会发生折叠,因此要给div里的span绑定单击响应函数

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>二级菜单</title>
    <link rel="stylesheet" href="../resetstylesheet/reset.css">
    <style>
        *{
            margin: 0;
            padding: 0;
            list-style-type: none;
        }
        a,img{
            border: 0;
            text-decoration: none;
        }
        body{
            font: 12px/180% Arial,Helvetica,sans-serif,"新宋体";
        }
    </style>
    <link rel="stylesheet" href="./sdmenu.css">
</head>
<script src="../tools/tools.js"></script>
<script>
    window.onload = function(){
        var menuSpan = document.querySelectorAll(".menuSpan");//获取所有menuSpan元素
        var openDiv = menuSpan[0].parentNode;//定义一个变量,保存当前打开的菜单,默认第一个
        for(var i=0;i<menuSpan.length;i++){
            menuSpan[i].onclick = function(){
                var parentDiv = this.parentNode;//this代表当前点击的span,获取当前span的父元素
                toggleMenu(parentDiv);//切换菜单的显示状态
                if(openDiv != parentDiv && !hasClass(openDiv,"collapsed")){//如果openDiv和parentDiv不相同且openDiv没有collapsed
                    // addClass(openDiv,"collapsed");//打开菜单以后,关闭之前打开的菜单
                    // toggleClass(openDiv,"collapsed");//调整为toggleClass统一处理后面过渡动画
                    toggleMenu(openDiv);
                }
                openDiv = parentDiv;//修改openDiv为当前打开的Div
            };
        }

        //用来切换菜单的折叠和显示状态
        function toggleMenu(obj){
            var begin = obj.offsetHeight;//切换类之前,获取元素的高度
                toggleClass(obj,"collapsed");//切换parentDiv的显示
                var end = obj.offsetHeight;//切换类之后,获取元素的高度
                obj.style.height = begin + "px"; //将元素高度重置为begin,内联样式优先,这样才可以执行动画过渡
                move(obj,"height",end,10,function(){
                    obj.style.height= "";//动画执行完毕,删除内联样式
                });
        }
    };
</script>
<body>
    <div id="my_menu" class="sdmenu">
        <div>
            <span class="menuSpan">在线工具</span>
            <a href="#">图像优化</a>
            <a href="#">收藏夹图标生成器</a>
            <a href="#">邮件</a>
            <a href="#">htaccess密码</a>
            <a href="#">梯度图像</a>
            <a href="#">按钮生成器</a>
        </div>
        <div class="collapsed">
            <span class="menuSpan">支持我们</span>
            <a href="#">推荐我们</a>
            <a href="#">链接我们</a>
            <a href="#">网络资源</a>
        </div>
        <div class="collapsed">
            <span class="menuSpan">合作伙伴</span>
            <a href="#">JavaScript工具包</a>
            <a href="#">CSS驱动</a>
            <a href="#">CodingForums</a>
            <a href="#">CSS例子</a>
        </div>
        <div class="collapsed">
            <span class="menuSpan">测试电流</span>
            <a href="#">Current or not</a>
            <a href="#">Current or not</a>
            <a href="#">Current or not</a>
            <a href="#">Current or not</a>
        </div>
    </div>
</body>
</html>

CSS文件:sdmenu.css

@charset "utf-8";

/* sdmenu */

div.sdmenu {
    width: 150px;
    margin: 100px auto;
    font-family: Arial, sans-serif;
    font-size: 12px;
    padding-bottom: 10px;
    background: url(../img/1.gif) no-repeat right bottom;
    color: #fff;
}

div.sdmenu div {
    background: url(../img/2.gif) repeat-x;
    overflow: hidden;
}

div.sdmenu div:first-child{
    background: url(../img/3.gif) no-repeat;
}

div.sdmenu div.collapsed{
    height: 25px;
}

div.sdmenu div span{
    display: block;
    height: 15px;
    overflow: hidden;
    padding: 5px 25px;
    font-weight: bold;
    color: white;
    background: url(../img/4.gif) no-repeat 10px center;
    cursor: pointer;
    border-bottom: 1px solid #ddd;
}

div.sdmenu div.collapsed span{
    background-image: url(../img/5.gif);
}

div.sdmenu div a{
    padding: 5px 10px;
    background: #eee;
    display: block;
    border-bottom: 1px solid #ddd;
    color: #066;
}

div.sdmenu div a.current{
    background: #ccc;
}

div.sdmenu div a:hover{
    background: #066 url(../img/6.gif) no-repeat right center;
    color: #fff;
    text-decoration: none;
}


tools工具类:tools.js

function move(obj, attr, target, speed, callback) {
    clearInterval(obj.timer);
  var current = parseInt(getStyle(obj, attr)); //获取box现在位置
    if (current > target) {
    speed = -speed;
}
    obj.timer = setInterval(function () {
    var oldvalue = parseInt(getStyle(obj, attr)); //获取box原来left
    var newValue = oldvalue + speed; //在旧值基础上增加
    if ((speed < 0 && newValue < target) || (speed > 0 && newValue > target)) {
        newValue = target;
    }
    obj.style[attr] = newValue + "px"; //将新值设置给box
    if (newValue == target) {
      //元素移动到目标,停止动画
      clearInterval(obj.timer); //关闭计时器
      callback && callback(); //动画执行完毕,有传回调函数则执行
    }
    }, 30);
}

function getStyle(obj, name) {
    if (window.getComputedStyle) {
    //注意window的使用,加和不加的区别
    return getComputedStyle(obj, null)[name];
    } else {
    return obj.currentStyle[name];
    }
}

//定义一个函数,用来向一个元素中添加指定的class属性值
//参数:obj要添加class属性的元素,cn:要添加的class值
function addClass(obj, cn) {
    if (!hasClass(obj, cn)) {
    obj.className += " " + cn;
    }
}

//定义一个函数,用来判断一个元素中是否有指定的属性值
//参数:obj,cn
function hasClass(obj, cn) {
    var reg = new RegExp("\\b" + cn + "\\b");
    return reg.test(obj.className);
}

//定义一个函数,用来删除一个元素中指定的class属性值gui
function removeClass(obj, cn) {
    var reg = new RegExp("\\b" + cn + "\\b");
  obj.className = obj.className.replace(reg, ""); //属性值换成空串
}

//定义一个函数,用来切换class属性值,如果有则删除,没有则添加
function toggleClass(obj, cn) {
    if (hasClass(obj, cn)) {
    removeClass(obj, cn);
    } else {
    addClass(obj, cn);
    }
}


在这里插入图片描述

126. JSON

JS(JavaScript Object Notation)中对象只有JS能识别,其它语言不能识别

JS对象表示法(JSON)是一个特殊格式的字符串,可以被任何语言识别,并且可以转换为任意语言中的对象

JSON和JS对象格式一样,只不过JSON字符串中的属性名必须加双引号,其它和JS语法一样
而对象中的属性名加单引号或加双引号或不加引号都可

JSON分类:
   1.对象{ }
   2.数组[ ]

JSON中允许的值:
   1.字符串
   2.数值
   3.布尔值
   4.null
   5.对象(不包括函数对象)
   6.数组

JSON字符串转换为JS对象,使用JSON工具类,该对象可以将一个JSON对象转为JS对象,也可以将JS对象转为JSON对象

JSON- ->JS:JSON.parse( )
例如:var json = ‘{“name”:“张三”,“age”:18,“gender”:“男”}’;
    var js = JSON.parse(json);

JS - - >JSON:JSON.stringify( )
例如:var obj = {name:“张三”,age:18,gender:“男”};
   var str = JSON.stringify(obj);

JSON对象在IE7及以下的浏览器中不支持
eval( ):方法,可以执行一段字符串形式JS代码返回结果,来将JSON对象转为JS对象
如果使用eval( )执行的字符串中有{ },它会将{ }当成代码块来解析,需在字符串前后各加( )

eval( )功能很强大,可以直接执行一个字符串中的JS代码,在开发中尽量不要使用
1.性能比较差
2.具有安全隐患
因此不推荐使用eval( )

如果需要兼容IE7及以下浏览器的JSON,可以引入一个外部的js文件来处理,其实质是创建JSON对象

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script src="../tools/json.js"></script>
    <script>
        var obj = {name:"张三",age:18,gender:"男"};//JS对象
        console.log(obj);

        var json = '{"name":"张三","age":18,"gender":"男"}';//JSON对象
        var arr = '[1,2,3,"hello",true]';//JSON数组
        console.log(json);

        var js = JSON.parse(json);//JSON对象转为JS对象
        console.log(js);
        console.log(js.name);

        var jsonObj = JSON.stringify(obj);//JS对象转为JSON对象
        console.log(jsonObj);

        eval("console.log('hello')");//eval()执行字符串形式JS代码
        var jsobj = eval("("+jsonObj+")");
        console.log(jsobj);
        console.log(jsobj.name);

        
    </script>
</head>
<body>
    
</body>
</html>

tools工具类:json.js

/*
 * @Author: your name
 * @Date: 2022-04-08 16:15:12
 * @LastEditTime: 2022-04-08 16:15:12
 * @LastEditors: Please set LastEditors
 * @Description: 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 * @FilePath: \web_QD\JavaScript\JavaScript\JAVAScript基础\宿主对象\BOM\js\json2.js
 */
//  json2.js
//  2016-05-01
//  Public Domain.
//  NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
//  See http://www.JSON.org/js.html
//  This code should be minified before deployment.
//  See http://javascript.crockford.com/jsmin.html

//  USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
//  NOT CONTROL.

//  This file creates a global JSON object containing two methods: stringify
//  and parse. This file is provides the ES5 JSON capability to ES3 systems.
//  If a project might run on IE8 or earlier, then this file should be included.
//  This file does nothing on ES5 systems.

//      JSON.stringify(value, replacer, space)
//          value       any JavaScript value, usually an object or array.
//          replacer    an optional parameter that determines how object
//                      values are stringified for objects. It can be a
//                      function or an array of strings.
//          space       an optional parameter that specifies the indentation
//                      of nested structures. If it is omitted, the text will
//                      be packed without extra whitespace. If it is a number,
//                      it will specify the number of spaces to indent at each
//                      level. If it is a string (such as "\t" or "&nbsp;"),
//                      it contains the characters used to indent at each level.
//          This method produces a JSON text from a JavaScript value.
//          When an object value is found, if the object contains a toJSON
//          method, its toJSON method will be called and the result will be
//          stringified. A toJSON method does not serialize: it returns the
//          value represented by the name/value pair that should be serialized,
//          or undefined if nothing should be serialized. The toJSON method
//          will be passed the key associated with the value, and this will be
//          bound to the value.

//          For example, this would serialize Dates as ISO strings.

//              Date.prototype.toJSON = function (key) {
//                  function f(n) {
//                      // Format integers to have at least two digits.
//                      return (n < 10)
//                          ? "0" + n
//                          : n;
//                  }
//                  return this.getUTCFullYear()   + "-" +
//                       f(this.getUTCMonth() + 1) + "-" +
//                       f(this.getUTCDate())      + "T" +
//                       f(this.getUTCHours())     + ":" +
//                       f(this.getUTCMinutes())   + ":" +
//                       f(this.getUTCSeconds())   + "Z";
//              };

//          You can provide an optional replacer method. It will be passed the
//          key and value of each member, with this bound to the containing
//          object. The value that is returned from your method will be
//          serialized. If your method returns undefined, then the member will
//          be excluded from the serialization.

//          If the replacer parameter is an array of strings, then it will be
//          used to select the members to be serialized. It filters the results
//          such that only members with keys listed in the replacer array are
//          stringified.

//          Values that do not have JSON representations, such as undefined or
//          functions, will not be serialized. Such values in objects will be
//          dropped; in arrays they will be replaced with null. You can use
//          a replacer function to replace those with JSON values.

//          JSON.stringify(undefined) returns undefined.

//          The optional space parameter produces a stringification of the
//          value that is filled with line breaks and indentation to make it
//          easier to read.

//          If the space parameter is a non-empty string, then that string will
//          be used for indentation. If the space parameter is a number, then
//          the indentation will be that many spaces.

//          Example:

//          text = JSON.stringify(["e", {pluribus: "unum"}]);
//          // text is '["e",{"pluribus":"unum"}]'

//          text = JSON.stringify(["e", {pluribus: "unum"}], null, "\t");
//          // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

//          text = JSON.stringify([new Date()], function (key, value) {
//              return this[key] instanceof Date
//                  ? "Date(" + this[key] + ")"
//                  : value;
//          });
//          // text is '["Date(---current time---)"]'

//      JSON.parse(text, reviver)
//          This method parses a JSON text to produce an object or array.
//          It can throw a SyntaxError exception.

//          The optional reviver parameter is a function that can filter and
//          transform the results. It receives each of the keys and values,
//          and its return value is used instead of the original value.
//          If it returns what it received, then the structure is not modified.
//          If it returns undefined then the member is deleted.

//          Example:

//          // Parse the text. Values that look like ISO date strings will
//          // be converted to Date objects.

//          myData = JSON.parse(text, function (key, value) {
//              var a;
//              if (typeof value === "string") {
//                  a =
//   /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
//                  if (a) {
//                      return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
//                          +a[5], +a[6]));
//                  }
//              }
//              return value;
//          });

//          myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
//              var d;
//              if (typeof value === "string" &&
//                      value.slice(0, 5) === "Date(" &&
//                      value.slice(-1) === ")") {
//                  d = new Date(value.slice(5, -1));
//                  if (d) {
//                      return d;
//                  }
//              }
//              return value;
//          });

//  This is a reference implementation. You are free to copy, modify, or
//  redistribute.

/*jslint
    eval, for, this
*/

/*property
    JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/

// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

if (typeof JSON !== "object") {
    JSON = {};
}

(function () {
    "use strict";

    var rx_one = /^[\],:{}\s]*$/;
    var rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g;
    var rx_three =
    /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g;
    var rx_four = /(?:^|:|,)(?:\s*\[)+/g;
    var rx_escapable =
    /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
    var rx_dangerous =
    /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;

    function f(n) {
    // Format integers to have at least two digits.
    return n < 10 ? "0" + n : n;
    }

    function this_value() {
    return this.valueOf();
    }

    if (typeof Date.prototype.toJSON !== "function") {
    Date.prototype.toJSON = function () {
        return isFinite(this.valueOf())
        ? this.getUTCFullYear() +
            "-" +
            f(this.getUTCMonth() + 1) +
            "-" +
            f(this.getUTCDate()) +
            "T" +
            f(this.getUTCHours()) +
            ":" +
            f(this.getUTCMinutes()) +
            ":" +
            f(this.getUTCSeconds()) +
            "Z"
        : null;
    };

    Boolean.prototype.toJSON = this_value;
    Number.prototype.toJSON = this_value;
    String.prototype.toJSON = this_value;
    }

    var gap;
    var indent;
    var meta;
    var rep;

    function quote(string) {
    // If the string contains no control characters, no quote characters, and no
    // backslash characters, then we can safely slap some quotes around it.
    // Otherwise we must also replace the offending characters with safe escape
    // sequences.

    rx_escapable.lastIndex = 0;
    return rx_escapable.test(string)
        ? '"' +
            string.replace(rx_escapable, function (a) {
            var c = meta[a];
            return typeof c === "string"
                ? c
                : "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
            }) +
            '"'
        : '"' + string + '"';
    }

    function str(key, holder) {
    // Produce a string from holder[key].

    var i; // The loop counter.
    var k; // The member key.
    var v; // The member value.
    var length;
    var mind = gap;
    var partial;
    var value = holder[key];

    // If the value has a toJSON method, call it to obtain a replacement value.

    if (
        value &&
        typeof value === "object" &&
        typeof value.toJSON === "function"
    ) {
        value = value.toJSON(key);
    }

    // If we were called with a replacer function, then call the replacer to
    // obtain a replacement value.

    if (typeof rep === "function") {
        value = rep.call(holder, key, value);
    }

    // What happens next depends on the value's type.

    switch (typeof value) {
        case "string":
        return quote(value);

        case "number":
        // JSON numbers must be finite. Encode non-finite numbers as null.

        return isFinite(value) ? String(value) : "null";

        case "boolean":
        case "null":
        // If the value is a boolean or null, convert it to a string. Note:
        // typeof null does not produce "null". The case is included here in
        // the remote chance that this gets fixed someday.

        return String(value);

      // If the type is "object", we might be dealing with an object or an array or
      // null.

        case "object":
        // Due to a specification blunder in ECMAScript, typeof null is "object",
        // so watch out for that case.

        if (!value) {
            return "null";
        }

        // Make an array to hold the partial results of stringifying this object value.

        gap += indent;
        partial = [];

        // Is the value an array?

        if (Object.prototype.toString.apply(value) === "[object Array]") {
          // The value is an array. Stringify every element. Use null as a placeholder
          // for non-JSON values.

            length = value.length;
            for (i = 0; i < length; i += 1) {
            partial[i] = str(i, value) || "null";
            }

          // Join all of the elements together, separated with commas, and wrap them in
          // brackets.

            v =
            partial.length === 0
                ? "[]"
                : gap
                ? "[\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "]"
                : "[" + partial.join(",") + "]";
            gap = mind;
            return v;
        }

        // If the replacer is an array, use it to select the members to be stringified.

        if (rep && typeof rep === "object") {
            length = rep.length;
            for (i = 0; i < length; i += 1) {
            if (typeof rep[i] === "string") {
                k = rep[i];
                v = str(k, value);
                if (v) {
                partial.push(quote(k) + (gap ? ": " : ":") + v);
                }
            }
            }
        } else {
          // Otherwise, iterate through all of the keys in the object.

          for (k in value) {
            if (Object.prototype.hasOwnProperty.call(value, k)) {
              v = str(k, value);
              if (v) {
                partial.push(quote(k) + (gap ? ": " : ":") + v);
              }
            }
          }
        }

        // Join all of the member texts together, separated with commas,
        // and wrap them in braces.

        v =
          partial.length === 0
            ? "{}"
            : gap
            ? "{\n" + gap + partial.join(",\n" + gap) + "\n" + mind + "}"
            : "{" + partial.join(",") + "}";
        gap = mind;
        return v;
    }
  }

  // If the JSON object does not yet have a stringify method, give it one.

  if (typeof JSON.stringify !== "function") {
    meta = {
      // table of character substitutions
      "\b": "\\b",
      "\t": "\\t",
      "\n": "\\n",
      "\f": "\\f",
      "\r": "\\r",
      '"': '\\"',
      "\\": "\\\\",
    };
    JSON.stringify = function (value, replacer, space) {
      // The stringify method takes a value and an optional replacer, and an optional
      // space parameter, and returns a JSON text. The replacer can be a function
      // that can replace values, or an array of strings that will select the keys.
      // A default replacer method can be provided. Use of the space parameter can
      // produce text that is more easily readable.

      var i;
      gap = "";
      indent = "";

      // If the space parameter is a number, make an indent string containing that
      // many spaces.

      if (typeof space === "number") {
        for (i = 0; i < space; i += 1) {
          indent += " ";
        }

        // If the space parameter is a string, it will be used as the indent string.
      } else if (typeof space === "string") {
        indent = space;
      }

      // If there is a replacer, it must be a function or an array.
      // Otherwise, throw an error.

      rep = replacer;
      if (
        replacer &&
        typeof replacer !== "function" &&
        (typeof replacer !== "object" || typeof replacer.length !== "number")
      ) {
        throw new Error("JSON.stringify");
      }

      // Make a fake root object containing our value under the key of "".
      // Return the result of stringifying the value.

      return str("", { "": value });
    };
  }

  // If the JSON object does not yet have a parse method, give it one.

  if (typeof JSON.parse !== "function") {
    JSON.parse = function (text, reviver) {
      // The parse method takes a text and an optional reviver function, and returns
      // a JavaScript value if the text is a valid JSON text.

      var j;

      function walk(holder, key) {
        // The walk method is used to recursively walk the resulting structure so
        // that modifications can be made.

        var k;
        var v;
        var value = holder[key];
        if (value && typeof value === "object") {
          for (k in value) {
            if (Object.prototype.hasOwnProperty.call(value, k)) {
              v = walk(value, k);
              if (v !== undefined) {
                value[k] = v;
              } else {
                delete value[k];
              }
            }
          }
        }
        return reviver.call(holder, key, value);
      }

      // Parsing happens in four stages. In the first stage, we replace certain
      // Unicode characters with escape sequences. JavaScript handles many characters
      // incorrectly, either silently deleting them, or treating them as line endings.

      text = String(text);
      rx_dangerous.lastIndex = 0;
      if (rx_dangerous.test(text)) {
        text = text.replace(rx_dangerous, function (a) {
          return "\\u" + ("0000" + a.charCodeAt(0).toString(16)).slice(-4);
        });
      }

      // In the second stage, we run the text against regular expressions that look
      // for non-JSON patterns. We are especially concerned with "()" and "new"
      // because they can cause invocation, and "=" because it can cause mutation.
      // But just to be safe, we want to reject all unexpected forms.

      // We split the second stage into 4 regexp operations in order to work around
      // crippling inefficiencies in IE's and Safari's regexp engines. First we
      // replace the JSON backslash pairs with "@" (a non-JSON character). Second, we
      // replace all simple value tokens with "]" characters. Third, we delete all
      // open brackets that follow a colon or comma or that begin the text. Finally,
      // we look to see that the remaining characters are only whitespace or "]" or
      // "," or ":" or "{" or "}". If that is so, then the text is safe for eval.

      if (
        rx_one.test(
          text.replace(rx_two, "@").replace(rx_three, "]").replace(rx_four, "")
        )
      ) {
        // In the third stage we use the eval function to compile the text into a
        // JavaScript structure. The "{" operator is subject to a syntactic ambiguity
        // in JavaScript: it can begin a block or an object literal. We wrap the text
        // in parens to eliminate the ambiguity.

        j = eval("(" + text + ")");

        // In the optional fourth stage, we recursively walk the new structure, passing
        // each name/value pair to a reviver function for possible transformation.

        return typeof reviver === "function" ? walk({ "": j }, "") : j;
      }

      // If the text is not JSON parseable, then a SyntaxError is thrown.

      throw new SyntaxError("JSON.parse");
    };
  }
})();

在这里插入图片描述



到此,JavaScript基础入门就结束啦!,谢谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值