前端第14天

JavaScript面向对象

一.面向对象编程

面向对象(oop)是把事务分解成一个个对象,然后有对象之间分工与合作。

三大特性:继承 封装 动态

优点:易维护,易复用,易扩展,由于面向对象有继承 封装 动态三大特性可以设计出低耦合的系统,使系统更加灵活,便于维护

缺点:性能比面向对象低

二.ES6中的类和对象

1.面向对象的思维特点

1.抽取(抽象 )对象公用的属性和行为组成(封装)成一个类(模板)

2.对类进行实例化,获得类的对象

对象由属性和方法组成:

属性:事物的特征

方法:事物的行为

2.类 class

对象是类的实例化

类泛指一大类,对象特指某一个,通过类实例化一个具体的对象

3.创建类和对象

<!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>
</head>

<body>
    <script>
        //1.创建类class 创建一个明星类
        class star {
            // constructor构造函数 可以接收传递过来的参数 同时返回实例对象 在new的时候执行
            //必须写constructor
            constructor(uname, age) {
                this.uname = uname;
                this.age = age;
            }

            //方法
            //类里面 方法之间 不用加逗号!!
            //类中方法前不用加function
            //可以传递参数
            sing(song) {
                console.log(this.uname + "会唱" + song);
            }
        }

        //2.利用类创建对象 new
        var dlrb = new star("迪丽热巴", 18);
        console.log(dlrb);
        dlrb.sing("wild");
        var ycy = new star("杨超越", 15);
        console.log(ycy);
    </script>
</body>

</html>

三.类的继承

1.子承父业!

<!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>
</head>

<body>
    <script>
        //类的继承
        class Father {
            constructor() {

            }
            money() {
                console.log(100);
            }
        }

        //子类
        class Son extends Father {

        }

        //使用 
        //可以使用父类的方法和属性
        var son = new Son();
        son.money();
    </script>
</body>

</html>

2.super关键字

<!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>super关键字</title>
</head>

<body>
    <script>
        class Father {
            constructor(x, y) {
                this.x = x;
                this.y = y;
            }

            //加法
            sum() {
                console.log("求和是:" + parseInt(this.x + this.y));
            }

            say() {
                console.log();
                return "我是father";
            }
        }

        class Son extends Father {
            constructor(x, y) {
                //调用父类的构造函数 必须在子类this之前调用
                super(x, y);
                this.x = x;
                this.y = y;
            }

            say() {
                //有返回值的方法才能被super调用
                console.log(super.say() + "'s son");
            }

            //减法
            subtract() {
                console.log("求差是:" + parseInt(this.x - this.y));
            }

        }

        var son = new Son(1, 3);
        son.sum();
        son.subtract();
        //调用子类的say方法
        //继承中的属性方法查找原则:
        // 1.继承中 如果实例化子类输出一个方法 先看子类有没有这个方法 如果有就先执行子类的
        // 2.如果子类没有 就去查找父类有没有这个方法 如果父类中有就回去执行父类这个方法(就近原则)
        son.say();
    </script>

</body>

</html>

3.三个注意点

1.在ES6中没有变量的提升 所以必须先定义类,才能通过类实例化对象。

2.类里面的共有属性和方法一定要加this才能调用

3.constructor里面的this指向实例对象,方法里面的this指向这个方法的调用者。

四.面向对象案例

tab栏切换功能

<!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>tab栏切换功能</title>
    <style>
        /* css样式部分 */
        
        * {
            margin: 0;
            padding: 0;
        }
        
        ul li {
            list-style: none;
        }
        
        main {
            width: 960px;
            height: 500px;
            border-radius: 10px;
            margin: 50px auto;
        }
        
        main h4 {
            height: 100px;
            line-height: 100px;
            text-align: center;
        }
        
        .tabsbox {
            width: 900px;
            margin: 0 auto;
            height: 400px;
            border: 1px solid lightsalmon;
            position: relative;
        }
        
        nav ul {
            overflow: hidden;
        }
        
        nav ul li {
            float: left;
            width: 100px;
            height: 50px;
            line-height: 50px;
            text-align: center;
            border-right: 1px solid #ccc;
            position: relative;
        }
        
        nav ul li.liactive {
            border-bottom: 2px solid #fff;
            z-index: 9;
        }
        
        #tab input {
            width: 80%;
            height: 60%;
        }
        
        nav ul li span:last-child {
            position: absolute;
            user-select: none;
            font-size: 12px;
            top: -18px;
            right: 0;
            display: inline-block;
            height: 20px;
        }
        
        .tabadd {
            position: absolute;
            /* width: 100px; */
            top: 0;
            right: 0;
        }
        
        .tabadd span {
            display: block;
            width: 20px;
            height: 20px;
            line-height: 20px;
            text-align: center;
            border: 1px solid #ccc;
            float: right;
            margin: 10px;
            user-select: none;
        }
        
        .tabscon {
            width: 100%;
            height: 300px;
            position: absolute;
            padding: 30px;
            top: 50px;
            left: 0px;
            box-sizing: border-box;
            border-top: 1px solid #ccc;
        }
        
        .tabscon section,
        .tabscon section.conactive {
            display: none;
            width: 100%;
            height: 100%;
        }
        
        .tabscon section.conactive {
            display: block;
        }
    </style>
</head>

<body>
    <main>
        <h4>
            Js 面向对象 动态添加标签页
        </h4>
        <div class="tabsbox" id="tab">
            <!-- tab 标签 -->
            <nav class="fisrstnav">
                <ul>
                    <li class="liactive"><span>测试1</span><span class="delete">x</span></li>
                    <li><span>测试2</span><span class="delete">x</span></li>
                    <li><span>测试3</span><span class="delete">x</span></li>
                </ul>
                <div class="tabadd">
                    <span>+</span>
                </div>
            </nav>

            <!-- tab 内容 -->
            <div class="tabscon">
                <section class="conactive">测试1</section>
                <section>测试2</section>
                <section>测试3</section>
            </div>
        </div>
    </main>
    <script src="js/tab.js"></script>
</body>

</html>

tab.js

var that;
class Tab {
    constructor(id) {
        //获取元素
        that = this;
        this.main = document.querySelector(id);
        this.add = this.main.querySelector('.tabadd');
        //li的父元素
        this.ul = this.main.querySelector('.fisrstnav ul:first-child');
        //section的父元素
        this.tabscon = this.main.querySelector('.tabscon');
        this.init();
    }

    //事件绑定 让相关的元素绑定事件
    init() {
        this.updateNode();
        this.add.onclick = this.addTab;
        for (var i = 0; i < this.lis.length; i++) {
            this.lis[i].index = i;
            this.lis[i].onclick = this.toggleTab;
            this.remove[i].onclick = this.removeTab;
            this.span[i].ondblclick = this.editTab;
            this.sections[i].ondblclick = this.editTab;
        }
    }

    //重新获取
    updateNode() {
        this.lis = this.main.querySelectorAll('li');
        this.sections = this.main.querySelectorAll('section');
        this.remove = this.main.querySelectorAll('.delete');
        this.span = this.main.querySelectorAll('.fisrstnav li span:first-child')
    }

