zoukankan      html  css  js  c++  java
  • 三阶段课程——Day03(函数扩展:箭头函数;类class;iterator迭代器)

    1、函数扩展

      1.1、箭头函数基本用法

      主要用在回调函数中,如map、forEach等,一般不用在事件函数对象方法中。

      语法:箭头函数通过声明变量的形式去定义它(本质上是变量中存储了一个箭头函数)

    let 变量名 = ( 参数 )=>{
        ......代码块
        return 返回值
    }

      参数相关特性

    • 没有参数
    • 多个参数
    • 一个参数(有且只有一个参数,可以省略小括号)
    • 剩余参数(箭头函数没有arguments,只能使用rest接收剩余参数)
    // 没有参数
    let fn = () => {
        console.log('我是箭头函数,我执行了');
    }
    fn();
    
    // 有多个参数
    let fn1 = (a, b) => {
        return a + b;
    }
    console.log(fn1(3, 5));
    
    // 有一个参数(有且只有一个参数,可以省略小括号)
    let fn2 = a => {
        console.log('我有一个参数是:' + a);
    }
    fn2(3);
    
    // 箭头函数中没有arguments
    // 如果想获取所有的实参的集合,用rest参数
    let fn3 = (...rest) => {
        // console.log(arguments); // arguments is not defined
        console.log(rest);
    }
    fn3(3, 4, 5);

      返回值的特性

    • 完整的写法:没有省略return关键字
    • 省略return:函数中只有一行代码,且可以省略return,同时大括号也需要省略
    • 返回对象的注意事项,需要用小括号括起来
    let fn1 = () => {
        return 10;
    }
    console.log(fn1());
    
    
    let fn2 = (a, b) => {
        return a + b;
    }
    console.log(fn2(3, 5));
    
    
    // 箭头函数中只有一句代码且要返回这句代码,可以不写return,同时也不写大括号
    // let fn3 = (a, b) => {
    // return a + b;
    // }
    // console.log(fn3(4, 5));
    let fn3 = (a, b) => a + b; console.log(fn3(4, 5)); let fn4 = a => a.repeat(3); console.log(fn4('小王')); // 返回的是对象,则要将这个对象用小括号括起来 let fn5 = () => ({ name: 'zs', age: 3 }) console.log(fn5());

      不作为构造函数

      无法使用new调用箭头函数,调用会报错

      函数参数默认值

    // 如果没有传参,index为undefined,则使用默认值
    // 如果传参,则用传入的参数
    function indexOf(arr, val, index = 0) {
        for (var i = index; i < arr.length; i++) {
            if (arr[i] === val) {
                return i;
            }
        }
        return -1;
    }
    
    var arr = [3, 2, 3, 2, 32];
    console.log(indexOf(arr, 3));
    console.log(indexOf(arr, 3, 1));
    console.log(indexOf(arr, 5));

      1.2、箭头函数中的this问题

      箭头函数没有this,箭头函数的this取决于它所处的上层环境是哪个对象,那么此this就指向这个对象。普通函数可以通过事件、apply或call等改变this指向,箭头函数无法通过上面方法修改this指向。

    // 普通函数中的this:是在调用的时候确定的,不是在定义的时候确定的
    // 箭头函数中的this:是在函数定义的时候确定的(函数所处的环境是谁,this指向谁),不是在调用的时候确定的
    let fn = () => {
        console.log(this);
    }
    
    fn(); // window
    
    document.onclick = fn; // window  事件调用不能改变箭头函数的this
    
    fn.call(document); // window  call和apply也不能改变箭头函数中的this

      关于环境的补充

      只有script全局和函数内才能称为环境,对象的花括号不属于环境

    let obj = {
        fn: function () {
            console.log(this);
        },
        fn1() {
            console.log(this);
        },
        fn2: () => {
            console.log(this);
        }
    }
    
    obj.fn(); // obj
    obj.fn1(); // obj
    obj.fn2(); // window  对象的方法中,一般不用箭头函数

      1.3、箭头函数的使用场景

      场景1:

    let persons = [
        {
            username: '张飞',
            sex: '男',
            salary: 50000
        },
        {
            username: '关羽',
            sex: '男',
            salary: 60000
        }
    ]
    
    // 完整写法
    // let v = persons.map((item) => {
    //     return {
    //         ...item,
    //         salary: item.salary + 2000
    //     }
    // });
    
    // 简写
    let v = persons.map((item) => ({ ...item, salary: item.salary + 2000 })
    );
    
    console.log(v);
    console.log(persons);

      场景2:

    var cartGoods = [
        {
            goodsname: '小米10',
            price: 5000,
            isChecked: true,//代表是否选中了
        },
        {
            goodsname: '苹果10',
            price: 3000,
            isChecked: false,//代表是否选中了
        }
    ]
    
    // 完整写法
    var a = cartGoods.every((item) => {
        return item.isChecked;
    });
    
    //简写
    var a = cartGoods.every(item => item.isChecked);
    
    console.log(a);

    2、类class

      2.1、面向对象编程

        2.1.1、概念

        面向对象是一种以对象为中心的编程思想。面向对象是相对于面向过程来讲的,面向对象把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模。

        面向过程

        面向过程思想强调的是步骤,当碰见问题时,思考的是“我该怎么做”,分析出解决问题所需要的步骤,一步步的去实现。 例如:想吃蛋炒饭,首先想到的是我要如何做,包括哪些步骤。比如:起锅烧油,加入鸡蛋,加入米饭,加入调料,翻炒,装盘等。

        面向对象

        面向对象思想强调的是对象(是一个整体),当碰见问题时,思考的是“我该让谁来做”。这个“谁”其实就是对象。找合适的对象做合适的事情。而对象如何去做(采用什么样的步骤)我们就不关心了,最终把问题解决掉就可以了。

        例如:还是想吃蛋炒饭,首先想到的是让谁来帮我做蛋炒饭,比如找厨师来帮我做蛋炒饭。具体厨师如何去做这个蛋炒饭,做饭的步骤是怎么样的我们并不关心。只要最终把蛋炒饭做好就可以了。

     

        2.1.2、类和对象的关系

        现实中先有对象,根据不同的对象有着相似的特点(归为一类)

        程序中(先有类,使用类实例化对象),之前都是使用构造函数创建对象

        es5的构造函数有一些问题:方法必须加在原型上。使用function创建对象对于其它语言的工程师觉得很另类 。

     

      2.2、class的基本使用

        2.2.1、传统方式创建对象

    // 创建对象的标准模式
    // 构造函数 + 原型 = 混合模式
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    Person.prototype.showName = function () {
        console.log(this.name);
    }
    Person.prototype.showAge = function () {
        console.log(this.age);
    }
    
    let p1 = new Person('zs', 3);
    console.log(p1);

        2.2.2、ES6创建类

    class Person {
        constructor(name, age) { // 实例化的时候,此构造器函数自动调用
            this.name = name;
            this.age = age;
        }
        // 方法都是自动加到类的原型上
        showName() {
            console.log(this.name);
        }
        showAge() {
            console.log(this.age);
        }
    }
    
    let p1 = new Person('李四', 5);
    // console.log(p1);
    console.log(p1.name);
    p1.showName();

      2.3、静态属性和静态方法

      实例属性和实例方法:通过实例调用的属性和方法。

      静态属性和方法:通过构造函数访问到的属性和方法。

    // js中存在的静态方法
    // Array.isArray() Array.of()  Array.from()
    // Object.assign()  Object.keys()   Object.values()
    class Person {
        // 静态的属性和方法
        static attr = '人类';
        static eat() {
            console.log('吃东西');
        }
    
        // 构造函数上的属性和方法
        constructor(name, age) {
            this.name = name;
            this.age = age;
        }
    
        // 原型上的属性和方法
        showName() {
            console.log(this.name);
        }
        showAge() {
            console.log(this.age);
        }
    }
    
    let p1 = new Person('张三', 5);
    console.log(p1);
    
    // ---------------------
    console.log(Person.attr);
    Person.eat();

      2.4、继承

      class可以通过extends关键字实现继承,这比ES5的通过修改原型链实现继承,要清晰和方便很多。

    // 格式:class 子类 extends 父类 { }
    
    // 父类
    class Person {
        constructor(name, age) {
            this.name = name;
            this.age = age;
        }
        showName() {
            console.log(this.name);
        }
        showAge() {
            console.log(this.age);
        }
    }
    
    // 子类
    class Student extends Person {
        constructor(name, age, sex) {
            super(name, age); // 写在constructor里面第一行,可以理解为把父类的constructor调用了
            this.sex = sex;
        }
        showSex() {
            console.log(this.sex);
        }
    }
    
    let s1 = new Student('张三', 3, '男');
    console.log(s1);

      2.5、面向对象的应用场景

      对面向对象不要有负担,只要懂语法即可。我们更多的是使用面向对象思想封装的框架去写业务,而不是用面向对象思想封装框架。

        2.5.1、封装工具原理

    class JS {
        constructor() {
            this.version = '1.0.1'
        }
        Array() {
            return {
                indexOf() { },
                slice() { }
            }
        }
        Object() {
            return {
                keys() { }
            }
        }
        DOM() {
            return {
                add() {
                    console.log('我是添加方法');
                },
                delete() {
                    console.log('我是删除方法');
                }
            }
        }
    }
    
    let js = new JS();
    // console.log(js);
    
    let dom = js.DOM();
    // console.log(dom);
    dom.add();
    dom.delete();

    3、iterator迭代器

      3.1、简介

      Iterator是一种接口机制,是为各种不同的数据结构提供统一的访问(循环)机制

      现在有Array / Object / Set / Map / String / NodeList / HTMLCollection / Arguments 等多种数据结构,每种都有对应的遍历方法,所以ES6 加入了Iterator遍历器,只要拥有这个Iterator遍历器,就都可以使用for...of进行遍历,这样统一方便。(但是对象没有遍历器)

      3.2、作用

    • 为各种数据结构,提供一个统一的、简便的访问接口
    • 使得数据结构的成员能够按某种次序排列
    • ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of使用
    • Iterator是一个抽象的概念, 具体的实现 for...of / Symbol.iterator

      只要可遍历的数据结构的原型上有 Symbol.iterator属性,则此数据就可以使用for...of进行遍历。唯独Object没有。

      3.3、for...of

      遍历数组、字符串、对象

    // 以下数据类型能够被for-of循环,是因为它的原型上面都有Symbol.iterator
    
    // 循环数组
    var arr = [11, 22, 33];
    // console.log(arr);
    for (let value of arr) {
        console.log(value);
    }
    
    // 循环字符串
    var str = 'abcd';
    for (let value of str) {
        console.log(value);
    }
    
    // 循环set
    let set = new Set(['aa', 'bb', 'cc']);
    // console.log(set);
    for (let val of set) {
        console.log(val);
    }
    
    // 循环map
    let map = new Map([
        [true, 1],
        ['ab', 345],
        [null, 123]
    ])
    for (let val of map) {
        console.log(val);
    }
    
    // 循环NodeList
    let btn = document.getElementsByTagName('button');
    for (let b of btn) {
        console.log(b);
    }

      注意事项:在使用for...of遍历数据时, 要确保被遍历的数据, 拥有Iterator功能

      原生具备iterator接口的结构有:Array / Set / Map / String / NodeList / HTMLCollection / Arguments

      3.4、数组的Iterator

      数组的原型上有一个 Symbol.iterator属性,这个属性上存在一个方法

      分析:

        1、Symbol.iterator是个函数,这个函数执行完毕会返回一个指针对象

        2、指针对象有一个next方法,每调用一次next则返回一个值 { value:当前值, done:true/false }

    let arr = [11, 22, 33];
    
    // console.log(arr);
    // console.log(arr[Symbol.iterator]); // 在数组的原型上有Symbol.iterator,它是一个函数,哪我们就可以调用它
    
    let ab = arr[Symbol.iterator](); // 函数调用返回一个对象,这个对象下面有一个next()方法
    console.log(ab.next()); // next方法调用一次,返回一个对象 {value: 11, done: false}
    console.log(ab.next()); // {value: 22, done: false}
    console.log(ab.next()); // {value: 33, done: false}
    console.log(ab.next()); // {value: undefined, done: true}
    
    // ------------------------------------
    // 总结:Symbol.iterator在原型上,它是一个函数,这个函数被调用,会返回一个对象,这个对象的下面有next()方法,next()方法调用一次,就返回{value: 值, done: 是否到最后了}
    // 不断的next就可以遍历这个数组

      3.5、为对象部署iterator接口

    Object.prototype[Symbol.iterator] = function () {
        let keyArr = Object.keys(this);
        let valueArr = Object.values(this);
        let index = 0;
    
        return {
            next() {
                let arr = [keyArr[index], valueArr[index]];
                return {
                    value: arr,
                    done: index++ >= keyArr.length
                }
            }
        }
    }
    
    
    let obj = {
        name: 'zs',
        age: 3,
        sex: '男'
    }
    for (let val of obj) {
        console.log(val); // ["name", "zs"] ["age", 3] ["sex", "男"]
    }

    Part1重点:let、const、模板字符串、对象的简写、解构赋值、...运算符、箭头函数

  • 相关阅读:
    Windows Server 2019 mmc无法创建单元
    .NET 设置IE代理
    检测WebService是否存在
    C#读取图片像素
    23种设计模式之简单工厂
    WinForm笔记一:文本框只允许输入数字
    ADO.NET笔记(一)XML导入导出和数据库
    winform中文本框的一些案例
    C#中的二进制序列化和Json序列化
    文件流操作(FileStream,StreamReader,StreamWriter)
  • 原文地址:https://www.cnblogs.com/miaochaofan/p/14814772.html
Copyright © 2011-2022 走看看