Js高级函数 Three Day

145 阅读2分钟

js高级:

一.Set:

  • 永远不会有重复元素的对象: 可以理解为不重复的数组

        <script>
            const set = new Set([1, 4, 6, 7])
            set.add(1)
            set.add(4) //增加的不会重复,直接不会添加进去
            console.log(set); //输出{1,4,6,7}
        </script>
    

Set对象转为数组:

    <script>
        const set = new Set([1, 4, 6, 7])
        const arr = [...set] // 将set对象转数组
        console.log(arr); //输出[1,4,6,7]
    </script>

用set方法数组去重:

    <input type="text" />
    <ul></ul>
    <script>
        const input = document.querySelector('input');
        const ul = document.querySelector('ul');
        let arr = ['a', 'b'];
        render();
        input.addEventListener('keydown', function (event) {
            if (event.key === 'Enter') {
                // 去重处理
                const set = new Set(arr)
                set.add(this.value) //input.value
                arr = [...set]  //set对象转数组
                render();
            }
        });
        function render() {
            const html = arr.map((value) => `<li>${value}</li>`).join('');
            ul.innerHTML = html;
        }
    </script>

二.函数的四种调用模式:

根据函数内部this的指向不同,可以将函数的调用模式分成4种

  1. 函数调用模式
  2. 方法调用模式
  3. 构造函数调用模式
  4. 上下文调用模式(借用方法模式)

函数调用模式:

如果一个函数不是一个对象的属性时,就是被当做一个函数来进行调用的。此时this指向了window

    <script>
        function fuc() {
            console.log(this);// 指向window
        }
        fuc()
    </script>

方法调用模式:

当一个函数被保存为对象的一个属性时,我们称之为一个方法。当一个方法被调用时,this被绑定到当前对象

    <script>
        const obj = {
            sayHi: function () {
                console.log(this);//在方法调用模式中,this指向调用当前方法的对象。
            }
        }
        obj.sayHi()
    </script>

构造函数调用模式:

如果函数是通过new关键字进行调用的,此时this被绑定到创建出来的新对象上

    <script>
        function Person() {
            console.log(this);
        }
        Person() //this指window
        const s = new Person(1) //this指Person
        console.log(s);
    </script>

方法借用模式:

也叫上下文模式,分为 apply 与 call

call方法:

call方法可以调用一个函数,并且可以指定这个函数的this指向

    <script>
        let obj = {
            name: '小花',
            say(age, sex) {
                console.log(this.name + age + sex);
            }
        }
        let afterObj = {
            name: '小明'
        }
        obj.say(16, '女') //小花 16 女
        obj.say.call(afterObj, 18, '男')  //小明 18 男
    </script>
apply方法:

就是apply()方法接受的是一个包含多个参数的数组。而call()方法接受的是若干个参数的列表

    <script>
        let obj = {
            name: '小花',
            say(age, sex) {
                console.log(this.name + age + sex);
            }
        }
        let afterObj = {
            name: '小明'
        }
        obj.say(16, '女') //小花 16 女
        obj.say.apply(afterObj, [18, '男']) //小明 18 男
    </script>
bind方法:

**bind()**方法创建一个新的函数, 可以绑定新的函数的this指向

    <script>
        let obj = {
            name: '小花',
            say(age, sex) {
                console.log(this.name + age + sex);
            }
        }
        let afterObj = {
            name: '小明'
        }
        obj.say(16, '女') //小花 16 女
        const fuc = obj.say.bind(afterObj)
        fuc(18, '男') //小明 18 男
    </script>
</body>

三.es6 class(重点):

es6的class 的出现 基本上可以替代了es5的构造函数和原型,使之代码结构上更加简洁。

关键字:

  1. class
  2. 属性
  3. 方法
  4. 继承 extends
  5. 构造函数 constructor
  6. 方法重写 override:子类方法覆盖父类,super.父类方法()
  7. 父类的构造函数 super :子类有构造方法且使用this前,必须使用super()