    //切换功能
    toggleTab() {
        that.clearClass();
        this.className = 'liactive';
        that.sections[this.index].className = 'conactive';
    }

    //清除 所有
    clearClass() {
        for (var i = 0; i < this.lis.length; i++) {
            this.lis[i].className = '';
            this.sections[i].className = '';
        }
    }

    //添加功能
    addTab() {
        //先清除 在修改 排他思想
        that.clearClass();
        //创建li元素和section元素
        var li = '<li class="liactive"><span>新建窗口</span><span class="delete">x</span></li>';
        var section = '<section class="conactive">新建测试</section>';
        that.ul.insertAdjacentHTML('beforeend', li);
        that.tabscon.insertAdjacentHTML('beforeend', section);
        //添加之后 刷新一下
        that.init();
    }

    //删除功能
    removeTab(e) {
        //停止冒泡
        e.stopPropagation();
        var index = this.parentNode.index;
        //根据索引号删除对应的li和sectin
        that.lis[index].remove();
        that.sections[index].remove();
        //删除后 刷新一下
        that.init();
        //当我们删除的不是选中状态的li的时候,原来的选中状态li保持不变
        if (document.querySelector('.liactive')) return;
        //当删除了选中状态的li的时候 让他前一个li处于选中状态。
        index--;
        //手动调用点击事件
        that.lis[index] && that.lis[index].click();
    }

    //修改功能
    editTab() {
        var str = this.innerHTML;
        //双击禁止选定文字
        window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
        //添加文本框
        this.innerHTML = '<input type="text" />';
        var input = this.children[0];
        input.value = str;
        input.select(); //让文本框文字处于选中状态
        //离开文本框就把文本框里面的值给span
        input.onblur = function() {
            this.parentNode.innerHTML = this.value;
        }

        //按下回车也可以把文字的值给span
        input.onkeyup = function(e) {
            if (e.keyCode === 13) {
                //手动调用表单失去焦点事件 不需要鼠标离开操作
                this.blur();
            }
        }
    }


}

new Tab("#tab");

构造函数和原型

一.构造函数和原型

1.概述

在典型的OOP语言中(JAVA),都存在类的概念,类似对象的模板,对象是类的实例,但是在ES6以前,JS没有引入类的概念。ES6全称为ECMAScript6.0,2015.06发版。在ES6之前,对象不是由类创建的,而是用一种称为构造函数的特殊函数来定义对象和他们的特征。

2.构造函数

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

构造函数使用时注意

1.构造函数用于创建某个对象首字母要大写。

2.构造函数要和new关键字一起使用,才有意义!

new执行时做的四件事:1.在内存创建一个新的空对象。2.让this指向这个新的对象。3.执行构造函数里面的代码,给这个新对象添加属性和方法。4.返回这个新对象,所以构造函数中不需要return。

实例成员:就是构造函数内部通过this添加的成员。只能通过实例化对象访问。

静态成员:在构造函数本身上添加的成员。只能通过构造函数来访问。

3.存在问题:存在内存浪费问题

3.构造函数原型对象prototype

主要作用:共享方法

构造函数通过原型分配的函数是所有对象共享的,javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。注意这个prototype就是一个对象,这个对象的属性和方法,都会被构造函数所拥有。我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例可以共享这些方法。

一般情况下,我们的公共属性定义到构造函数里面!公共方法定义到原型对象中!

<!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>构造函数原型对象prototype</title>
</head>

<body>
    <script>
        function Star(name, age) {
            //实例成员:就是构造函数内部通过this添加的成员
            this.name = name;
            this.age = age;
        }
        //原型对象:存放公共的方法
        //公共属性 定义到构造函数中去
        Star.prototype.sing = function() {
            console.log("我会唱歌");
        }

        var ldh = new Star('刘德华', 15);
        var zxy = new Star('张学友', 18);

        //静态成员 :在构造函数本身上添加的成员。
        Star.sex = '男';
        //静态成员:只能通过构造函数来访问。
        console.log(Star.sex); //男
        console.log(ldh.sex); //undefined

        //实例成员:只能通过实例化对象访问
        console.log(ldh.name); //刘德华

        //地址值比较
        console.log(ldh.sing === zxy.sing); //true 说明原型对象prototype生效!
        ldh.sing(); //在对象身上系统自己添加一个 __proto__ 指向我们构造函数的原型对象 prototype
        console.log(ldh.__proto__ === Star.prototype); //true!
        //方法查找顺序:首先查看ldh对象身上是否有sing方法,如果有就执行这个对象上的sing方法
        // 没有的话,因为有__proto__ 的存在,就会去构造函数原型对象prototype 中找
    </script>
</body>

</html>

5.构造函数constructor

对象原型_ prpto _ 和构造函数(prototype)原型对象里面都有一个属性constructor属性,constructor我们称为构造函数,因为他指回构造函数本身。

<!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>构造函数constructor</title>
</head>

<body>
    <script>
        function Star(name, age) {
            this.name = name;
            this.age = age;
        }
        //很多情况下,需要手动利用constructor 这个属性返回原来的构造函数
        //正常情况下
        /* Star.prototype.sing = function() {
            console.log("我会唱歌");
        }
        Star.prototype.movie = function() {
            console.log("我会拍电影");
        } */

        Star.prototype = {
            // 如果我们修改了原来的原型对象,给原型对象赋值时的是以一个对象的形式,
            // 则必须加上constructor: 指回原来的构造函数,!
            constructor: Star,
            sing: function() {
                console.log("我会唱歌");
            },
            movie: function() {
                console.log("我会拍电影");
            }
        }

        var ldh = new Star('刘德华', 15);
        var zxy = new Star('张学友', 18);

        console.log(Star.prototype); //指回Star
        console.log(Star.prototype.constructor); //指回构造函数
        console.log(ldh.__proto__); //指回Star
        console.log(ldh.__proto__.constructor); //指回构造函数
    </script>
</body>

</html>

6.构造函数、实例、原型对象三者之间的关系

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JJ7x9rcj-1676954555873)(C:\Users\t-y-x\AppData\Roaming\Typora\typora-user-images\image-20230131211452330.png)]

7.原型链

<!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>
</head>
<body>
    <script>
        function Star(name, age) {
            this.name = name;
            this.age = age;
        }
        Star.prototype.sing = function() {
            console.log("我会唱歌");
        }
        var ldh = new Star('刘德华', 15);
        //只要是对象就会有 __proto__ 原型,指向原型对象
        //Star原型对象里面__proto__ 原型指向的是Object.prototype
        console.log(Star.prototype.__proto__ === Object.prototype); //true

        console.log(Object.prototype.__proto__); //null
    </script>
</body>
</html>

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pK5uKT3k-1676954555874)(C:\Users\t-y-x\AppData\Roaming\Typora\typora-user-images\image-20230131212533362.png)]

8.JavaScript的成员查找机制

按照原型链机制查找

1.当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性

2.如果没有就去查找他的原型(也就是_ _ proto _ _指向的prototype原型对象)

3.如果还没有就查找原型对象的原型(Object的原型对象)

4.以此类推一直遭到Object为止(null)

9.原型对象this指向

在构造函数中this指向的时里面的对象实例 ,在原型对象函数里面的this 指向的都是实例对象 。

10.扩展内置对象

可以通过原型对象,对原来的内置对象进行扩展自定义的方法。

<!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>
</head>

<body>
    <script>
        //原型对象的应用-扩展内置对象
        //之前没有sum
        console.log(Array.prototype);
        Array.prototype.sum = function() {
            for (var i = 0; i < this.length; i++) {
                var sum = 0;
                sum += this[i];
            }
            return sum;
        }
        var arr = [1, 5, 8, 4];

        console.log(arr.sum());
        //添加之后有了sum方法
        console.log(Array.prototype);
    </script>
</body>

</html>

二.继承

ES6之前并没有提供继承extends继承。可以通过构造函数+原型对象模拟实现继承,被称为组合继承。

1.call()

调用这个函数,并且修改函数运行时的this指向

fun.call(thisArg, arg1, arg2, …)

参数:thisArg: 当前调用函数this的指向对象。 arg1:传递的参数

<!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>call方法</title>
</head>

<body>
    <script>
        //call方法
        function fn(x, y) {
            console.log('我不想和你');
            console.log(this); //Window 改变指向后变成了o
            console.log(x + y); //3
        }

        var o = {
            name: 'andy'
        }

        //call(): 可以调用函数
        //可以改变这个函数的this指向 改变之后this指向变成了o,
        fn.call(o, 1, 2);
    </script>
</body>

</html>

2.借用构造函数继承父类型属性和方法

核心原理:通过call()把父类型的this指向子类型的this,这样可以实现子类型继承父类型的属性

<!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>
</head>

<body>
    <script>
        //借用父构造函数继承属性
        //父构造函数
        function Father(uname, age) {
            this.uname = uname;
            this.age = age;
        }

        //父元素专门的方法
        Father.prototype.money = function() {
            console.log('10000');
        }

        //子构造函数
        function Son(uname, age) {
            //this指向之构造函数的对象实例, 修改指向对象
            //实现继承Father的属性!!
            Father.call(this, uname, age);
        }

        //实例化父构造函数 
        //实现继承父类的方法!!
        Son.prototype = new Father();
        //利用对象的形式修改原型对象 ,要用constructor指回构造函数
        Son.prototype.constructor = Son;

        //这是子元素专门的方法
        Son.prototype.exam = function() {
            console.log('孩子要考试!');
        }

        var son = new Son('zi', 12);
        var fa = new Father('fa', 12);
        console.log(son);
        console.log(fa);
        console.log(Son.prototype.constructor);
        console.log(Father.prototype);
    </script>
</body>

</html>

3.类的本质

ES6的类他大部分的功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰,更加面向对象编程而已!

ES6是ES5的语法糖!

<!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>
</head>

<body>
    <script>
        //ES6之前通过构造函数+原型对象编程
        // 1.构造函数有原型对象prototype
        // 2.构造函数原型对象prototype 里面有constructor 指向构造函数本身
        // 3.构造函数可以通过原型对象添加方法
        // 4.构造函数创建的实例对象有__proto__原型指向 构造函数的原型对象

        //ES6通过类实现面向对象编程
        class Star {

        }
        console.log(typeof Star); //function
        //类的本质就是函数 可以简单以为类就是构造函数的另外一种写法
        // 1.类有原型对象prototype
        console.log(Star.prototype); //存在原型对象
        // 2.类原型对象prototype 里面有constructor 指向构造函数本身
        console.log(Star.prototype.constructor); //指向类本身
        // 3.类可以通过原型对象添加方法
        Star.prototype.sing = function() {
            console.log('冰雨');
        }
        var ldh = new Star();
        console.log(ldh); //存在sing方法
        // 4.类创建的实例对象有__proto__原型指向 构造函数的原型对象
        console.log(ldh.__proto__ === Star.prototype); //true
    </script>
</body>

</html>

三.ES5中的新增方法

1.数组方法

迭代(遍历)方法:forEach()、map()、 filter()、some()、every()

filter()、forEach() 里面return true不会终止迭代, some()里面遇到return true 就是终止遍历 迭代效率更高,所以查找唯一的元素就用some()!

<!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>
</head>

<body>
    <script>
        //forEach 迭代遍历数组
        var arr = [1, 2, 3];
        var sum = 0;
        arr.forEach(function(value, index, array) {
            console.log('每个数组元素:' + value);
            console.log('每个数组元素索引号:' + index);
            console.log('数组本身:' + array);
            sum += value;
        })
        console.log("求和是:" + sum);

        //filter()方法 :用于进行数组的筛选
        var arr1 = [11, 2, 62, 31, 48];
        var newArr = arr1.filter(function(value, index, arr) {
            //用return返回满足条件的元素 注意要写return!!!
            return value >= 20;
        })
        console.log(newArr);
    </script>
</body>

</html>
案例-查询商品
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        table {
            width: 400px;
            border: 1px solid #000;
            border-collapse: collapse;
            margin: 0 auto;
        }
        
        td,
        th {
            border: 1px solid #000;
            text-align: center;
        }
        
        input {
            width: 50px;
        }
        
        .search {
            width: 600px;
            margin: 20px auto;
        }
    </style>
</head>

<body>
    <div class="search">
        按照价格查询: <input type="text" class="start"> - <input type="text" class="end"> <button class="search-price">搜索</button> 按照商品名称查询: <input type="text" class="product"> <button class="search-pro">查询</button>
    </div>
    <table>
        <thead>
            <tr>
                <th>id</th>
                <th>产品名称</th>
                <th>价格</th>
            </tr>
        </thead>
        <tbody>
        </tbody>
    </table>
    <script>
        // 利用新增数组方法操作数据
        var data = [{
            id: 1,
            pname: '小米',
            price: 3999
        }, {
            id: 2,
            pname: 'oppo',
            price: 999
        }, {
            id: 3,
            pname: '荣耀',
            price: 1299
        }, {
            id: 4,
            pname: '华为',
            price: 1999
        }, ]

        // 获取tbody
        var tb = document.querySelector('tbody');
        var search_price = document.querySelector('.search-price');
        var start = document.querySelector('.start');
        var end = document.querySelector('.end');
        var search_pro = document.querySelector('.search-pro')
        var product = document.querySelector('.product');
        // 把数据渲染到页面中
        datas(data)

        function datas(data) {
            // 清空tbody里面的内容
            tb.innerHTML = '';
            data.forEach(function(value) {
                // 创建一个行
                var tr = document.createElement('tr');
                // 创建三个列
                tr.innerHTML = '<td>' + value.id + '</td><td>' + value.pname + '</td><td>' + value.price + '</td>';
                // 把这个行追加到tbody里面
                tb.appendChild(tr);
            })
        }

        //根据价格查询商品
        //当我们点击了按钮,就可以根据我们的商品价格去筛选数组里面的对象
        search_price.addEventListener('click', function() {
            var newDate = data.filter(function(val) {
                    return val.price >= start.value && val.price <= end.value;
                })
                //清除表单数据
            tb.innerHTML = '';
            //把数据放到表单中
            datas(newDate);
        })

        //根据商品名查找商品
        //查找数组中唯一的元素用some比较合适 因为他找到这个元素就不再进行循环了 效率高
        search_pro.addEventListener('click', function() {
            var arr = [];
            data.some(function(val) {
                if (val.pname === product.value) {
                    arr.push(val);
                    //结束some
                    return true;
                }
            });
            //渲染数据
            datas(arr);
        })
    </script>