es6面对对象:

    <script>
        // es6 面向对象 引出新的语法 类 class
        class Person {
            // 方法 constructor 在es6 构造函数
            // constructor 会在 new Person的时候触发
            constructor(name) {
                // console.log("开始创建对象啦");
                this.name = name;
            }

            // 直接写行为
            say() {
                console.log('say方法被调用啦 ' + this.name);
            }
        }

        // 一样new一个对象
        const p1 = new Person('悟空1');
        const p2 = new Person('悟空2');
        // console.log(p1);
        // p1.say();
        console.log(p1.say === p2.say); //true
        // 属性
        // 行为
        class SuperMan {
            constructor() {
                // 对象有什么属性都写在 这里
                this.name = '超人';
                this.color = 'blue';
            }
            // 行为
            say() {
                console.log('说话');
            }
            fly() {
                console.log('会飞');
            }
            sing() {
                console.log('唱歌');
            }
        }
    </script>

es6面对对象继承:

    <script>
        class Person {
            constructor(name) {
                this.name = name
            }
            say() {
                console.log(this.name + '18岁');
            }
        }
        // 表示学生要继承父亲
        // extends 直接就实现了继承Person的方法
        class Student extends Person {
            constructor(name, sex) {
                super(name) // 父亲的构造函数 =es5   Person.call(this,name);
                this.sex = sex
            }
        }
        const s1 = new Student('小花', '女');
        console.log(s1); //小花 女
        s1.say() //小花 18岁
        // 1 如果你写了 extends 而且还写了 constructor 那你必须要在 constructor 调用了方法 super();
        // 2 如果你只写了 extends 但是你没有写constructor 不需要管super 
  
        // 继承要继承父亲的属性和父亲的行为
        // 1 只实现了继承父亲的行为  还没有实现继承父亲的属性 (super 表示可以继承父亲的属性)
    </script>

es6三个定义方法的写法:

    <script>
        class Person {
            // 性能最好 推荐方式!! 
            say1() {
                console.log('say1');
            }
            say2 = function () {
                console.log('s2');
            };
            say3 = () => {
                console.log('s3');
            };
        }
        const p1 = new Person();
        const p2 = new Person();

        console.log(p1.say1 === p2.say1); // true p1 和 p2 say1方法是同一个-节省内存
        console.log(p1.say2 === p2.say2); // false  p1 和 p2 say2方法不是同一个-性能不好
        console.log(p1.say3 === p2.say3); // false  p1 和 p2 say3方法不是同一个-性能不好
    </script>

四.原型链:

    <script>
        // 1 创建数组的方式 有两种
        // const arr = ['a', 'b', 'c']; // 字面量 常用-直接和简单的写法

        // 2 数组 也是可以被new
        // const arr = new Array('a', 'b', 'c');
        // console.log(arr);

        function Person() { }
        const p1 = new Person();
        // 在 Person的原型上添加一个方法
        Person.prototype.show = function () {
            console.log('自己添加的方法');
        };
        // p1.show();

        // 给js内置的Array数据 原型也添加一个方法试试
        Array.prototype.show = function () {
            console.log('自定义的数组方法');
        };

        const arr = new Array('a', 'b', 'c');
        // const arr = ['a', 'b', 'c'];
        // arr.show();

        // 利用原型对象的方式,在任意的构造函数上添加想要的行为
        // 任意的构造函数 包括 自己定义的构造函数
        // 也包括 js中 -内置就有的构造函数 Array

        // arr.forEach
        // arr.push()
        // arr.map()
        // arr.filter

        // 对象的创建也分两种清空
        // const ojb={};// 字面量 常用 直接 简单
        const obj = new Object(); // 利用构造函数的方式来创建对象
        Object.prototype.show = function () {
            console.log('对象 自己的show方法');
        };
        obj.show();
    </script>

五.修改原型链:

原型链 :

  • 一个对象 它可以通过 prototype 来 找到被它继承父亲的方法
  • 如果一个对象从底层触发 可以通过 prototype 一层一层往上找到 继承的关系

作用:

  • 如果我需要给 某个数据 (字符串、数组、对象) 统一添加一个方法 ,可以直接在原型上添加
    <script>
        // //  万物皆对象
        // Object.prototype.show = function () {
        //   console.log('这个是原型上的show方法');
        // };

        // // 你看要 dom对象  大哥大
        // console.dir(document.querySelector("div"));


        //  console.log(obj);// 直接看到定义在自己身上的属性和方法 看不见定义在 原型对象上的属性和方法

        Array.prototype.forEach = function () {
            console.log("老子罢工了");
        }
        Array.prototype.map = function () {
            console.log("老子罢工了");
        }
        const arr = [1, 2, 3];
        arr.forEach(); // forEach 循环 到了你这个项目 这个知识用不了 
    </script>