</body>

</html>

2.字符串的方法

trim()方法 会从一个字符串的两端删除空白字符!这个方法不会影响字符串本身,返回一个新的字符串。

<!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>
</head>

<body>
    <input type="text"> <button>验证</button>
    <div></div>
    <script>
        //trim 方法去除字符串两侧的空格
        var str = '         str       ';
        console.log('加了.trim方法后的str:' + str.trim());
        console.log('原来的str:' + str);
        var input = document.querySelector('input');
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        btn.onclick = function() {
            var str = input.value.trim();
            if (str === '') {
                console.log('请输入内容!');
            } else {
                console.log(str);
                console.log(str.length);
                div.innerHTML = str;
            }

        }
    </script>
</body>

</html>

3.对象方法

1.Object.keys() 用于获取对象自身的所有属性,返回数组

2.Object.defineProperty(obj, prop, descriptor) 定义对象中新属性或修改原有属性,obj目标对象,prop需要定义或修改的属性名字,descriptor目标属性所拥有的特性,以对象形式传递 有四个参数可以设置,VUE中有用到!!!

<!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>
</head>

<body>
    <script>
        var obj = {
            id: 1,
            name: '小米',
            price: 1999,
            num: 2000
            //在对象中直接创建的属性和值 writable enumerable configurable默认值是true
            //利用defineProperty创建时writable enumerable configurable 默认值是false
        };
        //将对象中所有属性存放到数组中!
        var arr = Object.keys(obj);

        //以前的对象添加和属性修改的方式
        // obj.price = 1222;
        // obj.num = 100;

        //利用defineProperty 修改属性或添加属性 
        Object.defineProperty(obj, 'num', {
            //value:设置属性值 默认undefined
            value: 1000,
            //writable:值是否可以重写 true或者false 
            //enumerable:目标属性是否可以被枚举 true或者false 
            //configurable:目标属性是否可以被删除或者是否可以再次修改特性 true或者false 
        });
        console.log(obj);

        Object.defineProperty(obj, 'id', {
            //value:设置属性值 默认undefined
            //writable:值是否可以重写 true或者false 
            writable: false, //false不允许被修改
            //enumerable:目标属性是否可以被枚举 true或者false 
            //configurable:目标属性是否可以被删除或者是否可以再次修改特性 true或者false 
        });
        //修改id!但是上面设置不然修改 所以修改不成功
        obj.id = 10;
        console.log(obj);

        Object.defineProperty(obj, 'adress', {
            //value:设置属性值 默认undefined
            value: '上海!',
            //writable:值是否可以重写 true或者false 
            //enumerable:目标属性是否可以被枚举 true或者false 
            enumerable: false,//不会被遍历出来!
            //configurable:目标属性是否可以被删除或者是否可以再次修改特性 true或者false
            configurable: false //为false不允许被删除 
        });
        console.log(Object.keys(obj));
    </script>
</body>

</html>

函数进阶

一.函数的定义和调用

1.函数的定义方式

<!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>
</head>

<body>
    <script>
        //函数定义方式
        //自定义函数
        function fn() {

        };

        //函数表达式
        var fun = function() {

        };

        //利用new Function('参数一', '参数2', '函数体');
        //Function里面参数必须都是字符串格式的
        //这种方法效率较低 
        //所有函数都是Function的实例,函数并且也属于对象
        var f = new Function('a', 'b', 'console.log(a+b)');
        //调用
        f(1, 2);
    </script>
</body>

</html>

2.函数调用方式

<!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>
</head>

<body>
    <script>
        //1.普通函数
        function fn() {
            console.log('人生低谷');
        }

        fn();

        //2.对象方法
        var o = {
            sayHi: function() {
                console.log('人生瓶颈');
            }
        }
        o.sayHi();

        //3.构造函数
        function Star() {
            this.sing = function() {
                console.log('我会唱歌');
            }
        }
        var star = new Star();
        star.sing();

        //4.绑定点击事件 点击了btn就会调用函数
        //btn.onclick = function(){};

        //5.定时器函数 1s触发一次函数
        //setInterval(function(){}, 1000);

        //6.立即执行函数
        (function(){
            console.log("立即执行函数");
        })
    </script>
</body>

</html>

二.this

1.函数内部this的指向

这些this的指向,是当我们调用函数的时候绑定的。调用方式不同决定了this指向不同。一般指向我们的调用者!

调用方式this指向
普通函数调用window
构造函数调用实例对象 原型对象里面的方法也指向实例对象
方法调用该方法所属对象
事件绑定方法绑定事件对象
定时器函数window
立即执行函数window

2.改变函数内部this指向

常用的方法bind(),call(),apply()三种方法

call方法 调用一个对象。简单理解为调用函数的方式,但是它可以改变函数的this指向,使用这个方法后直接执行!

apply方法也可以改变this指向,使用完直接调用函数!

<!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>apply方法</title>
</head>

<body>
    <script>
        var o = {
            name: 'andy'
        }

        function fn(arr) {
            console.log(this); //andy
            console.log(arr); //pink

        }

        //调用函数 可以改变函数内部的this指向 
        //参数 必须是数组形式
        //主要应用于 数学内置对象求最大值或者最小值!
        fn.apply(o, ['pink']); //修改指向

        //例子
        var arr1 = [18, 51, 35, 74, 67, 86, 48, 56];
        var max = Math.max.apply(Math, arr1); //86
        console.log(max);
    </script>
</body>

</html>

bind方法不会调用函数。可以改变内部指向!

<!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>bind方法</title>
</head>

<body>
    <button>按钮</button>
    <script>
        var o = {
            name: 'andy'
        }

        function fn(a, b) {
            console.log(this); //andy
            console.log(a + b);
        }

        //修改指向 不调用函数
        var f = fn.bind(o, 1, 2);
        f(); //这么调用函数

        //按钮定时功能
        var btn = document.querySelector('button');
        btn.onclick = function() {
            this.disabled = true; //this指向的是btn按钮
            setTimeout(function() {
                this.disabled = false; //按钮开启
            }.bind(this), 3000); //this指向btn
        }
    </script>
</body>

</html>
案例-tab栏的应用(改进)

vscode中有!

3.call apply bind 总结

相同点:都可以改变函数内部的this指向

区别点:call和apply会调用蛤属,并且改变函数内部的this指向。call和apply 传递参数不一样,call传递参数aru1 ,aru2…的形式,apply必须用数组的形式。bind不会调用函数 ,只会改变函数内部的this指向

应用场景:call经常用于继承,apply经常和数组一起操作,但不想调用函数还想改变其内部指向就用bind方法!

三.严格模式

1.简介

JavaScript除了提供正常模式外,还提供了严格模式。ES5的严格模式是采用具有限制性的JavaScript变体的一种方式,即在严格的条件下执行js代码。在IE10以上的版本才会被支持,旧版本的浏览器中会被忽略。

目的:消除了JavaScript语法不合理、不严谨的地方、减少一些怪异行为,消除代码运行不安全的地方,提高效率,增加运行速度。

2.开启严格模式

为脚本开启严格模式

在所有语句前放一个特定的语句:‘use strict’;

<script>
    (function(){
        //开启严格模式
        'use strict'
    })();
</script>
为函数开启严格模式
<script>
    function fn(){
        'use strict';
        // 只给第一个函数添加严格模式 只有里面才是严格模式
    }

    function fun(){
        //按照普通模式执行
    }
</script>

3.严格模式的变化

变量变化

必须先声明在使用 前面加var

严格模式下this指向问题:

以前在全局作用域函数中的this指向window对象。

严格模式下全局作用域中函数中的this是undefined。

以前构造函数 不加new也可以调用,当普通函数,this指向全局对象。

严格模式下,构造函数不用new调用,this会报错。

new实例化的构造函数指向创建对象的实例。

定时器的this还是指向window。

事件、对象还是指向调用者

函数变化

不能有重名的参数

四.高阶函数

高阶函数是对其他函数进行操作的函数,他接收函数作为参数将函数作为返回值输出。此时就称之为高阶函数。

<!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>
</head>

<body>
    <script>
        //高阶函数- 函数作为参数传递 回调函数就是高级函数
        function fn(a, b, callback) {
            console.log(a + b);
            //如果callback存在就执行
            callback && callback();
        }

        fn(1, 2, function() {
            console.log('我是最后调用的');
        });
    </script>
</body>

</html>

五.闭包

1.变量作用域

全局变量:函数内部可以使用全局变量

局部变量:函数外部不可以使用全局变量

当函数执行完毕,本作用域内的局部变量会销毁

2.闭包概念

闭包指有权访问另一个函数作用域中变量的函数。闭包就是一个函数!(用return 匿名函数实现)

主要作用:延伸了变量的作用范围

<!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>
</head>

<body>
    <script>
        //闭包closure函数fn
        function fn() {
            var num = 1;
            return function() {
                //只要一个作用域访问了 另一个作用域中的局部变量就会产生闭包
                //内访问的函数称之为闭包函数
                //console.log(num);验证
            };
        }
        //在外面全局作用域 访问了局部变量num
        var f = fn();
        //f存的是fn函数中的匿名函数 
        f();
    </script>
</body>

</html>
案例-点击li打印当前索引号
<!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>案例-点击li打印当前索引号</title>
</head>

<body>
    <ul class="nav">
        <li>榴莲</li>
        <li>臭豆腐</li>
        <li>罐头</li>
        <li>披萨</li>
    </ul>
    <script>
        //点击一个小li输出当前li
        var lis = document.querySelector('.nav').querySelectorAll('li');
        //利用闭包得到当前li的索引号
        for (var i = 0; i < lis.length; i++) {
            //利用for循环创建四个立即执行函数
            //立即执行函数 称为小闭包 因为立即执行函数中任何一个函数都可以使用他的i这个变量
            (function(i) {
                lis[i].onclick = function() {
                    console.log(i);
                }
            })(i);
        }
    </script>
</body>

</html>
案例-3秒钟之后打印li的内容
<!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>案例-3秒钟之后打印li的内容</title>
</head>

<body>
    <ul class="nav">
        <li>榴莲</li>
        <li>臭豆腐</li>
        <li>罐头</li>
        <li>披萨</li>
    </ul>
    <script>
        var lis = document.querySelector('.nav').querySelectorAll('li');
        for (var i = 0; i < lis.length; i++) {
            (function(i) {
                setTimeout(function() {
                    console.log(lis[i].innerHTML);
                }, 3000)
            })(i);
        }
    </script>
</body>

</html>
案例-计算打车价格
<!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>
</head>

<body>
    <script>
        var car = (function() {
            var start = 13; //起步价
            var total = 0; //总价
            return {
                price: function(n) {
                    if (n <= 3) {
                        total = start;
                    } else {
                        total = (n - 3) * 5 + 13
                    }
                    return total;
                },
                yd: function(flag) {
                    //堵车
                    if (flag) {
                        return flag ? total + 10 : total
                    }
                }
            }
        })();
        console.log(car.price(1)); //13
        console.log(car.yd(true)); //23
        console.log(car.price(5)); //23
        console.log(car.yd(true)); //33
    </script>
</body>

</html>

3.闭包总结

闭包是一个函数(一个作用不同于可以访问到另外一个函数的局部变量)

作用:延伸变量的作用范围

六.递归

如果一个函数在调用本身就称为递归!注意加限定条件!不然会栈溢出

案例-利用递归
<!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>
</head>

<body>
    <script>
        //求阶乘
        function prop(n) {
            if (n == 1) {
                return n = 1;
            }
            return n * prop(n - 1);
        }
        console.log(prop(3));

        //斐波那契厄数列
        function fei(n) {
            while (n == 1 || n == 2) {
                return 1;
            }
            return fei(n - 1) + fei(n - 2);
        }
        console.log(fei(3)); //2

        //利用递归遍历数据
        var data = [{
            id: 1,
            name: '家电',
            goods: [{
                id: 11,
                gname: '冰箱'
            }, {
                id: 12,
                gname: '洗衣机'
            }]
        }, {
            id: 2,
            name: '服饰',
            goods: [{
                id: 13,
                gname: 'nike'
            }, {
                id: 14,
                gname: 'adidas'
            }]
        }];
        //利用foreach遍历 里面的每一个对象
        var o = {};
        function getId(json, id) {

            json.forEach(function(item) {
                if (item.id == id) {
                    o = item;

                    // console.log(item); 没有必要直接打印
                } else if (item.goods && item.goods.length > 0) { //里面应该有goods数组
                    o = getId(item.goods, id);

                }
            });
            return o;
        }

        console.log(getId(data, 1));
        console.log(getId(data, 2));
        console.log(getId(data, 11));
        console.log(getId(data, 12));
        console.log(getId(data, 13));
        console.log(getId(data, 14));
    </script>
</body>

</html>

浅拷贝和深拷贝

浅拷贝:只拷贝一层,更深层次对象级别的只拷贝引用

深拷贝:拷贝多层,每一级别的数据都会拷贝

Object.assign(拷贝到的对象,拷贝对象) ES6新增的方法可以实现浅拷贝

深拷贝

<!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>
</head>

<body>
    <script>
        //旧对象
        var obj = {
            id: 1,
            name: 'andy',
            msg: {
                age: 18
            }
        };
        
        //新对象
        var o = {

        };
        //深拷贝函数封装
        function deepCopy(newObj, oldObj) {
            for (var k in oldObj) {
                //判断属性值属于那种数据类型
                var item = oldObj[k];
                //判断值是否是数组
                if (item instanceof Array) {
                    newObj[k] = [];
                    o.color = [];
                    deepCopy(newObj[k], oldObj);
                } else if (item instanceof Object) {
                    //判断是否属于对象
                    newObj[k] = {};
                    deepCopy(newObj[k], item);
                } else {
                    //属于简单数据类型
                    newObj[k] = item;
                }
            }
        }
        deepCopy(o, obj);
        console.log(o);
    </script>
</body>

</html>

正则表达式

一.正则表达式概述

用于匹配字符串组合的模式,在JavaScript中,正则表达式也是对象,

二.正则表达式在JavaScript中的使用

<!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>正则表达式在JavaScript中的使用</title>
</head>

<body>
    <script>
        //1.利用RegExp对象来创建 正则表达式
        var regexp = new RegExp(/123/);

        //利用字面量创建 正则表达式
        var rg = /123/;

        //test 方法测试字符串是否复合正则表达式要求的规范
        console.log(rg.test(1234)); //true
        console.log(rg.test('abc')); //false
    </script>
</body>

</html>

三.正则表达式中的特殊字符

1.正则表达式的组成

一个正则表达式可以由简单的字符构成,比如/abc/,也可以由简单和特殊字符的组合,/ab*c/。其中特殊字符也被称为元字符,在正则表达式中具有特殊意义的专用符号,比如:^、$、+等。

2.边界符

^……$:一起使用能有精确匹配的意思

边界符说明
^表示匹配行首的文本,以谁开始
$表示匹配行尾的文本,以谁结束
字符类
[]表示有一系列字符可供选择,只要匹配其中一个就可以了
-表示一个范围
量词
*重复零次或更多次
+重复一次或更多次
?重复零次或一次
{n}重复n次
{n,}重复n次或更多次
{n,m}重复n到m次 中间不能有空格
<!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>
</head>

<body>
    <script>
        //正则表达式里面不需要加引号 不管是数值型还是字符串型
        //边界符
        var rg = /^abc$/; //必须是以abc开头 abc结尾
        console.log(rg.test('aabc')); //false
        console.log(rg.test('abc')); //true
        console.log(rg.test('abcabc')); //false
        console.log(rg.test('abcd')); //false
        console.log('=========================');
        //字符类
        var rg1 = /[abc]/; //只要包含abc其中一个,都会返回true
        var rg2 = /^[abc]$/ //只有是a b 或者 c 这三个字母才返回true
        console.log(rg1.test('aabc')); //true
        console.log(rg1.test('abc')); //true
        console.log(rg1.test('abcabc')); //true
        console.log(rg1.test('abcd')); //true
        console.log('=========================');
        console.log(rg2.test('a')); //true
        console.log(rg2.test('b')); //true
        console.log(rg2.test('c')); //true
        console.log(rg2.test('abcd')); //false
        console.log('=========================');
        var rg3 = /^[a-z]$/; //26个英文字母任何一个字母 都返回true
        console.log(rg3.test('a')); //true
        console.log(rg3.test('b')); //true
        console.log(rg3.test('c')); //true
        console.log(rg3.test('A')); //false
        console.log('=========================');
        //字符组合
        var rg4 = /^[a-zA-Z]$/; //26个英文字母任何一个字母不区分大小写 都返回true
        console.log(rg4.test('a')); //true
        console.log(rg4.test('b')); //true
        console.log(rg4.test(1)); //false
        console.log(rg4.test('A')); //true
        console.log('=========================');
        //ps:如果中括号里面有^ 表示取反的意思 不要和[]外面的弄混了!

        //量词符:用来设定某个模式出现的次数
        var reg5 = /^a*$/; //允许a出现0次 或者 很多次
        var reg6 = /^a+$/; //允许a出现1次 或者 很多次
        var reg7 = /^a?$/; //允许a出现1次 或者 不出现
        var reg9 = /^a{3}$/; //允许a出现3次
        var reg8 = /^a{3,}$/; //允许a出现3次以上的次数
        var reg10 = /^a{3,10}$/; //允许a出现3到10次 {3,10}中间不能有空格

        var reg11 = /^[a-zA-Z0-9_-]{3,10}$/; //允许前面的格式出现3到10次 {3,10}中间不能有空格
        console.log(reg11.test('and_red')); //true
        console.log(reg11.test('and-qwer')); //true
        console.log(reg11.test(145248)); //true
        console.log(reg11.test('AvgsyeSS')); //true
        console.log('=========================');
    </script>
</body>

</html>
案例-用户表单验证
<!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>
    <style>
        input {
            width: 100px;
            height: 15px;
        }
        
        .right {
            font-size: 11px;
            color: green;
        }
        
        .wrong {
            font-size: 11px;
            color: red;
        }
        
        .normal {
            font-size: 11px;
            color: #ccc;
        }
    </style>
</head>

<body>
    <input type="text" class="uname">
    <span class="normal">请输入用户名</span>
    <script>
        var reg = /^[a-zA-Z0-9_-]{6,13}$/;
        var uname = document.querySelector('.uname');
        var span = document.querySelector('span');
        uname.onblur = function() {
            if (reg.test(this.value)) {
                span.className = 'right';
                span.innerHTML = '用户名输入正确!';
            } else {
                span.className = 'wrong';
                span.innerHTML = '用户名输入错误!';
            }
        }
    </script>

</body>

</html>

3.括号总结

<!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>
</head>

<body>
    <script>
        //中括号 字符集合,匹配方括号中的任意字符
        var reg = /^[abc]$/; //a可以 b可以 c可以

        //大括号 量词符 里面表示重复次数
        var reg2 = /^abc{3}$/; //只让c重复三次
        console.log(reg2.test('abc')); //false
        console.log(reg2.test('abcabcabc')); //false
        console.log(reg2.test('abccc')); //true

        //小括号 表示优先级 优先计算
        var reg3 = /^(abc){3}$/; //abc重复三次
        console.log(reg3.test('abc')); //false
        console.log(reg3.test('abcabcabc')); //true
        console.log(reg3.test('abccc')); //false
    </script>
</body>

</html>

在线测试工具:https://c.runoob.com/

4.预定义类

指某些常见的格式简写

预定义类说明
\d匹配0-9之间的任意数字,相当于[0-9]
\D匹配0-9以外的任意数字,相当于[ ^ 0-9 ]
\w匹配任意的字母、数字和下划线,相当于[A-Za-z0-9_]
\W匹配任意的字母、数字和下划线以外的字符,相当于[ ^ A-Za-z0-9_]
\s匹配空格(包括换行符、制表符、空格符等),相当于[\t\r\n\v\f]
\S匹配非空格的字符,相当于[ ^ \t\r\n\v\f]
案例-号码验证
<!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>
</head>

<body>
    <script>
        //座机号码
        var reg = /^\d{3}-\d{8} | \d{4}-\d{7}$/;

        //手机号码
        var phone = /^1[3|4|5|6|7|8]\d{9}$/;

        //qq号
        var qq = /^[1-9]\d{4,10}$/;
    </script>
</body>

</html>

四.正则表达式中的替换

1.replace替换

replace()方法可以实现替换字符串的操作,用来替换的参数可以是一个字符串或是一个正则表达式。

格式:stringObject.replace(regexp/substr, replacement);

第一个参数:被替换掉字符串或者正则表达式

第二个参数:替换为的字符串

返回值是一个替换完毕的新的字符串

<!DOCTYPE html>
<html lang="en">
 
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>替换关键字</title>
    <style>
        textarea {
            width: 300px;
            height: 100px;
            border: 1px solid #ccc;
        }
    </style>
</head>
 
<body>
    <textarea name="" id="message"></textarea> <button>提交</button>
    <div></div>
    <script>
        var text = document.querySelector('textarea');
        var btn = document.querySelector('button');
        var div = document.querySelector('div');
        btn.onclick = function () {
            //替换敏感词 激情,gay 为 **
            div.innerHTML = text.value.replace(/激情|gay/g, '**');
        }
    </script>
</body>
 
</html>

2.正则表达式参数

格式:/正则表达式/[switch]

switch(也称为修饰符)按照什么样的模式来匹配 有三种值:

g:全局匹配

i:忽略大小写

gi:全局匹配+忽略大小写

ES6

一.概述

ES全称ECMAScript,是由ECMA国际标准化组织,制订的一项脚本语言的标准化规范,6是版本号!

ES6是一个泛指,指ES2015及其后续的版本。

二.ES6新增语法

1.let

ES6中新增的用于声明变量关键字,let声明的变量只在 处于的块级({}就是大括号)中有效。

特点:

1.防止循环变量变成全局变量

2.不存在变量提升,变量得先声明在使用!

3.暂时性死区

2.const

用来声明常量,常量就是值(内存地址)不能变化的量。

特点:

1.具有块级作用域

2.声明时必须给初始值

3.常量赋值后不能更改!(基本数据类型值不能被更改,复杂数据类型数组数据结构内部的值可以更改,数据值本身不能更改)

3.var、let、const区别

varletconst
函数级作用域块级作用域块级作用域
变量提升不存在变量提升不存在变量提升
值可以更改值可以更改值不能更改

4.解构赋值

ES6中允许从数组中提取值,按照对应位置,对变量赋值。对象也可以实现解构。更加简便的从数组中提取值

数组解构

允许我们按照一一对应的关系从数组中提取值 然后赋值给变量

<!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>
</head>

<body>
    <script>
        //ES6新增
        //定义数组 
        let [a, b, c, d, e] = [1, 2, 3];
        //直接取值
        console.log(a); //1
        console.log(b); //2
        console.log(c); //3
        console.log(d); //undefined
        console.log(e); //undefined
    </script>
</body>

</html>
对象解构

允许我们使用变量的名字匹配对象的属性,匹配成功将对象的值赋值给变量

<!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>
</head>

<body>
    <script>
        //对象
        let person = {
            name: '张三',
            age: 20
        };
        //对象解构 方式一
        let {
            name,
            age,
            sex
        } = person;
        console.log(name); //张三
        console.log(age); //20
        console.log(sex); //undefined 未定义的显示undefined

        //方式二
        let {
            //左边用于属性匹配 右边是真正的解构变量名
            name: myName,
            age: myAge
        } = person;
        console.log(myName);
        console.log(myAge);
    </script>
</body>

</html>

5.箭头函数

ES6中新增的定义函数的方式!

<!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>
</head>

<body>
    <script>
        //正常形式
        const fun = () =>{
            console.log(123);
        }
        fun();

        //当{}中语句只有一句时 {}可以省略! 
        const fn = (x, y) => x + y;
        console.log(fn(1, 3));

        //但小括号中的参数只有一个时 ()也可以省略
        const f = v => v;
        console.log(f(20));
    </script>
</body>

</html>

箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this

<!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>箭头函数中的this</title>
</head>

<body>
    <script>
        function fn() {
            console.log(this);
            return ()=>{
                console.log(this);
            }
        }

        const obj = {
            name: 'zhangsan'
        };
        fn.call(obj); //obj
        const resFn = fn.call(obj);
        resFn(); //obj
    </script>
</body>

</html>
箭头函数面试题
<!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>
</head>

<body>
    <script>
        var age = 100;
        var obj = {
            age: 20,
            say: () => {
                //箭头函数 this弹出的对象是window中的对象所以是100 不是20!
                alert(this.age);
            }
        }
        obj.say(); //100
    </script>
</body>

</html>

6.剩余参数

剩余参数语法允许我们将一个不定数量的参数表示为一个数组。

<!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>
</head>

<body>
    <script>
        //剩余参数的基本使用
        const sum = (...args) => {
            let total = 0;
            args.forEach(item => {
                total += item;
            })
            return total;
        };
        console.log(sum(10, 20, 30));
        console.log(sum(10, 20));

        //剩余参数和解构一起使用
        let arr = ['张三', '李四', '王五'];
        let [s1, ...s2] = arr;
        console.log(s1); //张三
        console.log(s2); //一个数组Array(2)包含 李四和王五
    </script>
</body>

</html>

三.ES6的内置对象扩展

1.Array的扩展方法

拓展运算符…

可以将数组或者对象转为逗号分隔的参数序列

<!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>
</head>

<body>
    <div>1</div>
    <div>2</div>
    <div>3</div>
    <div>4</div>
    <div>5</div>
    <div>6</div>
    <div>7</div>
    <div>8</div>
    <script>
        //扩展运算符可以将数组拆分成为以逗号分割的参数序列
        let arr = ['a', 'b', 'c'];
        //...扩展运算符! 可以把arr数组的参数 按逗号分开
        console.log(...arr); //a b c

        //扩展运算符可以运用在合并数组上
        let arr1 = [1, 2, 3];
        let arr2 = [4, 5, 6];
        //方式一
        let arr3 = [...arr1, ...arr2];
        console.log(arr3); //(6) [1, 2, 3, 4, 5, 6]

        //方式二  合并数组    
        arr1.push(...arr2);
        console.log(arr1); //(6) [1, 2, 3, 4, 5, 6]

        //将伪数组转换为 数组
        //目地:让伪数组能使用数组的一些方法
        var oDivs = document.getElementsByTagName('div');
        console.log(oDivs); //HTMLCollection(8) [div, div, div, div, div, div, div, div]
        var arrs = [...oDivs];
        console.log(arrs); //(8) [div, div, div, div, div, div, div, div]
    </script>
</body>

</html>
Array.from(要转换的伪数组, 函数)

将伪数组或可遍历对象转换为真正的数组,

<!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>Array.from(要转换的伪数组, 函数)</title>
</head>

<body>
    <script>
        //伪数组
        var arrayLike = {
            "0": 1,
            "1": 2,
            "length": 2
        }
        //第一个参数是要改变的数组 
        //第二个参数是 对变化的数组元素的变化
        var ary = Array.from(arrayLike, item => item * 2);
        console.log(ary); //(2) [2, 4]
    </script>
</body>

</html>
find(函数限定条件)

用于找出第一个符合条件的数组成员,没有找到返回underfined

<!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>find(函数限定条件)</title>
</head>

<body>
    <script>
        var ary = [{
            id: 1,
            name: '张三'
        }, {
            id: 2,
            name: '李四'
        }, {
            id: 3,
            name: '王五'
        }]

        let target = ary.find(item => item.id == 2);
        let target1 = ary.find(item => item.id == 4);

        console.log(target); //{id: 2, name: '李四'}
        console.log(target1); //undefined
    </script>
</body>

</html>
findIndex(函数限定条件)

用于查找第一个符合条件的数组成员的位置,找不到返回-1

<!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>findIndex(函数限定条件)</title>
</head>

<body>
    <script>
        let arr = [10, 20, 50];
        //返回满座()里面条件的数组元素索引
        let index = arr.findIndex(item => item > 15);
        console.log(index);
    </script>
</body>

</html>
includes(查找的值)

检查数组是否包含给定的值,返回是布尔值

<!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>includes(查找的值)</title>
</head>

<body>
    <script>
        let arr = ['a', 'b', 'c'];
        //查找()里面的元素有就返回true 没有返回false
        let result = arr.includes('a');
        let result1 = arr.includes('f');
        console.log(result); //true
        console.log(result1); //false
    </script>
</body>

</html>

2.String的拓展方法

模板字符串

ES6新增的创建支付喜欢的方式,使用反引号定义。

特点:可以解析变量,可以换行,模板字符串可以调用函数

<!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>
</head>

<body>
    <span></span>
    <script>
        //注意用的是 反引号` 使用的时候用${}取值
        let name = `这是一个模板字符串`;
        let sayHello = `Hello ${name}`;
        console.log(sayHello);

        //模板字符串可以换行
        let result = {
            name: "zhangsan",
            age: 20
        }

        let html = `
            <div>
                <span>${result.age}</span>
                <span>${result.name}</span>
            </div>
        `;
        console.log(html);

        //模板字符串可以调用函数
        const fn = () => {
            return '我是fn函数';
        }
        let html1 = `调用函数 ${fn()}`;
        console.log(html1);
    </script>
</body>

</html>
startsWith(‘字符串’)和endsWith(‘字符串’)

判断参数字符串是否在源字符串的头部/尾部,返回布尔值:满足true或者不满足false

<!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>startsWith('字符串')和endsWith('字符串')</title>
</head>

<body>
    <script>
        let str = 'hello ECMAScript 2015';
        //中间传入字符串!
        let flag = str.startsWith('hello');
        let flag1 = str.endsWith('2015');
        console.log(flag); //true
        console.log(flag1); //true
    </script>
</body>

</html>
repeat(n)

该方法表示把原字符串重复n次!

<!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>repeat(n)</title>
</head>

<body>
    <script>
        let str = "y".repeat(5);
        console.log(str);
    </script>
</body>

</html>

3.Set数据结构

ES6提供了新的数据结构Set 。类似于数组,成员的值都是唯一的,没有重复的值。Set本身是一个构造函数,用来生成Set数据结构。Set函数可以接受数组作为参数,用来初始化

<!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>Set数据结构</title>
</head>

<body>
    <script>
        const s1 = new Set();
        //创建成功 s1.size长度是0
        console.log(s1.size); //0
        const s2 = new Set([1, 2, 3, 4]);
        console.log(s2.size); //4
        const s3 = new Set(["a", "a", "b", "b"]);
        console.log(s3); //Set(2) {'a', 'b'} 会自动去掉重复的 
        const ary = [...s3]; //转换为数组!
        console.log(ary); //(2) ['a', 'b']
    </script>
</body>

</html>
Set常用实例方法
实例方法
add(value)添加某个值,返回Set结构本身
delete(value)删除某个值,返回一个布尔值,true成功
has(value)返回一个布尔值,表示该值是否为Set的成员
clear()清除所有成员,没有返回值
<!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>Set常用实例方法</title>
</head>

<body>
    <script>
        const s = new Set();
        //先s中添加值 用add方法
        s.add('a').add('b');
        console.log(s); //Set(2) {'a', 'b'}
        //删除set中的值 用delete方法
        const f = s.delete('a');
        console.log(f); //true删除成功 
        console.log(s); //Set(1) {'b'}
        //检查元素是否在集合中
        const f1 = s.has('a');
        console.log(f1); //false a不是s中的成员

        //清空set值
        s.clear();
        console.log(s.size); //0 清空完毕
    </script>
</body>

</html>
Set的遍历

Set结构的实例和数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。
dth, initial-scale=1.0">
startsWith(‘字符串’)和endsWith(‘字符串’)

```
repeat(n)

该方法表示把原字符串重复n次!

<!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>repeat(n)</title>
</head>

<body>
    <script>
        let str = "y".repeat(5);
        console.log(str);
    </script>
</body>

</html>

3.Set数据结构

ES6提供了新的数据结构Set 。类似于数组,成员的值都是唯一的,没有重复的值。Set本身是一个构造函数,用来生成Set数据结构。Set函数可以接受数组作为参数,用来初始化

<!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>Set数据结构</title>
</head>

<body>
    <script>
        const s1 = new Set();
        //创建成功 s1.size长度是0
        console.log(s1.size); //0
        const s2 = new Set([1, 2, 3, 4]);
        console.log(s2.size); //4
        const s3 = new Set(["a", "a", "b", "b"]);
        console.log(s3); //Set(2) {'a', 'b'} 会自动去掉重复的 
        const ary = [...s3]; //转换为数组!
        console.log(ary); //(2) ['a', 'b']
    </script>
</body>

</html>
Set常用实例方法
实例方法
add(value)添加某个值,返回Set结构本身
delete(value)删除某个值,返回一个布尔值,true成功
has(value)返回一个布尔值,表示该值是否为Set的成员
clear()清除所有成员,没有返回值
<!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>Set常用实例方法</title>
</head>

<body>
    <script>
        const s = new Set();
        //先s中添加值 用add方法
        s.add('a').add('b');
        console.log(s); //Set(2) {'a', 'b'}
        //删除set中的值 用delete方法
        const f = s.delete('a');
        console.log(f); //true删除成功 
        console.log(s); //Set(1) {'b'}
        //检查元素是否在集合中
        const f1 = s.has('a');
        console.log(f1); //false a不是s中的成员

        //清空set值
        s.clear();
        console.log(s.size); //0 清空完毕
    </script>
</body>

</html>
Set的遍历

Set结构的实例和数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

来地球玩啊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值